Limiting Altitude - Helicopter Tutorial

Greetings,

I have been working with a Helicoptor Tutorial. I seem to have figured out the controls thus far. I have a working (touchy) helicoptor flying around.

Can someone point me to how I would limit the altitude the helicopter can go? I really only want it to fly a little bit (just above building height) and not sure what to do. This is the first non char controler type object I have done. All physics controled.

Here is the control script thus far.

var main_Rotor_GameObject: GameObject;
var tail_Rotor_GameObject: GameObject;

var max_Rotor_Force: float = 22241.1081;
var max_Rotor_Velocity: float = 7200;
static var rotor_Velocity: float = 0.0;
private var rotor_Rotation: float = 0.0;

var max_tail_Rotor_Force: float = 15000.0;
var max_Tail_Rotor_Velocity: float = 2200.0;
private var tail_Rotor_Velocity: float = 0.0;
private var tail_Rotor_Rotation: float = 0.0;

var forward_Rotor_Torque_Multiplier: float = 0.5;
var sideways_Rotor_Torque_Multiplier: float = 0.5;

static var main_Rotor_Active: boolean = true;
static var tail_Rotor_Active: boolean = true;

function FixedUpdate()
{
	var torqueValue: Vector3;
	var controlTorque: Vector3 = Vector3(Input.GetAxis("Vertical")*forward_Rotor_Torque_Multiplier,
														1.0,
														-Input.GetAxis("Horizontal2")*sideways_Rotor_Torque_Multiplier);
	
	if( main_Rotor_Active==true)
	{
		torqueValue +=(controlTorque * max_Rotor_Force * rotor_Velocity);
		rigidbody.AddRelativeForce(Vector3.up * max_Rotor_Force * rotor_Velocity);
	}

	if(Vector3.Angle(Vector3.up,transform.up)<80)
	{
		transform.rotation = Quaternion.Slerp(transform.rotation,
															Quaternion.Euler(0,transform.rotation.eulerAngles.y,0),
															Time.deltaTime * rotor_Velocity *2);
	}
	
	if(tail_Rotor_Active == true)
	{
		torqueValue -=(Vector3.up * max_tail_Rotor_Force * tail_Rotor_Velocity);
	}
	
	rigidbody.AddRelativeTorque(torqueValue);
}

function Update () 
{
	if(main_Rotor_Active ==true)
	{
		main_Rotor_GameObject.transform.rotation = transform.rotation *
		Quaternion.Euler(0,
								rotor_Rotation,
								0);
	}
	
	if(tail_Rotor_Active ==true)
	{
		tail_Rotor_GameObject.transform.rotation = transform.rotation *
		Quaternion.Euler(tail_Rotor_Rotation,
								0,
								0);
	}
	
	rotor_Rotation += max_Rotor_Velocity * rotor_Velocity * Time.deltaTime;
	tail_Rotor_Rotation += max_Tail_Rotor_Velocity * rotor_Velocity * Time.deltaTime;
	
	var hover_Rotor_Velocity = (rigidbody.mass * Mathf.Abs(Physics.gravity.y)
											/max_Rotor_Force);
	var hover_Tail_Rotor_Velocity = (max_Rotor_Force * rotor_Velocity)
												/max_tail_Rotor_Force;
												
	if(Input.GetAxis("Vertical2") !=0.0)
	{
		rotor_Velocity += Input.GetAxis("Vertical2") * 0.005;
	}
	else
	{
		rotor_Velocity = Mathf.Lerp(rotor_Velocity,
												hover_Rotor_Velocity,
												Time.deltaTime * Time.deltaTime *5);
	}
	tail_Rotor_Velocity= hover_Tail_Rotor_Velocity - Input.GetAxis("Horizontal");
	
	if(rotor_Velocity>1.0)
	{
		rotor_Velocity = 1.0;
	}
	else if(rotor_Velocity <0.0)
	{
		rotor_Velocity =0.0;
	}
	
	audio.pitch = rotor_Velocity;
	
}

Any pointers?

I did’nt look to see if you have a var for this already, but just get the transform var adn do somthing like this :smile:

 var maxHieght =0.0;
function Update(){
if(transform >= maxHieght) {
transform = maxHieght;
//this would prevent it from going any higher.  
//It may call for a different operator in the conditional statment.
  }
}

Ofc This is just an example and probably only close. But may give you the general idea. This is kind of the way they did it in the airplane demo in the showcase :smile:

Another option is to place an invisible ceiling in your scene. I’m a big proponent of this, because I’ve got a cool prefab I think everyone should be using. It’s on www.CreatedByBrett.com on the “Programming” page.

I had to do the same thing for my tutorial and I used to
use the method black mantis described but in the end I
found using Mathf.Clamp was easier and it did what I wanted

transform.position.y = Mathf.Clamp(transform.position.y, 0, maxHeight);

easyest way to do it if you ask me. You will still need a maxHeight var of course.

P.s. Would you by chance be doing this for the uniknowledge 2
contest? if not you might want to enter.

I am actually only doing a remake of the game Return Fire. I am not good enough with Unity to enter any contests yet.

Thanks for the feedback all.

Directly manipulating the transform of a GameObject that uses a RigidBody component for its movement can cause all kinds of weird behaviour. When you put a rigidbody on an object, that rigidbody expects to be handling all the transform logic (unless it’s set to kinematic). So when you start messing with the object’s transform behind the rigidbody’s back that rigidbody might not be able to do its work properly.

So instead of capping the helicopter’s transform at a maximum values, you might have to find a more rigidbody-friendly way. For instance, you could limit the amount of upward force (lift) generated by the rotor based on the altitude. The higher the helicopter gets, the less force it generates to keep it in the air. This should eventually keep the helicopter in equilibrium at a certain altitude, while not feeling like it suddenly hit an invisible wall. Thus:

rigidbody.AddRelativeForce(Vector3.up * max_Rotor_Force * rotor_Velocity);

… could become:

/* --- Editor variables --- */
public var falloffStartHeight = 1000;
/* Height above which the lift force should start to decrease */

public var falloffRange = 100;
/* How many additional meters need to be climbed before the lift force is gone entirely. Set to large amount for a very gradual effect, or set to small value to instantly kill lift.*/


/* --- For inside FixedUpdate --- */
var altitude = transform.position.y;
/* Could also do this based on a raycast, but this should do, I guess */

var aboveFalloffHeight = Mathf.Clamp(altitude - falloffStartHeight, 0, falloffRange);
/* Amount of meters above falloff heigth */

var falloffScalar = 1 - aboveFalloffHeight / falloffRange;
/* Scalar used to modify the amount of lift that the rotor generates. Stays at 1 when flying under the fallofStartHeigth, and gradually falls to 0  when flying above it. A value of 1 means the lift stays unchanged, a value of 0.5 the lift is halfed, at 0 the lift is gone completely, etc. */

rigidbody.AddRelativeForce(Vector3.up * max_Rotor_Force * rotor_Velocity * falloffScalar);
/* Here, the original calculated force is modulated by the scalar we just calculated */

(Note: I haven’t tested the code, I’m pretty sure such a setup will work.)

The way Andrew wrote this script it does not factor in heat and altitude, both of which reduce performance.

That means that they are both inversely related to lift generated. At the very highest altitude, at maximum effective collective and maximum throttle, your aircraft should balance at generating an upward acceleration of 9.8mss. Andrew’s script, while fantastic, does not factor in collective so don’t worry too much about that.

To implement this, you just need to have it calculate either an air pressure value or a simple altitude. Use that value as a constraint on the force generated by the rotors and you would be OK.