Added double precision above 1000m and kinematics below 1000m

This commit is contained in:
2026-02-18 12:57:07 +00:00
parent e48b4e1b81
commit 3eb5c75f99
2 changed files with 84 additions and 10 deletions

View File

@@ -211,7 +211,7 @@ MeshCollider:
m_Bits: 0 m_Bits: 0
m_LayerOverridePriority: 0 m_LayerOverridePriority: 0
m_IsTrigger: 0 m_IsTrigger: 0
m_ProvidesContacts: 0 m_ProvidesContacts: 1
m_Enabled: 1 m_Enabled: 1
serializedVersion: 5 serializedVersion: 5
m_Convex: 0 m_Convex: 0
@@ -1609,6 +1609,8 @@ MonoBehaviour:
mainEngine: {fileID: 1437557825} mainEngine: {fileID: 1437557825}
rb: {fileID: 1172921199} rb: {fileID: 1172921199}
altimeter: {fileID: 894314916} altimeter: {fileID: 894314916}
physicsTransitionAltitude: 1000
useUnityPhysics: 1
--- !u!54 &1172921199 --- !u!54 &1172921199
Rigidbody: Rigidbody:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1635,7 +1637,7 @@ Rigidbody:
m_IsKinematic: 0 m_IsKinematic: 0
m_Interpolate: 0 m_Interpolate: 0
m_Constraints: 0 m_Constraints: 0
m_CollisionDetection: 2 m_CollisionDetection: 0
--- !u!65 &1172921200 --- !u!65 &1172921200
BoxCollider: BoxCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1652,7 +1654,7 @@ BoxCollider:
m_Bits: 0 m_Bits: 0
m_LayerOverridePriority: 0 m_LayerOverridePriority: 0
m_IsTrigger: 0 m_IsTrigger: 0
m_ProvidesContacts: 0 m_ProvidesContacts: 1
m_Enabled: 1 m_Enabled: 1
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1} m_Size: {x: 1, y: 1, z: 1}

View File

@@ -13,17 +13,86 @@ public class RocketPhysics : MonoBehaviour
public DoublePrecisionVector3 velocity; public DoublePrecisionVector3 velocity;
public DoublePrecisionVector3 rotation; public DoublePrecisionVector3 rotation;
// Start is called once before the first execution of Update after the MonoBehaviour is created [Header("Physics Mode Settings")]
public float physicsTransitionAltitude = 1000f; // meters - switch to Unity physics below this
public bool useUnityPhysics = true; // current physics mode
private Vector3 lastPhysicsPosition;
void Start() void Start()
{ {
position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z); position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z);
velocity = new DoublePrecisionVector3(rb.linearVelocity.x, rb.linearVelocity.y, rb.linearVelocity.z); velocity = new DoublePrecisionVector3(rb.linearVelocity.x, rb.linearVelocity.y, rb.linearVelocity.z);
rotation = new DoublePrecisionVector3(rb.rotation.eulerAngles.x, rb.rotation.eulerAngles.y, rb.rotation.eulerAngles.z); rotation = new DoublePrecisionVector3(rb.rotation.eulerAngles.x, rb.rotation.eulerAngles.y, rb.rotation.eulerAngles.z);
rb.useGravity = false;
lastPhysicsPosition = rb.position;
} }
// Update is called once per frame void FixedUpdate()
void Update()
{ {
// Determine which physics mode to use
bool shouldUseUnityPhysics = altimeter.altitude < physicsTransitionAltitude;
// Handle mode transition
if (shouldUseUnityPhysics != useUnityPhysics)
{
TransitionPhysicsMode(shouldUseUnityPhysics);
}
if (useUnityPhysics)
{
UpdateWithUnityPhysics();
}
else
{
UpdateWithDoublePrecision();
}
}
void TransitionPhysicsMode(bool toUnityPhysics)
{
if (toUnityPhysics)
{
// Transitioning to Unity physics (descending)
rb.isKinematic = false;
rb.position = new Vector3((float)position.x, (float)position.y, (float)position.z);
rb.linearVelocity = new Vector3((float)velocity.x, (float)velocity.y, (float)velocity.z);
lastPhysicsPosition = rb.position;
}
else
{
// Transitioning to double precision (ascending)
rb.isKinematic = true;
position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z);
velocity = new DoublePrecisionVector3(rb.linearVelocity.x, rb.linearVelocity.y, rb.linearVelocity.z);
}
useUnityPhysics = toUnityPhysics;
Debug.Log($"Physics mode switched to: {(useUnityPhysics ? "Unity Physics" : "Double Precision")}");
}
void UpdateWithUnityPhysics()
{
// Use Unity's physics engine - allows ground interaction
double gravityAcceleration = altimeter.gh;
Vector3 gravityForce = new Vector3(0, (float)(-gravityAcceleration * rb.mass), 0);
Vector3 thrustDirection = rb.rotation * Vector3.up;
Vector3 thrustForce = thrustDirection * mainEngine.thrust;
rb.AddForce(gravityForce, ForceMode.Force);
rb.AddForce(thrustForce, ForceMode.Force);
// Update double precision tracking from Unity physics
position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z);
velocity = new DoublePrecisionVector3(rb.linearVelocity.x, rb.linearVelocity.y, rb.linearVelocity.z);
rotation = new DoublePrecisionVector3(rb.rotation.eulerAngles.x, rb.rotation.eulerAngles.y, rb.rotation.eulerAngles.z);
}
void UpdateWithDoublePrecision()
{
// Manual double-precision integration - no ground interaction
double gravityAcceleration = altimeter.gh; double gravityAcceleration = altimeter.gh;
double thrustAcceleration = mainEngine.thrust / rb.mass; double thrustAcceleration = mainEngine.thrust / rb.mass;
@@ -36,11 +105,14 @@ public class RocketPhysics : MonoBehaviour
); );
DoublePrecisionVector3 totalAcceleration = gravityAccelerationVector + thrustAccelerationVector; DoublePrecisionVector3 totalAcceleration = gravityAccelerationVector + thrustAccelerationVector;
velocity = velocity + totalAcceleration * Time.deltaTime; velocity = velocity + totalAcceleration * Time.fixedDeltaTime;
position = position + velocity * Time.deltaTime; position = position + velocity * Time.fixedDeltaTime;
rb.position = new Vector3((float)position.x, (float)position.y, (float)position.z); // Update Unity transform (kinematic mode)
rb.linearVelocity = new Vector3((float)velocity.x, (float)velocity.y, (float)velocity.z); Vector3 newPosition = new Vector3((float)position.x, (float)position.y, (float)position.z);
rb.position = newPosition;
// Do not set linearVelocity for kinematic bodies
// rb.linearVelocity = new Vector3((float)velocity.x, (float)velocity.y, (float)velocity.z);
rb.rotation = Quaternion.Euler((float)rotation.x, (float)rotation.y, (float)rotation.z); rb.rotation = Quaternion.Euler((float)rotation.x, (float)rotation.y, (float)rotation.z);
} }
} }