Flight Physics

Oh man, I am so excited. After much studying this noob has invented flight!

I’ve got my falcon model up and moving and mostly under control. The problem is that a change in direction (rotation) does not affect my thrust force. Basically what happens is I can roll and nose up or down to make turns, but if I turn too sharp or yaw too much the falcon model is flying bass ackwards.

I messed around with the angular drag a bit, but that didn’t seem like the right fix. How is it that I can keep my forward velocity tied to my current rotation?

I really appreciate any help. This is my first effort at creating my own code and it’s really exciting to be producing wanted results-- help me keep up my momentum!

Here is my code:`public class FlightControl : MonoBehaviour {

	//Birds mass and drag
	Rigidbody rigidBody;
	

	//Pitch, yaw, and roll control factors
	public float rollSpeed;
	public float pitchSpeed;
	public float yawSpeed;

	
	//how strong the wings flap, how much force they apply forwards and upwards
	public float thrustPower;
	public float upThrust;
	public float forwardThrust;

	//Lift and drag, will be defined in seperate functions; dragFactor defines the increasing scale that multiplies with velocity
	//private float dragFactor;
	private Vector3 liftFactor;

	// velocity, will be defined in seperate function
	private Vector3 forwardVelocity;

	void Start()
	{
		SetInitialReferences();
	}

	void FixedUpdate ()
	{
		LiftOff ();
		DirectionalControl ();
	}

	void SetInitialReferences()
	{
		rigidBody = GetComponent<Rigidbody> ();
		birdBody = transform.position;
	}

	void DirectionalControl()
	{
	float h = Input.GetAxis ("Horizontal") * rollSpeed * Time.deltaTime;
	float v = Input.GetAxis ("Vertical") * pitchSpeed * Time.deltaTime;
	float y = Input.GetAxis ("Yaw") * yawSpeed * Time.deltaTime;

	rigidBody.AddTorque (transform.forward * -h);
	rigidBody.AddTorque (transform.right * v);
	rigidBody.AddTorque (transform.up * y);

	}
	

	void LiftOff()

	{
		if (Input.GetButtonDown ("Jump"))
			rigidBody.AddRelativeForce (0, upThrust, forwardThrust, ForceMode.Impulse);
	}

}

`

The easiest way is to implement drag yourself. There are three things to consider.

  • Maximum Drag
  • Angle of airplane relative to direction
  • Magnitude of airplane

Here is the code // or something resembling a solution. You can probably stick this all in a sepate script called “Air Resistance” and it should work.

Maximum Drag

For this we need to calculate the maximum possible force at one time. To make it easy we will assume the minimal drag is 0. We can get this by calculating the resistance of air * exposed area of plane at maximum resistance.

but calculating the area of a plane is a bit harder. So what we can do is assume the plane is a circle and calculate resistance based on that.

public float resistanceFactor; // Resistance per k/m^3. Try to keep below 1
public float radius; // This will be the proposed radius of the plane
    
float area; // The area of the plane
float maxResistance; // This will be per cubic meter
RigidBody rb;


void Start () {
  rb = GetComponent<RigidBody> ();
   // Get the constant area and maximum resistance
   area = Mathf.Pi * Math.Pow (r, 2);
   maxResistance = area * Math.Pow(resistanceFactor , 3);
 }

Angle Of Plane

Now we want to calculate angle relative to the velocity.

/// The idea behind this is that it will return a value from
/// 0 - 1. Where 0 is when the plain is flighting straight
/// And 1 is where the plain is at a 90 angle
float resistanceFactor () {
   // Get the direction
   float direction = rb..velocity.direction;
  
   // get angle between direction and way the plane is facing
   float angle = Vector3.Angle(transform.forward, direction);
  
  // Return the resistance Factor
 return Mathf.Abs (Mathf.Sin (angle));
}

Now we have to calculate the magnitude of the force at higher speeds. Because the faster the plane goes the higher the air resistance will be

// Simply gets and returns the planes magnitude
float velocityFactor () {
  // Get and return the magnitude of the plane
  return rb.velocity.magnitude;
}

Apply Force

Finally apply the force to the plain in the opposite direction of travel

// use the Physics Update
 void LateUpdate {
   // calculate Magnitude of Air resistance
   float magnitude = maxResistance * ResistanceFactor () * VelocityFactor ();

 // Calculate the direction
 Vector3 direction = transform.forward.normalized * -1;

 // Add the force to the rigid body
 rb.AddRelativeForce (direction * magnitude);
 }

And that’s it. You can play around with the air resistance and radius variables because that is going to be how you balance this. You can even add the two lines that assign them:

area = Mathf.Pi * Math.Pow (r, 2);
maxResistance = area * Math.Pow(resistanceFactor , 3);

To the update function to balance them in game and dynamically, but that will chew up processing power in the final fame and should be placed in the start function

@ Cornelis-de-Jager

*** Update: Yeah, it’s something to do with the way I implemented the script because I can change the resistanceFactor and dragArea to infinite and it makes no difference whatsoever.

I tried to implement this and it makes sense to me. I will provide my script at the bottom. Unfortunately, I can see no effect on my flight object. My script is running without any errors. I wonder if my drag factor isn’t being applied in the right direction somehow?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FlightControl : MonoBehaviour {

					
	//USER CONTROLS***************************
	public float rollSpeed;
	public float pitchSpeed;
	public float yawSpeed;

	//PHYSICS VARIABLES******************************************************

	//The birds mass
	public Rigidbody theBird;
		
	//Upward and forward thrust generated by wing flaps
	public float thrustPower;
	public float upThrust;
	public float forwardThrust;



	//Air physics - Drag Resistance Applied Inverse to Velocity
	public float radius; //Radius of the flight object -- Higher equals more drag
	private float dragArea; //Area of the flight object -- in this case a sphere
	private Vector3 currentDirection;
	private float angle;
	private float resistanceFactor; // Resistance per k/m^3. Try to keep below 1
	private float maxResistance; //Per cubic meter
	private float velocityFactor;

	//Air Physics - Lift Force Inverse to Velocity
	//public float requiredAirSpeedForFlight;
	//private float lift;

	//***************************************************************************



		
		
		
		
	void Start()
	{
		SetInitialReferences();
	}

	void FixedUpdate ()
	{
		LiftOff ();
		DirectionalControl ();
					
	}

	void LateUpdate()
	{
		ApplyForce ();
	}

	void SetInitialReferences()
	{
		theBird = GetComponent<Rigidbody> ();
	}

	void DirectionalControl()
	{
	float h = Input.GetAxis ("Horizontal") * rollSpeed * Time.deltaTime;
	float v = Input.GetAxis ("Vertical") * pitchSpeed * Time.deltaTime;
	float y = Input.GetAxis ("Yaw") * yawSpeed * Time.deltaTime;

	theBird.AddTorque (transform.forward * -h);
	theBird.AddTorque (transform.right * v);
	theBird.AddTorque (transform.up * y);
	}
	

	void LiftOff()
	{
		if (Input.GetButtonDown ("Jump")) 
		theBird.AddRelativeForce (0, upThrust, forwardThrust, ForceMode.Impulse);
		
	}

	float FindVelocityFactor()
	{

		return theBird.velocity.magnitude;

	}

	float FindResistanceFactor()
	{
		//Get the constant area and maximum resistance
		 dragArea = Mathf.PI * Mathf.Pow (radius, 2);
		 maxResistance = dragArea * Mathf.Pow (resistanceFactor, 3);
		 currentDirection = theBird.velocity;           	//Birds direction
		 angle = Vector3.Angle (transform.forward, currentDirection);	//Angle between bird direction and velocity direction
		return Mathf.Abs (Mathf.Sin (angle));						//Return the resistance factor
		return theBird.velocity.magnitude;						//Gets and returns the birds velocity magnitude
	}

	void ApplyForce()
	{
		float magnitude = maxResistance * resistanceFactor * velocityFactor; //Magnitude of air resistance
		Vector3 direction = transform.forward.normalized * -1;  //calculate the direction
		theBird.AddRelativeForce (direction*magnitude);		//Add the force to the rigidbody
	}

//	float LiftEquation()
//	{
//		if (airSpeed >= requiredAirSpeedForFlight) 
//		{
//			theBird.AddRelativeForce (0, lift, 0);
//		}
//	}
//
//	float DefineLift()
//	{
//		
//	}
//
//	float FindAirSpeed()
//	{
//		
//	}


	}