- Home /
Find turning radius with torque
I have a 3d space game where all ships move around using physics. I am trying to determine if a given object is reachable by a ship at a given velocity and turn radius. I believe the formula for turn radius movementSpeed / rotation_in_radians but that doesn't seem to be working for me. I think it is because the torque rotations are unpredictable and changing rotations takes extra time because of excess torque in a different direction. There is also a bit of a slip factor in AerodyanmicEffect that probably needs to be accounted for.
I have code to tell if something is within a given turn radius that I am pretty sure works
public bool InsideTurnRadius(Vector3 point) {
float turnRadius = GetTurnRadius();
var toTarget = point - transform.position;
toTarget = Vector3.ProjectOnPlane(toTarget, transform.forward);
var toCenterNormalized = toTarget.normalized;
var turnRadiusCenter = transform.position + toCenterNormalized * turnRadius;
return ((point - turnRadiusCenter).sqrMagnitude) > (turnRadius * turnRadius);
}
But I don't know how to actually find the right turn radius value to plug in there.
Does anybody know how I can account for all the forces to determine if a target point is reachable?
I am using a cut down and modified version of the Unity Standard Assets Plane script.
public class SpaceCraftController : MonoBehaviour {
[SerializeField]
private float m_MaxEnginePower = 40f; // The maximum output of the engine.
[SerializeField]
private float m_AerodynamicEffect = 0.5f; // How much aerodynamics affect the speed of the aeroplane.
[SerializeField]
private float m_ThrottleChangeSpeed = 0.3f; // The speed with which the throttle changes.
public float Throttle { get; private set; } // The amount of throttle being used.
public float ForwardSpeed { get; private set; } // How fast the aeroplane is traveling in it's forward direction.
public float EnginePower { get; private set; } // How much power the engine is being given.
public float MaxEnginePower { get { return m_MaxEnginePower; } } // The maximum output of the engine.
public float RollAngle { get; private set; }
public float PitchAngle { get; private set; }
public float RollInput { get; private set; }
public float PitchInput { get; private set; }
public float YawInput { get; private set; }
public float ThrottleInput { get; private set; }
public float maxPitchSpeed = 360;
public float maxRollSpeed = 360;
public float maxYawSpeed = 360;
public bool useAeroFactor = true;
private float m_AeroFactor;
private Rigidbody m_Rigidbody;
[Header("Debug")]
public bool drawVelocity = true;
/* THIS IS WHAT I NEED A HAND WITH */
public float TurnRadius {
get {
float pitchRadius = maxPitchSpeed * Mathf.Deg2Rad;
float yawRadius = maxYawSpeed * Mathf.Deg2Rad;
if (pitchRadius > yawRadius) {
return ForwardSpeed / (yawRadius);
} else {
return ForwardSpeed / (pitchRadius);
}
}
}
private void Start() {
m_Rigidbody = GetComponent<Rigidbody>();
}
public void Move(float rollInput, float pitchInput, float yawInput, float throttleInput) {
RollInput = rollInput;
PitchInput = pitchInput;
YawInput = yawInput;
ThrottleInput = throttleInput;
ClampInputs();
CalculateRollAndPitchAngles();
ControlThrottle();
CaluclateAerodynamicEffect();
CalculateTorque();
if (drawVelocity) {
Debug.DrawRay(transform.position, GetComponent<Rigidbody>().velocity.normalized * ForwardSpeed, Color.white);
}
}
private void ClampInputs() {
RollInput = Mathf.Clamp(RollInput, -1, 1);
PitchInput = Mathf.Clamp(PitchInput, -1, 1);
YawInput = Mathf.Clamp(YawInput, -1, 1);
ThrottleInput = Mathf.Clamp(ThrottleInput, -1, 1);
}
/* ALSO not 100% sure why this works, if anybody knows I'd be very happy to learn*/
private void CalculateRollAndPitchAngles() {
// Calculate roll & pitch angles
// Calculate the flat forward direction (with no y component).
var flatForward = transform.forward;
flatForward.y = 0;
if (flatForward.sqrMagnitude > 0) {
flatForward.Normalize();
// calculate current pitch angle
var localFlatForward = transform.InverseTransformDirection(flatForward);
PitchAngle = Mathf.Atan2(localFlatForward.y, localFlatForward.z);
// calculate current roll angle
var flatRight = Vector3.Cross(Vector3.up, flatForward);
var localFlatRight = transform.InverseTransformDirection(flatRight);
RollAngle = Mathf.Atan2(localFlatRight.y, localFlatRight.x);
}
}
private void ControlThrottle() {
Throttle = Mathf.Clamp01(Throttle + ThrottleInput * Time.deltaTime * m_ThrottleChangeSpeed);
EnginePower = Throttle * m_MaxEnginePower;
m_Rigidbody.AddForce(EnginePower * transform.forward, ForceMode.Acceleration);
var velocity = m_Rigidbody.velocity;
var magnitude = velocity.magnitude;
if (magnitude > 0 && magnitude > m_MaxEnginePower) {
velocity *= (m_MaxEnginePower / magnitude);
m_Rigidbody.velocity = velocity;
}
// Forward speed is the speed in the forward direction (not the same as its velocity)
var localVelocity = transform.InverseTransformDirection(m_Rigidbody.velocity);
ForwardSpeed = Mathf.Max(0, localVelocity.z);
}
private void CaluclateAerodynamicEffect() {
// "Aerodynamic" calculations. This is a very simple approximation of the effect that a plane
// will naturally try to align itself in the direction that it's facing when moving at speed.
// Without this, the plane would behave a bit like the asteroids spaceship!
if (m_Rigidbody.velocity.sqrMagnitude > 0) {
// compare the direction we're pointing with the direction we're moving
//areoFactor is between 1 and -1
m_AeroFactor = Vector3.Dot(transform.forward, m_Rigidbody.velocity.normalized);
// multipled by itself results in a desirable rolloff curve of the effect
m_AeroFactor *= m_AeroFactor;
// Finally we calculate a new velocity by bending the current velocity direction towards
// the the direction the plane is facing, by an amount based on this aeroFactor
var newVelocity = Vector3.Lerp(m_Rigidbody.velocity, transform.forward * ForwardSpeed,
m_AeroFactor * ForwardSpeed *
m_AerodynamicEffect * Time.deltaTime);
m_Rigidbody.velocity = newVelocity;
// also rotate the plane towards the direction of movement
m_Rigidbody.rotation = Quaternion.Slerp(m_Rigidbody.rotation,
Quaternion.LookRotation(m_Rigidbody.velocity, transform.up),
m_AerodynamicEffect * Time.deltaTime);
}
}
private void CalculateTorque() {
var torque = Vector3.zero;
torque += PitchInput * (maxPitchSpeed * Time.deltaTime) * transform.right;
torque += YawInput * (maxYawSpeed * Time.deltaTime) * transform.up;
torque += -RollInput * (maxRollSpeed * Time.deltaTime) * transform.forward;
if (useAeroFactor) {
m_Rigidbody.AddTorque(torque * m_AeroFactor, ForceMode.Acceleration);
} else {
m_Rigidbody.AddTorque(torque, ForceMode.Acceleration);
}
}
Your answer
Follow this Question
Related Questions
AI Player Jerky Movement - Overcoming Obstacle 0 Answers
Thief Car AI for 3D Game 0 Answers
AI Turret Aiming 2 Answers
AI Aircraft/Spacecraft yaw and pitch help 1 Answer
Kill Rotation of object using forces 0 Answers