x


Hovering Tank

I have a sci-fi themed tank that I need to make it look like it's hovering up and down through C# script. How do I go about applying force to the rigidbody giving it the impression that it's hovering up and letting gravity bring it back down again all without increasing or editing the collider box? Where do I start?

EDIT

So I was playing around with the code I gave in the link below to see if it was an all in one solution and I think my freak of nature gravity value (-500) is affecting the code badly and my craft still sticks to the ground does anyone have a clue?

Converted Code:

using UnityEngine;

using System.Collections;

public class ScifiHover : MonoBehaviour { float forwardPower;

float steerPower;

float landingPower;

float jumpingPower;

float hoverHeight;

float stability = 1;

public GameObject body;


public float speedUpdate;


private Vector3[] hitNormal = new Vector3[5];

private Quaternion rotation;

private float increment;

private Vector3[] lastNormals = new Vector3[5];

private bool physicsSetup = false;

private Vector3 boxDim;

private Vector3[] cornersPoint = new Vector3[5];

private Transform[] corners = new Transform[5];

private BoxCollider boxCollider;

private float yBounce;

private Vector3 lastPosition;

private float distance;

private Vector3 average;


void Awake()
{

    InitializePhysics();
}


void Update()
{

    CalculateSpeed();

}


void FixedUpdate()
{


    if (physicsSetup)
    {

        RaycastHit hit;


        for (int i = 0; i <= corners.Length - 1; i++)
        {

            if (Physics.Raycast(corners[i].position, -corners[i].up, out hit, hoverHeight + 100.0f))
            {

                if (hit.collider.gameObject.tag == "Floor")
                {

                    hitNormal[i] = body.transform.InverseTransformDirection(hit.normal);

                    if (lastNormals[i] != hitNormal[i])
                    {

                        increment = 0;

                        lastNormals[i] = hitNormal[i];

                    }

                    distance = hit.distance;

                    if (hit.distance < hoverHeight)
                    {

                        constantForce.relativeForce = (-average + transform.up) * rigidbody.mass * jumpingPower * rigidbody.drag * Mathf.Min(hoverHeight, hoverHeight / distance);

                    }
                    else
                    {

                        constantForce.relativeForce = -(transform.up) * rigidbody.mass * landingPower * rigidbody.drag / Mathf.Min(hoverHeight, hoverHeight / distance);

                    }

                }

            }

        }

        average = -(hitNormal[0] + hitNormal[1] + hitNormal[2] + hitNormal[3] + hitNormal[4]) / 2;


        if (increment != 1) { increment += 0.03f; }


        rotation = Quaternion.Slerp(body.transform.localRotation, Quaternion.Euler(average * Mathf.Rad2Deg), increment);


        Quaternion temp = rotation;

        temp.y = transform.up.y * Mathf.Deg2Rad;

        body.transform.localRotation = temp;


        float fwdForce = Input.GetAxis("Vertical") * forwardPower;

        rigidbody.AddForce(transform.forward * fwdForce);


        float steerForce = Input.GetAxis("Horizontal") * steerPower;

        rigidbody.AddTorque(transform.up * steerForce);


    }

}

void CalculateSpeed()
{

    if (lastPosition != transform.position)
    {

        float distance = Vector3.Distance(transform.position, lastPosition);

        speedUpdate = (distance / 1000) / (Time.deltaTime / 3600); //Km/h

    }

}


void InitializePhysics()
{

    //Store the box dimenssion of the hovering object.

    boxCollider = body.AddComponent<BoxCollider>();

    boxDim = new Vector3(boxCollider.size.x * body.transform.localScale.x, boxCollider.size.y * body.transform.localScale.y, boxCollider.size.z * body.transform.localScale.z) * stability;

    cornersPoint[0] = new Vector3(transform.position.x - boxDim.x / 2, transform.position.y - boxDim.y / 2, transform.position.z + boxDim.z / 2);

    cornersPoint[1] = new Vector3(boxDim.x / 2 + transform.position.x, transform.position.y - boxDim.y / 2, transform.position.z + boxDim.z / 2);

    cornersPoint[2] = new Vector3(boxDim.x / 2 + transform.position.x, transform.position.y - boxDim.y / 2, transform.position.z - boxDim.z / 2);

    cornersPoint[3] = new Vector3(transform.position.x - boxDim.x / 2, transform.position.y - boxDim.y / 2, transform.position.z - boxDim.z / 2);

    cornersPoint[4] = transform.position;

    Destroy(boxCollider);


    for (int i = 0; i <= cornersPoint.Length - 1; i++)
    {

        GameObject stablePlatform = GameObject.CreatePrimitive(PrimitiveType.Sphere);

        stablePlatform.name = "StablePlatform" + "(" + i + ")";

        stablePlatform.transform.parent = body.transform;

        stablePlatform.transform.localPosition = transform.InverseTransformPoint(cornersPoint[i]);

        corners[i] = stablePlatform.transform;

        Destroy(stablePlatform.GetComponent<MeshRenderer>());

        Destroy(stablePlatform.GetComponent<Collider>());

    }

    cornersPoint = null;

    physicsSetup = true;

}

}

more ▼

asked May 15 '12 at 08:44 AM

djdrool91 gravatar image

djdrool91
12 7 11 11

I believe animation would work better and provide more predictable results in this case.

May 15 '12 at 12:25 PM asafsitner
(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

Here's a part of my Hoverboard script.

What it does is check the distance down to the ground; if it is less than the specified height, it applies upward force at a percentage of the force needed to lift it up. The - Time.deltaTime is actually just a small number that is used to make sure the hoverForceMultiplier doesn't go above 1.

I have a Rigidbody of Mass 1, Use Gravity is Enabled (ticked).

EDIT - here's the C# version :

using UnityEngine;
using System.Collections;

public class HoverScript : MonoBehaviour 
{
    public float hoverDistance = 0.75f;
    public float hoverForce = 10.0f;
    private float currentHeight = 0.0f;
    private float hoverForceMultiplier = 0.0f;
    private Vector3 hoverForceApplied = Vector3.zero;

    void FixedUpdate() 
    {
        // -- find hover distance and add force to make hover   
        RaycastHit rayHit;
        if (Physics.Raycast(transform.position, Vector3.down, out rayHit))
        {
           currentHeight = rayHit.distance;
           if (currentHeight < (hoverDistance - Time.deltaTime))
           {
             // find percentage of currentHeight below hoverDistance
             hoverForceMultiplier = (hoverDistance - currentHeight) / hoverDistance;
             hoverForceApplied = (Vector3.up * hoverForce * hoverForceMultiplier) + (Vector3.up * 9.8f);
             rigidbody.AddForce(hoverForceApplied);         
           } else {       
             // apply anti-gravity force for half distance above hoverDistance
             if ((currentHeight - hoverDistance - Time.deltaTime) < (hoverDistance / 2))
             {
              hoverForceApplied = (Vector3.up * 9.8f) * ((hoverDistance - (currentHeight - hoverDistance)) / hoverDistance);
              rigidbody.AddForce(hoverForceApplied);
             }
           }
        }
    }
}

Original Post :

It's in JS and right now I have no time to convert and check it. I shall make a C# vesion when I get home tonight =]

#pragma strict

var hoverDistance : float = 0.75;
var hoverForce : float = 10.0;
private var currentHeight : float = 0.0;
private var hoverForceMultiplier : float = 0.0;
private var hoverForceApplied : Vector3 = Vector3(0, 0, 0);


function FixedUpdate () 
{
    // -- find hover distance and add force to make hover   
    var rayHit : RaycastHit;
    if(Physics.Raycast(transform.position, Vector3.down, rayHit))
    {
       currentHeight = rayHit.distance;
       if (currentHeight < (hoverDistance - Time.deltaTime))
       {
         // find percentage of currentHeight below hoverDistance
         hoverForceMultiplier = (hoverDistance - currentHeight) / hoverDistance;
         hoverForceApplied = (Vector3.up * hoverForce * hoverForceMultiplier) + (Vector3.up * 9.8);
         rigidbody.AddForce(hoverForceApplied);         
       } else {       
         // apply anti-gravity force for half distance above hoverDistance
         if ((currentHeight - hoverDistance - Time.deltaTime) < (hoverDistance / 2))
         {
          hoverForceApplied = (Vector3.up * 9.8) * ((hoverDistance - (currentHeight - hoverDistance)) / hoverDistance);
          rigidbody.AddForce(hoverForceApplied);
         }
       }
    }
}

example : http://www.alucardj.net16.net/unityquestions/HoverBoard6.html

more ▼

answered May 16 '12 at 03:37 AM

alucardj gravatar image

alucardj
13.6k 34 55 86

Wow ok thanks a million! I'll run it through a converter and work out the bugs and get back to you.

EDIT

Initial conversion successful however the vehicle just kept increasing it's hover height. I will continue to tweak and get back. Also I have to turn off gravity?

May 16 '12 at 03:46 AM djdrool91

I just converted and tested this , and it seems to be working ok.

I have a Rigidbody of Mass 1, Use Gravity is Enabled (ticked).

using UnityEngine;
using System.Collections;

public class HoverScript : MonoBehaviour 
{
    public float hoverDistance = 0.75f;
    public float hoverForce = 10.0f;
    private float currentHeight = 0.0f;
    private float hoverForceMultiplier = 0.0f;
    private Vector3 hoverForceApplied = Vector3.zero;

    void FixedUpdate() 
    {
        // -- find hover distance and add force to make hover   
        RaycastHit rayHit;
        if (Physics.Raycast(transform.position, Vector3.down, out rayHit))
        {
           currentHeight = rayHit.distance;
           if (currentHeight < (hoverDistance - Time.deltaTime))
           {
             // find percentage of currentHeight below hoverDistance
             hoverForceMultiplier = (hoverDistance - currentHeight) / hoverDistance;
             hoverForceApplied = (Vector3.up * hoverForce * hoverForceMultiplier) + (Vector3.up * 9.8f);
             rigidbody.AddForce(hoverForceApplied);         
           } else {       
             // apply anti-gravity force for half distance above hoverDistance
             if ((currentHeight - hoverDistance - Time.deltaTime) < (hoverDistance / 2))
             {
              hoverForceApplied = (Vector3.up * 9.8f) * ((hoverDistance - (currentHeight - hoverDistance)) / hoverDistance);
              rigidbody.AddForce(hoverForceApplied);
             }
           }
        }
    }
}

I also updated the answer , let me know if you're still having problems with the gravity.

May 16 '12 at 07:39 AM alucardj

You probably don't want to use physics, because transform.Translate(...) do not work well with non-kinematic rigid bodies and I really doubt that you want to move all of your units with physics (rigidbody.AddForce)

May 16 '12 at 12:46 PM Tseng

I agree physics is probably not the way to go , but with no script in the question , and the asker stated "How do I go about applying force to the rigidbody", I had this script already made and it wasn't hard to convert, so I thought I would post it and maybe there would be some other ideas that could come out of it.

May 16 '12 at 01:32 PM alucardj

Thanks for all the replies, I really appreaciate it. My apologies for not thoroughly giving more for you to help, I've just been working on it for awhile and have not familiarised myself with everything inside the project.

Ok, so after testing Jay Kay's converted C# script, My tank does NOT hover when it starts with gravity on and mass of 1. I had to increase the force to a ridiculous number and it will fly into the air upon colliding with a static object or going up the ramp.

Testing it with alucardj's conversion also results in the same situation.

Both code makes the tank fall slower but it still sticks to the ground. Should I make it check for tags and tag my floors?

Increasing the hover distance alone pulls the tank up forever only when going up a ramp.

Sorry to be vague with my question but essentially I have controls and camera's all set however all I need left to do is to have the model bob up and down constantly even through movement and up ramps but without adding animation in Maya or something. I was suggested to add force for rigidbodies and since posted the question but what I want to know really is the best and simplest way to achieve this effect. Is there a way to not do it through physics or rather a "Hard-coded" method to achieving this?

Edit

Ok so I might have found the problem or part of it. When I print out the currentHeight variable, the results I get is weird. My tank starts at Y position 138 and the highest point in the entire map is 180 however according to the print I get 138 for my lowest point (correct) but when I am going up ramps or even on any slight descending or ascending planes, it gives me a single digit print.

Ok I'm still having the gravity problem however in one of the test's I noticed that it hovered (I had to add like 3000 force) but highly unbalanced. How do I prevent this? I saw this guy's video (http://virtualrealitydesign4.blogspot.com/2012/01/script-for-hovercraft-mechanics.html) where he used spheres at the corners for balancing.

MAJOR EDIT

I've just been told that the project's gravity value was editted to -500. So do i change the value of 9.8 inside the code to 500 as I'm guessing that's the gravity value by default.

Ok so if I changed that value to 500, It works! With Hover Distance at 10 it will float and bob up and down! However the movements like how II feared. Highly unstable when going up ramps. Is there any work around to this problem?

May 17 '12 at 02:58 AM djdrool91
(comments are locked)
10|3000 characters needed characters left

As asafsitner mentioned, it's best to do it via animation, as it allows you to add unsteady hovering which also depends on the current state of the tank (i.e. moving, shooting, standing, searching).

You can always use Mathf.Cos or Mathf.Sin, as they will produce a periodical value which ranges from -1 to 1.

alt text

more ▼

answered May 15 '12 at 12:35 PM

Tseng gravatar image

Tseng
1.5k 6 8 23

I would love to do it through animation however the current circumstance is not allowing me to do so and thus has to be done by script. I'm not too good with C# and unity so if you could help me get started on how to use Mathf.Cos or Mathf.Sin I would really appreaciate it.

What I'm trying to achieve is something like on this video (http://www.youtube.com/watch?v=JE0ZLq5bobc) however my controller and camera are all set I just simply need to make the tank hover up and down by time intervals.

May 16 '12 at 02:46 AM djdrool91
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x4140
x291
x60
x55

asked: May 15 '12 at 08:44 AM

Seen: 1361 times

Last Updated: Feb 24 at 12:12 PM