# Damn hoovercraft i hate you!

okey, so i have to write a hovercraft-script.

I have searched here in the forums, and checked out the threads:

and started writing my own. Did some pseudo code and tried out the code examples in the above thread.

First simple example gave me a predicted result. Cube hoversbut when it hits its “top” it gets a push downwards, when i move it against a hill it flips over and lays there like a turtle that can’t get up. I lookes like “shit” to be honest.

Second script was really complicated and tried it, same problem. Cube was wobbly, unstable, flipped over.

So i have no idea how to write a proper hovercraftscript, i have like a million questions:

Should i use empty gameObjects that raycasts down, that are childs to my Cubemesh, and if so how many?
OR should i raycast from certain points on my cube?
How do i balance it properly, with mass, gravity, downforce?
How to add some sort of sinus anumation so that i feels like it is floating?
how to handle so that the cube actually rotates to its surface and not stays completly flat when going uphill?

i’ve been at it for a couple of days and im running out of options. I prefer C# over Javascript, i have a pretty good coding experiance behind me in C# and unity but i have problems with this.

I lost my hover script when I forgot to back it up on a reinstall, but I ran into pretty much every problem you did. What I eventually came up with was something like the following:

Set the desired hovering height. Use a Sin function based on total time to add in a variance each frame.

Set up N points on the object as sampling points. I generally used 6 points and set them up just outside of the object’s bounds. They can be children game objects or an array of transforms (I think I used gameobjects).

Raycast down from each point, compute the average normal of the surfaces beneath each point and compute the percentage of thrust (this is equal to number-of-raycasts-which-hit-less-than-or-equal-to-the-current-desired-height / N) Also, for each raycast that doesn’t get a hit that is less than or equal to the current desired height, the normal used for computing the average for that raycast should be the World Up vector.

Lerp or Slerp the object’s current normal to the computed normal. Apply desired thrust force (multiplied by the thrust percentage) in the object’s local Up vector.

I’m pretty certain that’s what I did. I still have the web demo on the blog in my sig. And I might have the script on my other portable hdd now that I think about it. I’ll check that out when I get off work.

The way my hover script works is like so…

It uses a raycast to determine height… there is a target height above terrain that the vehicle wants to be, so the percentage of distance away from the height determines how strong the hover force works. This provides a constant push up… float down… action

The second part involves constantly trying to turn the vehicle up-right… I think I used this code…

you should be able to adapt it so that ‘up’ is the terrain normal

Okey, so lets see now if i get this straight.

I set up N number of let’s say empty gameObject, i’ll add them to an array for keeping. Then raycast down from eaych object to the ground. But then the:

How do i compute the avarge of the surface normal?

i found this http://docs.unity3d.com/Documentation/Manual/ComputingNormalPerpendicularVector.html and as i remember to compute a side in a triangle i need two sides of it (brushing up my mathskills here). And then how to calculate the percentage thrust.

lets say we have 5 true out of 6 and i want it to be at a hight of 1m so what does that mean, 5% of thrust? doesnt’ the thrust depend on the mass of the object? Raycasts are booleans… so sorry if im beeing a bit on the slow side.

Then i have to calculate the normal of my own object, and im not sure how to do that either.

Sorry if im asking to many dumb questions, but im trying to get better at the “maths”.

You can get the normal by adding up the normals that are held in the RaycastHit object from the raycast and then normalizing the resulting vector(sets the magnitude to 1).

As for the percentage thrust, that would be 5 hits out of 6, so 5/6 = 83.3% of thrust. The idea here is that any “thruster” not within the target height isn’t able to contribute to the overall thrust. Not entirely physically accurate (I think, 'tis the morning and I’m still without coffee), but it should work.

The more I think about it, the more I’m pretty certain there might have been a few other things I did to make it work right, but I can’t quite remember them. I didn’t get around to checking my portable last night, so I’ll write myself a note to not forget this time

i really appriciate the info you are giving me. Im gonna try something here and will be reading this post and updating with my progress. These are the times i regret studying sound engineering when i was young and didn’t take math classes instead.

crap im starting to feel that this is way to complicated for me.

okey so i have set up a cube, 4 raycasts, 4 if-statements that register 4 different hits, but now what?

why do i have to normalize the hits?

Lets say, one of my rays hit the ground, it hits only ONE object, the FIRST object. Im not hitting multiple objects in each ray so why compute the average of all the struck normals and then normalize it to get the general direction of the single ray?

or should i add the normals of ALL rays struck objects normals?

i still think im not really sure about how the theory is going to work behind this.

Lets say i have a ray, it hits a surface and returns a normal of:

x: -2
y: 0.9
z: 0.2

so what does this number actually tell me? is this only a point in space?, is it the point in space where the collision occured? or is the direction of the normal (where the normal is heading/sloping). ANd what do i do with this number?

raycasthit only returns the first hit. So do i need to use the raycasthit[ ] and return everything it hits, including the stuff underneath? or are you talking about adding up the total of all the hits that my 4 points are receiving?

let me know if my questions are getting stupid and annoying but i really want to try to understand the theory of this.

The idea of computing the average of the normals is to get an average normal for the area your hovercraft is hovering over. Each ray will hit one object, and it will have a normal for the face on that object that it hit. By then averaging the normals (4 raycasts = 4 normals, 1 for each), you smooth out any “bumps” while still following the angle of the terrain. So yeah, you add up the total of the hits that your 4 raycasts are getting (which would be 4 normals).

I had done that because there were sections in my terrain that were really jagged, and if I just set the Up vector of the hovercraft to the normal of whatever was directly beneath it, it wound up looking like a bucking horse.

The normal returned by the raycast is a vector which is orthogonal to the face which the ray cast hits, and which points outward. In the case of terrain, this can essentially be said to describe the slope of the terrain, although it is perpendicular/orthogonal to the slope.

I do remember there being something that I had to do with dealing with the turning and maintaining a heading, because if you just set the Hovercraft’s local up vector to the average normal, you’ll lose all rotation. There was a question on Answers about vehicle rotation that I got that info from, I’ll see if I can’t find it (because, for the life of me, I can’t remember what I did for that).

okey this is how far i’ve come and im trying to understand all the steps.

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

public class HooverTest : MonoBehaviour {

private RaycastHit hit;

public List<GameObject>hooverpoints;
public float height;
public float force;

void Start () {
}

void LateUpdate(){

Vector3 normal = Vector3.zero;

for(int i = 0; i < hooverpoints.Count; i++){

Ray ray = new Ray(hooverpoints[i].transform.position, transform.TransformDirection(Vector3.down));
Debug.DrawRay(hooverpoints[i].transform.position, transform.TransformDirection(Vector3.down * height), Color.green);

if (Physics.Raycast(ray, out hit, height)) {

normal += hit.normal;