Hey, Welcome back to my blog series. This is one of the many blogs which i am gonna talk about physics in Unity. In this blog i am gonna demonstrate some simple physics mechanics to move UFO which i have made in blender. You can try this for yourself and i am gonna provide link to my UFO.
UFO fbx model: https://drive.google.com/drive/folders/1DKrHjmHQpwpNBqgf4doUWl2Ws01HnnRa?usp=sharing
OK, Lets come back to Physics. In Unity we can activate physics by adding Rigidbody component. As soon as you add Rigidbody component to an object in unity, forces start acting on the body.
The first and the only force that acts as soon as you add Rigidbody component( and obviously collider) is "GRAVITATIONAL FORCE". This gravitational force acts downward and pulls the body down similar to the real world. Gravitational force is nothing but the force that pulls the body on to the ground. No matter the rotation of the body, gravitational force pulls down the body in negative y axis. Now that we know the direction, what is the magnitude of the force? The magnitude of the gravitation force can be calculated using simple formulae=mass of the body * gravity. In unity we calculate it using (_rigidbody.mass*Physics.gravity.magnitude). Before this we obviously need to get _rigidbody using _rigidbody = GetComponent<Rigidbody>();.
Ok, lets breakdown our UFO physics into different parts.
1. Firstly if you see our UFO, it hovers in the air. That means there is some force which is acting on the UFO which is cancelling our only world gravitation force. This external force F which should obvious act in the direction opposite to gravitation force and its magnitude should also me equal to mass * gravity that is gravitation force magnitude.
Here mg is gravitation force and F is the force we apply in TRANSFORM.UP direction for our UFO to hover or stay in the air. In a very simple terms we are just cancelling gravitation force effect.
The same effect i spiced it up a little bit. All i wanted to do was UFO to maintain a constant altitude from the terrain. So for the i casted a ray in negative y direction of the body and calculated the "HIT" distance. Based on the hit distance i calculated the upward force "F".
Like if the body is too close to ground i applied more force and vice versa.
void HoverUpwardForce()
{
if (Physics.Raycast(transform.position, new Vector3(0, -1, 0), out _hit, 21.0f))
{
test = _hit.distance;
_rigidBody.AddForce(transform.up.normalized * (_rigidBody.mass * Physics.gravity.magnitude) * (20 / _hit.distance), ForceMode.Force);
}
}
in the above code if _hit.distance is 20, the force F counters gravitation force and stays 20 units above the ground always.
2. The second force which we are gonna apply to make UFO move forward, backward, left and right.
Now this is where we use the nature of Physics. To make our UFO move forward/backward or left/right we DON'T apply any forward or left forces. Just tilt your UFO forward in X-axis it starts moving forward. How? The only force we are apply is upward force to cancel out our gravity but how does our UFO move forward?
Let me explain you with a picture. When UFO is tiled, the hoverUpwardForce acts in trasform.up direction which is also tiled. If if spit up the force in forward and up direction, this forward force is taking out UFO forward.
F- is HoverUpwardForce which is acting in trasform.up direction.
Forward - this is forward force which is resultant of angle and equal to Fsin(angle)
up - Fcos(angle).
3. Now that you know tilting produces angle and results in forward force which moves UFO forward, all you need to do is add torque on axis input.
void TiltSidewaysTorque()
{
_rigidBody.AddRelativeTorque(transform.forward * -Input.GetAxis("Horizontal"), ForceMode.Acceleration);
}
void TiltForwardTorque()
{
_rigidBody.AddRelativeTorque(transform.right * Input.GetAxis("Vertical"), ForceMode.Acceleration);
}
Note: Always remember to do all physics operations in LateUpdate().
Here is the entire code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HoverPhysics : MonoBehaviour
{
RaycastHit _hit;
Rigidbody _rigidBody;
// Start is called before the first frame update
void Start()
{
_rigidBody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
HoverUpwardForce();
TiltSidewaysTorque();
TiltForwardTorque();
}
void HoverUpwardForce()
{
if (Physics.Raycast(transform.position, new Vector3(0, -1, 0), out _hit, 21.0f))
{
_rigidBody.AddForce(transform.up.normalized * (_rigidBody.mass * Physics.gravity.magnitude) * (20 / _hit.distance), ForceMode.Force);
}
}
void TiltSidewaysTorque()
{
_rigidBody.AddRelativeTorque(transform.forward * -Input.GetAxis("Horizontal"), ForceMode.Acceleration);
}
void TiltForwardTorque()
{
_rigidBody.AddRelativeTorque(transform.right * Input.GetAxis("Vertical"), ForceMode.Acceleration);
}
}
Comments