Numerous improvments to the engine & physics system (thrust arrown, freezing, gimbal, etc...)
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
"name": "Move",
|
"name": "Move",
|
||||||
"type": "Value",
|
"type": "Value",
|
||||||
"id": "701d83ea-56bd-4dbb-86c8-ba6b2fea3af1",
|
"id": "701d83ea-56bd-4dbb-86c8-ba6b2fea3af1",
|
||||||
"expectedControlType": "Vector2",
|
"expectedControlType": "Vector3",
|
||||||
"processors": "",
|
"processors": "",
|
||||||
"interactions": "",
|
"interactions": "",
|
||||||
"initialStateCheck": true
|
"initialStateCheck": true
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
{
|
{
|
||||||
"name": "WASD",
|
"name": "WASD",
|
||||||
"id": "51492236-360c-4bbe-b388-38d0353c387a",
|
"id": "51492236-360c-4bbe-b388-38d0353c387a",
|
||||||
"path": "2DVector",
|
"path": "3DVector",
|
||||||
"interactions": "",
|
"interactions": "",
|
||||||
"processors": "",
|
"processors": "",
|
||||||
"groups": "",
|
"groups": "",
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
"isPartOfComposite": false
|
"isPartOfComposite": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "up",
|
"name": "Up",
|
||||||
"id": "0293c1d3-b1a3-454e-bc68-fc94cca3048b",
|
"id": "0293c1d3-b1a3-454e-bc68-fc94cca3048b",
|
||||||
"path": "<Keyboard>/w",
|
"path": "<Keyboard>/w",
|
||||||
"interactions": "",
|
"interactions": "",
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
"isPartOfComposite": true
|
"isPartOfComposite": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "down",
|
"name": "Down",
|
||||||
"id": "75b35661-ce4e-4133-afe7-636d5a48e463",
|
"id": "75b35661-ce4e-4133-afe7-636d5a48e463",
|
||||||
"path": "<Keyboard>/s",
|
"path": "<Keyboard>/s",
|
||||||
"interactions": "",
|
"interactions": "",
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
"isPartOfComposite": true
|
"isPartOfComposite": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "left",
|
"name": "Left",
|
||||||
"id": "7b679c97-20c2-45d4-8480-6e333d9fb12a",
|
"id": "7b679c97-20c2-45d4-8480-6e333d9fb12a",
|
||||||
"path": "<Keyboard>/a",
|
"path": "<Keyboard>/a",
|
||||||
"interactions": "",
|
"interactions": "",
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
"isPartOfComposite": true
|
"isPartOfComposite": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "right",
|
"name": "Right",
|
||||||
"id": "7fed79ba-720c-4f6d-a48d-e0f990cb4f34",
|
"id": "7fed79ba-720c-4f6d-a48d-e0f990cb4f34",
|
||||||
"path": "<Keyboard>/d",
|
"path": "<Keyboard>/d",
|
||||||
"interactions": "",
|
"interactions": "",
|
||||||
@@ -101,6 +101,28 @@
|
|||||||
"isComposite": false,
|
"isComposite": false,
|
||||||
"isPartOfComposite": true
|
"isPartOfComposite": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Forward",
|
||||||
|
"id": "8f905a6e-4d1c-41dd-a38c-c0ac7eb2baa6",
|
||||||
|
"path": "<Keyboard>/q",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Backward",
|
||||||
|
"id": "bbe2daf5-32ea-448d-b8a3-a48f5aacd1be",
|
||||||
|
"path": "<Keyboard>/e",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "",
|
||||||
"id": "7136f4c4-0885-41a2-8ae2-4386402979ee",
|
"id": "7136f4c4-0885-41a2-8ae2-4386402979ee",
|
||||||
|
|||||||
@@ -1412,8 +1412,11 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: '::'
|
m_EditorClassIdentifier: '::'
|
||||||
throttleAction: {fileID: -5533345291228272259, guid: c56ea0479fd0f296da411bf82c2c21a0, type: 3}
|
throttleAction: {fileID: -5533345291228272259, guid: c56ea0479fd0f296da411bf82c2c21a0, type: 3}
|
||||||
|
attitudeAction: {fileID: 7066772054865228084, guid: c56ea0479fd0f296da411bf82c2c21a0, type: 3}
|
||||||
rampSpeed: 1
|
rampSpeed: 1
|
||||||
|
attitudeResponseSpeed: 1
|
||||||
mainEngine: {fileID: 1437557825}
|
mainEngine: {fileID: 1437557825}
|
||||||
|
gimbalSystem: {fileID: 1437557827}
|
||||||
throttleDisplay: {fileID: 348618513}
|
throttleDisplay: {fileID: 348618513}
|
||||||
--- !u!114 &986986473
|
--- !u!114 &986986473
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@@ -1607,10 +1610,15 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: '::'
|
m_EditorClassIdentifier: '::'
|
||||||
mainEngine: {fileID: 1437557825}
|
mainEngine: {fileID: 1437557825}
|
||||||
|
gimbalSystem: {fileID: 1437557827}
|
||||||
rb: {fileID: 1172921199}
|
rb: {fileID: 1172921199}
|
||||||
altimeter: {fileID: 894314916}
|
altimeter: {fileID: 894314916}
|
||||||
physicsTransitionAltitude: 1000
|
physicsTransitionAltitude: 1000
|
||||||
useUnityPhysics: 1
|
useUnityPhysics: 1
|
||||||
|
isFrozen: 1
|
||||||
|
showThrustArrow: 1
|
||||||
|
thrustArrowScale: 0.00001
|
||||||
|
thrustArrowMaxLength: 500
|
||||||
--- !u!54 &1172921199
|
--- !u!54 &1172921199
|
||||||
Rigidbody:
|
Rigidbody:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1902,6 +1910,19 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: a1205446b72eb1daeb13064fb0454b99, type: 3}
|
m_Script: {fileID: 11500000, guid: a1205446b72eb1daeb13064fb0454b99, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: '::'
|
m_EditorClassIdentifier: '::'
|
||||||
|
mainEngine: {fileID: 1437557825}
|
||||||
|
rocketPhysics: {fileID: 1172921198}
|
||||||
|
rb: {fileID: 1172921199}
|
||||||
|
maxGimbalAngle: 10
|
||||||
|
gimbalResponseRate: 30
|
||||||
|
pitchInput: 0
|
||||||
|
yawInput: 0
|
||||||
|
rollInput: 0
|
||||||
|
currentPitchAngle: 0
|
||||||
|
currentYawAngle: 0
|
||||||
|
appliedTorque: {x: 0, y: 0, z: 0}
|
||||||
|
gimbalLeverArm: 5
|
||||||
|
showDebugInfo: 0
|
||||||
--- !u!4 &1437557828
|
--- !u!4 &1437557828
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -2,15 +2,130 @@ using UnityEngine;
|
|||||||
|
|
||||||
public class GimbalSystem : MonoBehaviour
|
public class GimbalSystem : MonoBehaviour
|
||||||
{
|
{
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
[Header("References")]
|
||||||
void Start()
|
public MainEngine mainEngine;
|
||||||
{
|
public RocketPhysics rocketPhysics;
|
||||||
|
public Rigidbody rb;
|
||||||
|
|
||||||
|
[Header("Gimbal Settings")]
|
||||||
|
[Range(0f, 20f)]
|
||||||
|
public float maxGimbalAngle = 10f; // degrees - maximum deflection angle
|
||||||
|
public float gimbalResponseRate = 30f; // degrees per second - how fast gimbal can move
|
||||||
|
|
||||||
|
[Header("Input")]
|
||||||
|
public float pitchInput = 0f; // -1 to 1 (negative = pitch down, positive = pitch up)
|
||||||
|
public float yawInput = 0f; // -1 to 1 (negative = yaw left, positive = yaw right)
|
||||||
|
public float rollInput = 0f; // -1 to 1 (optional roll control)
|
||||||
|
|
||||||
|
[Header("Current Gimbal State")]
|
||||||
|
public float currentPitchAngle = 0f; // degrees
|
||||||
|
public float currentYawAngle = 0f; // degrees
|
||||||
|
public Vector3 appliedTorque = Vector3.zero; // N⋅m
|
||||||
|
|
||||||
|
[Header("Gimbal Physics")]
|
||||||
|
public float gimbalLeverArm = 5f; // meters - distance from CoM to thrust vector application point
|
||||||
|
|
||||||
|
[Header("Debug")]
|
||||||
|
public bool showDebugInfo = false;
|
||||||
|
|
||||||
|
void FixedUpdate()
|
||||||
|
{
|
||||||
|
UpdateGimbalAngles();
|
||||||
|
CalculateGimbalTorque();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update is called once per frame
|
/// <summary>
|
||||||
void Update()
|
/// Updates the current gimbal angles based on input, respecting limits and response rates
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateGimbalAngles()
|
||||||
{
|
{
|
||||||
|
// Calculate target angles from input
|
||||||
|
float targetPitchAngle = pitchInput * maxGimbalAngle;
|
||||||
|
float targetYawAngle = yawInput * maxGimbalAngle;
|
||||||
|
|
||||||
|
// Smoothly move toward target angles at the response rate
|
||||||
|
float maxDelta = gimbalResponseRate * Time.fixedDeltaTime;
|
||||||
|
currentPitchAngle = Mathf.MoveTowards(currentPitchAngle, targetPitchAngle, maxDelta);
|
||||||
|
currentYawAngle = Mathf.MoveTowards(currentYawAngle, targetYawAngle, maxDelta);
|
||||||
|
|
||||||
|
// Enforce gimbal limits (safety clamp)
|
||||||
|
currentPitchAngle = Mathf.Clamp(currentPitchAngle, -maxGimbalAngle, maxGimbalAngle);
|
||||||
|
currentYawAngle = Mathf.Clamp(currentYawAngle, -maxGimbalAngle, maxGimbalAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates torque based on gimbal angles and engine thrust (does not apply it)
|
||||||
|
/// RocketPhysics will read and apply this torque
|
||||||
|
/// </summary>
|
||||||
|
private void CalculateGimbalTorque()
|
||||||
|
{
|
||||||
|
// Only calculate torque if engine is producing thrust
|
||||||
|
if (mainEngine == null || !mainEngine.engineIgnited || mainEngine.thrust <= 0f)
|
||||||
|
{
|
||||||
|
appliedTorque = Vector3.zero;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert gimbal angles to radians for calculation
|
||||||
|
float pitchRad = currentPitchAngle * Mathf.Deg2Rad;
|
||||||
|
float yawRad = currentYawAngle * Mathf.Deg2Rad;
|
||||||
|
|
||||||
|
// Calculate perpendicular force components from gimbal deflection
|
||||||
|
// For small angles: F_perp ≈ F_thrust × sin(angle) ≈ F_thrust × angle_rad
|
||||||
|
// Using full sin for accuracy at larger gimbal angles
|
||||||
|
float pitchForce = mainEngine.thrust * 1000f * Mathf.Sin(pitchRad); // Convert kN to N
|
||||||
|
float yawForce = mainEngine.thrust * 1000f * Mathf.Sin(yawRad);
|
||||||
|
|
||||||
|
// Calculate torque: τ = F × r (cross product, but simplified for perpendicular forces)
|
||||||
|
// Pitch gimbal creates torque around the local right axis (X)
|
||||||
|
// Yaw gimbal creates torque around the local forward axis (Z)
|
||||||
|
// Torque directions: positive pitch input → nose up, positive yaw input → nose right
|
||||||
|
Vector3 localTorque = new Vector3(
|
||||||
|
pitchForce * gimbalLeverArm, // Pitch torque around X axis
|
||||||
|
0f, // No direct Y torque from gimbal
|
||||||
|
-yawForce * gimbalLeverArm // Yaw torque around Z axis (negative for correct direction)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert local torque to world space
|
||||||
|
appliedTorque = rb.rotation * localTorque;
|
||||||
|
|
||||||
|
if (showDebugInfo)
|
||||||
|
{
|
||||||
|
Debug.Log($"[GimbalSystem] Pitch: {currentPitchAngle:F2}°, Yaw: {currentYawAngle:F2}°, Torque: {appliedTorque.magnitude:F2} N⋅m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the pitch input (-1 to 1)
|
||||||
|
/// </summary>
|
||||||
|
public void SetPitchInput(float value)
|
||||||
|
{
|
||||||
|
pitchInput = Mathf.Clamp(value, -1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the yaw input (-1 to 1)
|
||||||
|
/// </summary>
|
||||||
|
public void SetYawInput(float value)
|
||||||
|
{
|
||||||
|
yawInput = Mathf.Clamp(value, -1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the roll input (-1 to 1) - for future use with RCS or other control surfaces
|
||||||
|
/// </summary>
|
||||||
|
public void SetRollInput(float value)
|
||||||
|
{
|
||||||
|
rollInput = Mathf.Clamp(value, -1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets gimbal to neutral position
|
||||||
|
/// </summary>
|
||||||
|
public void ResetGimbal()
|
||||||
|
{
|
||||||
|
pitchInput = 0f;
|
||||||
|
yawInput = 0f;
|
||||||
|
rollInput = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,17 @@ public class InstrumentManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
[Header("Input")]
|
[Header("Input")]
|
||||||
public InputActionReference throttleAction; // Your Input Action reference
|
public InputActionReference throttleAction; // Your Input Action reference
|
||||||
|
public InputActionReference attitudeAction; // Vector3 input for pitch/yaw/roll control
|
||||||
|
|
||||||
[Header("Throttle Settings")]
|
[Header("Throttle Settings")]
|
||||||
public float rampSpeed = 1f; // Units per second
|
public float rampSpeed = 1f; // Units per second
|
||||||
|
|
||||||
|
[Header("Attitude Control Settings")]
|
||||||
|
public float attitudeResponseSpeed = 1f; // Multiplier for attitude input sensitivity
|
||||||
|
|
||||||
[Header("References")]
|
[Header("References")]
|
||||||
public MainEngine mainEngine; // Reference to your engine script
|
public MainEngine mainEngine; // Reference to your engine script
|
||||||
|
public GimbalSystem gimbalSystem; // Reference to gimbal control system
|
||||||
// Referance to TextMeshPro Throttle slider
|
// Referance to TextMeshPro Throttle slider
|
||||||
public Slider throttleDisplay; // Reference to UI Slider component
|
public Slider throttleDisplay; // Reference to UI Slider component
|
||||||
|
|
||||||
@@ -26,16 +31,30 @@ public class InstrumentManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
Debug.LogWarning("Throttle action reference is not set!");
|
Debug.LogWarning("Throttle action reference is not set!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attitudeAction != null)
|
||||||
|
{
|
||||||
|
attitudeAction.action.Enable();
|
||||||
|
Debug.Log("Attitude action enabled.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Attitude action reference is not set!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDisable()
|
void OnDisable()
|
||||||
{
|
{
|
||||||
if (throttleAction != null)
|
if (throttleAction != null)
|
||||||
throttleAction.action.Disable();
|
throttleAction.action.Disable();
|
||||||
|
|
||||||
|
if (attitudeAction != null)
|
||||||
|
attitudeAction.action.Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
{
|
{
|
||||||
|
// Handle throttle input
|
||||||
if (throttleAction == null || mainEngine == null)
|
if (throttleAction == null || mainEngine == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -59,5 +78,23 @@ public class InstrumentManager : MonoBehaviour
|
|||||||
{
|
{
|
||||||
throttleDisplay.value = mainEngine.throttleInput;
|
throttleDisplay.value = mainEngine.throttleInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle attitude control input
|
||||||
|
if (attitudeAction != null && gimbalSystem != null)
|
||||||
|
{
|
||||||
|
// Read Vector3 input
|
||||||
|
Vector3 attitudeInput = attitudeAction.action.ReadValue<Vector3>();
|
||||||
|
|
||||||
|
// Apply attitude response speed multiplier
|
||||||
|
attitudeInput *= attitudeResponseSpeed;
|
||||||
|
|
||||||
|
// Map inputs to gimbal system:
|
||||||
|
// Y (up/down) → Pitch
|
||||||
|
// X (left/right) → Yaw
|
||||||
|
// Z (forward/backward) → Roll
|
||||||
|
gimbalSystem.SetPitchInput(attitudeInput.y);
|
||||||
|
gimbalSystem.SetYawInput(attitudeInput.x);
|
||||||
|
gimbalSystem.SetRollInput(attitudeInput.z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class MainEngine : MonoBehaviour
|
|||||||
public bool engineOnline = false; // true if engine is running
|
public bool engineOnline = false; // true if engine is running
|
||||||
public bool engineIgnited = false; // true if ignition completed
|
public bool engineIgnited = false; // true if ignition completed
|
||||||
public bool restartable = true; // if false, engine cannot restart once shut down
|
public bool restartable = true; // if false, engine cannot restart once shut down
|
||||||
public float throttleInput = 0f; // 0-1 input from pilot
|
[Range(0f, 1f)]public float throttleInput = 0f; // 0-1 input from pilot
|
||||||
public float thrust = 0f; // kN
|
public float thrust = 0f; // kN
|
||||||
public float fuelFlowRate = 0f; // kg/s
|
public float fuelFlowRate = 0f; // kg/s
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
{
|
{
|
||||||
[Header("References")]
|
[Header("References")]
|
||||||
public MainEngine mainEngine;
|
public MainEngine mainEngine;
|
||||||
|
public GimbalSystem gimbalSystem;
|
||||||
public Rigidbody rb;
|
public Rigidbody rb;
|
||||||
public Altimeter altimeter;
|
public Altimeter altimeter;
|
||||||
|
|
||||||
@@ -16,6 +17,12 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
[Header("Physics Mode Settings")]
|
[Header("Physics Mode Settings")]
|
||||||
public float physicsTransitionAltitude = 1000f; // meters - switch to Unity physics below this
|
public float physicsTransitionAltitude = 1000f; // meters - switch to Unity physics below this
|
||||||
public bool useUnityPhysics = true; // current physics mode
|
public bool useUnityPhysics = true; // current physics mode
|
||||||
|
public bool isFrozen = false; // when true, freezes rocket physics (thrust arrow still works)
|
||||||
|
|
||||||
|
[Header("Visualization")]
|
||||||
|
public bool showThrustArrow = true;
|
||||||
|
public float thrustArrowScale = 0.0001f; // scales thrust magnitude for arrow length
|
||||||
|
public float thrustArrowMaxLength = 100f; // prevents arrow from being too long
|
||||||
|
|
||||||
private Vector3 lastPhysicsPosition;
|
private Vector3 lastPhysicsPosition;
|
||||||
|
|
||||||
@@ -34,12 +41,13 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
// Determine which physics mode to use
|
// Determine which physics mode to use
|
||||||
bool shouldUseUnityPhysics = altimeter.altitude < physicsTransitionAltitude;
|
bool shouldUseUnityPhysics = altimeter.altitude < physicsTransitionAltitude;
|
||||||
|
|
||||||
// Handle mode transition
|
// Handle mode transition (only if not frozen)
|
||||||
if (shouldUseUnityPhysics != useUnityPhysics)
|
if (!isFrozen && shouldUseUnityPhysics != useUnityPhysics)
|
||||||
{
|
{
|
||||||
TransitionPhysicsMode(shouldUseUnityPhysics);
|
TransitionPhysicsMode(shouldUseUnityPhysics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always calculate physics, but only apply if not frozen
|
||||||
if (useUnityPhysics)
|
if (useUnityPhysics)
|
||||||
{
|
{
|
||||||
UpdateWithUnityPhysics();
|
UpdateWithUnityPhysics();
|
||||||
@@ -48,6 +56,12 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
{
|
{
|
||||||
UpdateWithDoublePrecision();
|
UpdateWithDoublePrecision();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw thrust visualization (works even when frozen)
|
||||||
|
if (showThrustArrow)
|
||||||
|
{
|
||||||
|
DrawThrustArrow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransitionPhysicsMode(bool toUnityPhysics)
|
void TransitionPhysicsMode(bool toUnityPhysics)
|
||||||
@@ -78,11 +92,34 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
double gravityAcceleration = altimeter.gh;
|
double gravityAcceleration = altimeter.gh;
|
||||||
Vector3 gravityForce = new Vector3(0, (float)(-gravityAcceleration * rb.mass), 0);
|
Vector3 gravityForce = new Vector3(0, (float)(-gravityAcceleration * rb.mass), 0);
|
||||||
|
|
||||||
|
// Thrust force (converted from kN to N)
|
||||||
Vector3 thrustDirection = rb.rotation * Vector3.up;
|
Vector3 thrustDirection = rb.rotation * Vector3.up;
|
||||||
Vector3 thrustForce = thrustDirection * mainEngine.thrust;
|
Vector3 thrustForce = thrustDirection * mainEngine.thrust * 1000f;
|
||||||
|
|
||||||
rb.AddForce(gravityForce, ForceMode.Force);
|
if (!isFrozen)
|
||||||
rb.AddForce(thrustForce, ForceMode.Force);
|
{
|
||||||
|
// Apply forces only when not frozen
|
||||||
|
rb.AddForce(gravityForce, ForceMode.Force);
|
||||||
|
rb.AddForce(thrustForce, ForceMode.Force);
|
||||||
|
|
||||||
|
// Apply gimbal torque if available
|
||||||
|
if (gimbalSystem != null)
|
||||||
|
{
|
||||||
|
rb.AddTorque(gimbalSystem.appliedTorque, ForceMode.Force);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// When frozen, manually calculate what velocity would be
|
||||||
|
Vector3 totalForce = gravityForce + thrustForce;
|
||||||
|
Vector3 acceleration = totalForce / rb.mass;
|
||||||
|
Vector3 newVelocity = rb.linearVelocity + acceleration * Time.fixedDeltaTime;
|
||||||
|
velocity = new DoublePrecisionVector3(newVelocity.x, newVelocity.y, newVelocity.z);
|
||||||
|
// Position stays the same when frozen
|
||||||
|
position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z);
|
||||||
|
rotation = new DoublePrecisionVector3(rb.rotation.eulerAngles.x, rb.rotation.eulerAngles.y, rb.rotation.eulerAngles.z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Update double precision tracking from Unity physics
|
// Update double precision tracking from Unity physics
|
||||||
position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z);
|
position = new DoublePrecisionVector3(rb.position.x, rb.position.y, rb.position.z);
|
||||||
@@ -94,7 +131,7 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
{
|
{
|
||||||
// Manual double-precision integration - no ground interaction
|
// 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 * 1000.0) / rb.mass; // Convert kN to N
|
||||||
|
|
||||||
Vector3 thrustDirection = rb.rotation * Vector3.up;
|
Vector3 thrustDirection = rb.rotation * Vector3.up;
|
||||||
DoublePrecisionVector3 gravityAccelerationVector = new DoublePrecisionVector3(0, -gravityAcceleration, 0);
|
DoublePrecisionVector3 gravityAccelerationVector = new DoublePrecisionVector3(0, -gravityAcceleration, 0);
|
||||||
@@ -105,15 +142,110 @@ public class RocketPhysics : MonoBehaviour
|
|||||||
);
|
);
|
||||||
DoublePrecisionVector3 totalAcceleration = gravityAccelerationVector + thrustAccelerationVector;
|
DoublePrecisionVector3 totalAcceleration = gravityAccelerationVector + thrustAccelerationVector;
|
||||||
|
|
||||||
|
// Always calculate new velocity and position
|
||||||
velocity = velocity + totalAcceleration * Time.fixedDeltaTime;
|
velocity = velocity + totalAcceleration * Time.fixedDeltaTime;
|
||||||
position = position + velocity * Time.fixedDeltaTime;
|
position = position + velocity * Time.fixedDeltaTime;
|
||||||
|
|
||||||
// Update Unity transform (kinematic mode)
|
// Only apply to rigidbody if not frozen
|
||||||
Vector3 newPosition = new Vector3((float)position.x, (float)position.y, (float)position.z);
|
if (!isFrozen)
|
||||||
rb.position = newPosition;
|
{
|
||||||
// Do not set linearVelocity for kinematic bodies
|
// Apply gimbal torque if available
|
||||||
// rb.linearVelocity = new Vector3((float)velocity.x, (float)velocity.y, (float)velocity.z);
|
if (gimbalSystem != null && gimbalSystem.appliedTorque.magnitude > 0f)
|
||||||
rb.rotation = Quaternion.Euler((float)rotation.x, (float)rotation.y, (float)rotation.z);
|
{
|
||||||
|
ApplyManualTorque(gimbalSystem.appliedTorque);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Unity transform (kinematic mode)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manually applies torque for double-precision physics mode
|
||||||
|
/// </summary>
|
||||||
|
private void ApplyManualTorque(Vector3 torque)
|
||||||
|
{
|
||||||
|
// Get moment of inertia tensor
|
||||||
|
Vector3 inertiaTensor = rb.inertiaTensor;
|
||||||
|
if (inertiaTensor == Vector3.zero)
|
||||||
|
{
|
||||||
|
// Fallback if inertia tensor not set - use a simplified calculation
|
||||||
|
float I = rb.mass * 25f; // Simplified inertia estimate
|
||||||
|
inertiaTensor = new Vector3(I, I, I);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate angular acceleration: α = τ / I (in local space)
|
||||||
|
Vector3 localTorque = Quaternion.Inverse(rb.rotation) * torque;
|
||||||
|
Vector3 angularAcceleration = new Vector3(
|
||||||
|
inertiaTensor.x > 0 ? localTorque.x / inertiaTensor.x : 0,
|
||||||
|
inertiaTensor.y > 0 ? localTorque.y / inertiaTensor.y : 0,
|
||||||
|
inertiaTensor.z > 0 ? localTorque.z / inertiaTensor.z : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Integrate angular velocity (simplified Euler integration)
|
||||||
|
Vector3 angularDisplacement = angularAcceleration * Time.fixedDeltaTime * Time.fixedDeltaTime * Mathf.Rad2Deg;
|
||||||
|
|
||||||
|
// Update rotation
|
||||||
|
Quaternion deltaRotation = Quaternion.Euler(angularDisplacement);
|
||||||
|
rb.rotation = rb.rotation * deltaRotation;
|
||||||
|
|
||||||
|
// Update rotation tracking
|
||||||
|
rotation.x = rb.rotation.eulerAngles.x;
|
||||||
|
rotation.y = rb.rotation.eulerAngles.y;
|
||||||
|
rotation.z = rb.rotation.eulerAngles.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a debug arrow showing the direction and magnitude of thrust
|
||||||
|
/// </summary>
|
||||||
|
private void DrawThrustArrow()
|
||||||
|
{
|
||||||
|
// Base thrust direction
|
||||||
|
Vector3 thrustDirection = Vector3.up;
|
||||||
|
|
||||||
|
// Apply gimbal deflection if gimbal system is available
|
||||||
|
if (gimbalSystem != null)
|
||||||
|
{
|
||||||
|
// Apply pitch rotation around local X axis (right)
|
||||||
|
Quaternion pitchRotation = Quaternion.AngleAxis(gimbalSystem.currentPitchAngle, Vector3.right);
|
||||||
|
thrustDirection = pitchRotation * thrustDirection;
|
||||||
|
|
||||||
|
// Apply yaw rotation around local Z axis (forward)
|
||||||
|
Quaternion yawRotation = Quaternion.AngleAxis(-gimbalSystem.currentYawAngle, Vector3.forward);
|
||||||
|
thrustDirection = yawRotation * thrustDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform to world space
|
||||||
|
thrustDirection = rb.rotation * thrustDirection;
|
||||||
|
|
||||||
|
float thrustMagnitude = mainEngine.thrust * 1000f; // Convert kN to N
|
||||||
|
|
||||||
|
// Scale the arrow length proportionally but cap it
|
||||||
|
float arrowLength = Mathf.Min(thrustMagnitude * thrustArrowScale, thrustArrowMaxLength);
|
||||||
|
|
||||||
|
if (arrowLength > 0.1f) // Only draw if there's meaningful thrust
|
||||||
|
{
|
||||||
|
Vector3 arrowEnd = rb.position + thrustDirection * arrowLength;
|
||||||
|
|
||||||
|
// Draw main arrow line
|
||||||
|
Debug.DrawLine(rb.position, arrowEnd, Color.green, 0f);
|
||||||
|
|
||||||
|
// Draw arrowhead (two lines forming a V)
|
||||||
|
Vector3 arrowHeadSize = thrustDirection * (arrowLength * 0.15f);
|
||||||
|
Vector3 perpendicular1 = Vector3.Cross(thrustDirection, Vector3.up).normalized * (arrowLength * 0.1f);
|
||||||
|
if (perpendicular1.magnitude < 0.01f) // Handle case where thrust is vertical
|
||||||
|
{
|
||||||
|
perpendicular1 = Vector3.Cross(thrustDirection, Vector3.right).normalized * (arrowLength * 0.1f);
|
||||||
|
}
|
||||||
|
Vector3 perpendicular2 = Vector3.Cross(thrustDirection, perpendicular1).normalized * (arrowLength * 0.1f);
|
||||||
|
|
||||||
|
Debug.DrawLine(arrowEnd, arrowEnd - arrowHeadSize + perpendicular1, Color.green, 0f);
|
||||||
|
Debug.DrawLine(arrowEnd, arrowEnd - arrowHeadSize - perpendicular1, Color.green, 0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1263,7 +1263,7 @@ MonoBehaviour:
|
|||||||
m_Position:
|
m_Position:
|
||||||
m_Target: {x: 0, y: 0, z: 0}
|
m_Target: {x: 0, y: 0, z: 0}
|
||||||
speed: 2
|
speed: 2
|
||||||
m_Value: {x: 241.54735, y: 149.56917, z: 1.1022915}
|
m_Value: {x: 0, y: 0, z: 0}
|
||||||
m_RenderMode: 0
|
m_RenderMode: 0
|
||||||
m_CameraMode:
|
m_CameraMode:
|
||||||
drawMode: 0
|
drawMode: 0
|
||||||
@@ -1311,15 +1311,15 @@ MonoBehaviour:
|
|||||||
m_Rotation:
|
m_Rotation:
|
||||||
m_Target: {x: -0.01953283, y: 0.97352827, z: -0.091104165, w: -0.20872095}
|
m_Target: {x: -0.01953283, y: 0.97352827, z: -0.091104165, w: -0.20872095}
|
||||||
speed: 2
|
speed: 2
|
||||||
m_Value: {x: 0, y: 0, z: 0, w: 1}
|
m_Value: {x: -0.0195328, y: 0.9735268, z: -0.09110402, w: -0.20872062}
|
||||||
m_Size:
|
m_Size:
|
||||||
m_Target: 2.4383476
|
m_Target: 2.4383476
|
||||||
speed: 2
|
speed: 2
|
||||||
m_Value: 192.62563
|
m_Value: 2.4383476
|
||||||
m_Ortho:
|
m_Ortho:
|
||||||
m_Target: 0
|
m_Target: 0
|
||||||
speed: 2
|
speed: 2
|
||||||
m_Value: 1
|
m_Value: 0
|
||||||
m_CameraSettings:
|
m_CameraSettings:
|
||||||
m_Speed: 1
|
m_Speed: 1
|
||||||
m_SpeedNormalized: 0.5
|
m_SpeedNormalized: 0.5
|
||||||
|
|||||||
Reference in New Issue
Block a user