I had a couple questions.
What is a good way to achieve the actual hover? I am using this:
if (Physics.Raycast(transform.position, -Vector3.up, out hit)) {
float distanceToGround = hit.distance;
distanceToGround = Mathf.Min(maxHoverImpulseRange, distanceToGround);
rigidbody.AddForce(hit.normal * (maxHoverImpulseRange - distanceToGround) * 5, ForceMode.Force);
It is really bouncy though. Once I drop it, it never stops bouncing.
My other question is, what is a good way to make the vehicle self-righting. I want it to tend to keep itself upright, while still being able to be tumbled about if it hits something.
2 Answers
2
After trying many many methods that failed here's what I came up with. It is very much a work in progress and doesn't yet handle a lot of edge cases, but it works very well. Place the repulsors on the corners of your vehicle.
using UnityEngine;
using System.Collections;
public class Hover : MonoBehaviour {
public float thrust = 1f;
public float steerThrust = .5f;
public float hoverThrust = 2.5f;
public float diveThrust = .01f;
public float maxHoverImpulseRange = 10f;
private bool accelerate = false;
private bool steerLeft = false;
private bool steerRight = false;
private Transform leftThruster;
private Transform rightThruster;
private Transform noseThruster;
private Transform mainThruster;
private Transform frontLeftRepulsor;
private Transform frontRightRepulsor;
private Transform rearLeftRepulsor;
private Transform rearRightRepulsor;
private Transform[] repulsors;
public bool soaring = false;
void Start () {
leftThruster = (Transform) transform.FindChild("Left Thruster");
rightThruster = (Transform) transform.FindChild("Right Thruster");
mainThruster = (Transform) transform.FindChild("Main Thruster");
noseThruster = (Transform) transform.FindChild("Nose Thruster");
frontLeftRepulsor = (Transform) transform.FindChild("Front Left Repulsor");
frontRightRepulsor = (Transform) transform.FindChild("Front Right Repulsor");
rearLeftRepulsor = (Transform) transform.FindChild("Rear Left Repulsor");
rearRightRepulsor = (Transform) transform.FindChild("Rear Right Repulsor");
repulsors = new Transform[4];
repulsors[0] = frontLeftRepulsor;
repulsors[1] = frontRightRepulsor;
repulsors[2] = rearLeftRepulsor;
repulsors[3] = rearRightRepulsor;
}
void Update () {
TrackInput();
}
void FixedUpdate() {
Move();
RepulseAll();
}
void Repulse(RaycastHit hit, Transform repulsor) {
float distanceToGround = hit.distance;
distanceToGround = Mathf.Min(maxHoverImpulseRange, distanceToGround);
float halfMaxHoverImpulseRange = maxHoverImpulseRange/2;
if (distanceToGround > maxHoverImpulseRange/2) {
rigidbody.AddForceAtPosition(-repulsor.up * ((distanceToGround - halfMaxHoverImpulseRange) / halfMaxHoverImpulseRange) * hoverThrust, repulsor.position);
} else {
rigidbody.AddForceAtPosition(repulsor.up * (halfMaxHoverImpulseRange / distanceToGround) * hoverThrust, repulsor.position);
}
}
void RepulseAll() {
foreach (Transform repulsor in repulsors) {
RaycastHit hit;
if (Physics.Raycast(repulsor.transform.position, -repulsor.transform.up, out hit, maxHoverImpulseRange)) {
Repulse(hit, repulsor);
}
}
}
void TrackInput() {
if (Input.GetKeyDown(KeyCode.UpArrow)) {
accelerate = true;
}
if (Input.GetKeyUp(KeyCode.UpArrow)) {
accelerate = false;
}
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
steerLeft = true;
}
if (Input.GetKeyUp(KeyCode.LeftArrow)) {
steerLeft = false;
}
if (Input.GetKeyDown(KeyCode.RightArrow)) {
steerRight = true;
}
if (Input.GetKeyUp(KeyCode.RightArrow)) {
steerRight = false;
}
if (Input.GetKeyUp("mouse 0")) {
rigidbody.AddForce(new Vector3(Random.Range(-10,10),Random.Range(-10,10),Random.Range(-10,10)) * 20);
rigidbody.AddTorque(new Vector3(Random.Range(-10,10),Random.Range(-10,10),Random.Range(-10,10)));
}
}
void Move() {
if (steerRight) {
rigidbody.AddForceAtPosition(transform.right * steerThrust, leftThruster.position, ForceMode.Impulse);
}
if (steerLeft) {
rigidbody.AddForceAtPosition(-transform.right * steerThrust, rightThruster.position, ForceMode.Impulse);
}
if (soaring) {
//rigidbody.AddForceAtPosition(-transform.up * diveThrust, noseThruster.position, ForceMode.Impulse);
}
if (accelerate) {
rigidbody.AddForce(transform.forward * thrust, ForceMode.Impulse);
}
}
}
You probably want more drag on you object to fix your first problem. If you don't want drag on all the axis then you can implement drag yourself on just the Y axis. This will help it come to rest quicker.
For your second question I'd personally not self right the craft at all until it comes to rest on its side or top. Then once you've detected this state either respawn the craft or start a self-right coroutine or something similar.
Also when implementing the Y axis drag it may even be a good idea to only use it while close to the ground (in range of your hover rays) so the craft falls at a normal rate the rest of the time.
– Antony-BlackettWill try the drag, that sounds like what I need for sure. I kind of have to self-right it or a teeny bump will cause it to just roll over. My thought was to use (transform.up - normal) and apply torque based on that, but it isn't working how I expected it too.
– anon23814272