Hover Ship (Like F Zero)

Hey unity users, I’m making a simple racing game similar to F Zero for fun as a home project. I’ve been having some troubles with this code. When set the thrusters to fast my ship doesn’t stay on the ground very well. The script it free for anyone to use as I found it on the forums and thought I would modify it a little. At this stage it looks like I might have to make an entirely new script. Here is how I want the ships to behave http://www.youtube.com/watch?v=1PI5ZVdl-PQ

and here is the script.

using UnityEngine;
using System.Collections;

public class Hover : MonoBehaviour {
//	Approximate dimensions of the vehicle.
	public float length = 10;
	public float width = 5;
	public float height = 2;
	
//	Height above planet surface to hover.
	public float hoverHeight = 4;

//	Strength and persistence of the lifting force on the hover.
	public float springiness = 3;
	public float damping = .01f;
	
//	Forward thrust parameter. Increase for a faster vehicle.
	public float thrust = 10;
	
//	Alter y coordinate of Centre of Mass to increase hover's roll on
//	turns.
	public Vector3 centreOfMass;

//	The planet object...
	public Transform planet;
	
//	...and its gravity.
	public float gravity = 9.8f;
	
	// Use this for initialization
	void Start () {
		rigidbody.centerOfMass = centreOfMass;
	}
	
	// Update is called once per frame
	void FixedUpdate () {
	//	Gravity toward the "planet".
		Vector3 gravForce = (planet.position - transform.position).normalized * gravity;
		rigidbody.AddForce(gravForce);
		
	//	Get the four corners of the vehicle in world space.
		Vector3 frontLeft = transform.TransformPoint(-width / 2, -height / 2, length / 2);
		Vector3 frontRight = transform.TransformPoint(width / 2, -height / 2, length / 2);
		Vector3 backLeft = transform.TransformPoint(-width / 2, -height / 2, -length / 2);
		Vector3 backRight = transform.TransformPoint(width / 2, -height / 2, -length / 2);
		
	//	Vehicle's relative "up" direction.
		Vector3 relUp = transform.TransformDirection(Vector3.up);
		RaycastHit frontLeftHit;
		RaycastHit frontRightHit;
		RaycastHit backLeftHit;
		RaycastHit backRightHit;
		
	//	Measure the distance to the ground with rays.
		Physics.Raycast(frontLeft, -relUp, out frontLeftHit);
		Physics.Raycast(frontRight, -relUp, out frontRightHit);
		Physics.Raycast(backLeft, -relUp, out backLeftHit);
		Physics.Raycast(backRight, -relUp, out backRightHit);
	
	//	Get the current velocity of the corner points in the
	//	hover's up/down direction to act as damping for the
	//	springy hovering force.
		Vector3 dampVec = new Vector3(0, damping, 0);
		
		Vector3 frontLeftDamp = transform.TransformDirection(
				Vector3.Scale(transform.InverseTransformDirection(rigidbody.GetPointVelocity(frontLeft)), dampVec));
		Vector3 frontRightDamp = transform.TransformDirection(Vector3.Scale(transform.InverseTransformDirection(rigidbody.GetPointVelocity(frontRight)), dampVec));
		Vector3 backLeftDamp = transform.TransformDirection(Vector3.Scale(transform.InverseTransformDirection(rigidbody.GetPointVelocity(backLeft)), dampVec));
		Vector3 backRightDamp = transform.TransformDirection(Vector3.Scale(transform.InverseTransformDirection(rigidbody.GetPointVelocity(backLeft)), dampVec));

	//	Calculate the lift given by each corner.
		Vector3 frontLeftLift = (-relUp * gravity / 4) + (relUp * (hoverHeight - frontLeftHit.distance) * springiness) - frontLeftDamp;
		Vector3 frontRightLift = (-relUp * gravity / 4) + (relUp * (hoverHeight - frontRightHit.distance) * springiness) - frontRightDamp;
		Vector3 backLeftLift = (-relUp * gravity / 4) + (relUp * (hoverHeight - backLeftHit.distance) * springiness) - backLeftDamp;
		Vector3 backRightLift = (-relUp * gravity / 4) + (relUp * (hoverHeight - backRightHit.distance) * springiness) - backRightDamp;
		
	//	Calculate a simple forward thrust from the arrow keys.
		float lThrust, rThrust;
		
		lThrust = rThrust = thrust * Input.GetAxis("Vertical");
		
		float horizAxis = Input.GetAxis("Horizontal");
		
		Vector3 lThrustForce = transform.TransformDirection(Vector3.forward) * (lThrust + horizAxis);
		Vector3 rThrustForce = transform.TransformDirection(Vector3.forward) * (rThrust - horizAxis);

	//	Add the forces to the hover at the appropriate places. Note that
	//	the back corners have forward thrust as well as lift.
		rigidbody.AddForceAtPosition(frontLeftLift, frontLeft);
		rigidbody.AddForceAtPosition(frontRightLift, frontRight);
		rigidbody.AddForceAtPosition(backLeftLift + lThrustForce, backLeft);
		rigidbody.AddForceAtPosition(backRightLift + rThrustForce, backRight);
		
	}
}

If you get results please post here.

When playing around with some of the settings the closest I could get was that it would fly up which not what I want. :stuck_out_tongue:

I actually increased the springness and damping and its close very close now I just need to add in some banking when turning. Any help would be apreciated.

From the looks of it, the linked video uses something like:

public void LockToTerrain(float height, float zero, float speed)
{
    Vector3 newPosition = new Vector3(transform.position.x, Mathf.Max(Terrain.activeTerrain.SampleHeight(transform.position), zero) + height, transform.position.z);
    transform.position = Vector3.Lerp(transform.position, newPosition, speed * Time.deltaTime);
}

Which is being called in every update. I came up with that code just for demonstration purposes, you might have to tweak it in order to achieve the behaviour you want to.

I will give it a try and post some feedback.

Ok I got the script working to my liking but it doesn’t turn fast enough, and I need the ship to bank on about 30 degree angles when turning, I will try and post if I get something.

I made a script for the tilting but it can’t add it for some reason.

// Turning
	if (Input.GetButton("Left")){
		transform.eulerAngles.y += -turnSpeed * Time.deltaTime;
		// Tilt
		if(transform.eulerAngles.z >= 315 || transform.eulerAngles.z <= 45){
			Tilt("left");
		}
		
	}else if (Input.GetButton("Right")){
	transform.eulerAngles.y += turnSpeed * Time.deltaTime;
		//tilt
		if(transform.eulerAngles.z <= 45 || transform.eulerAngles.z >= 315){
			Tilt("right");
		}
	}else{ //no turn
		if (transform.eulerAngles.z < 357.5  transform.eulerAngles.z > 315){
			Tilt("right");
		}
		else if (transform.eulerAngles.z > 2.5  transform.eulerAngles.z < 45){
			Tilt("left");
		}
	}

My script is only for smoothly keeping the height, you should avoid triple-posting and instead look around here for other controller scripts, everything about tilting, rotating and accelerating has already been discussed in detail.

If you cannot add a script to a GameObject you are either missing “YourClass : MonoBehaviour” or named your class or *.cs file wrong. Just have a look around here, problems like that can easily be solved on your own.