Hi,
I have a problem with my trajectory calculations not matching Unity’s physics simulations.
I am working on a trajectory estimator. As I had trouble with a complex ballistic case, I wanted to understand where I was wrong and restarted simple.
I now have a simple case of a ball falling. Initial position is (0;0), initial speed is (0;0) and the only force applied on the ball is its own weight (mass * gravityAcceleration, with gravity acceleration = 9.81 m.s-2) and there is no drag at all.
So, if I am not mistaken, I have a trajectory equation like :
Y_Ball_Position(time) = - 0.5 * gravityAcceleration * time^2
In the meantime, I created a ball, gave it a rigidbody with a mass of 1kg and no drag.
I attached this script to it :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test1 : MonoBehaviour
{
public float gravityAcceleration;
private Rigidbody _ballRb;
private float _mass;
private bool fall = false;
private float _timer = 0;
private void Start()
{
gravityAcceleration = Vector3.Magnitude(Physics.gravity);
_ballRb = this.GetComponent<Rigidbody>();
_ballRb.isKinematic = true;
_mass = _ballRb.mass;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Z))
{//Triggers the fall
fall = true;
}
if (Input.GetKeyDown(KeyCode.E))
{//Resets ball position to (0,0,0)
_ballRb.isKinematic = true;
_ballRb.useGravity = false;
this.transform.position = Vector3.zero;
_timer = 0;
fall = false;
}
}
private void FixedUpdate()
{
if (fall)
{
_ballRb.isKinematic = false;
_ballRb.useGravity = true;
//_ballRb.AddForce(-_mass * gravityAcceleration * Vector3.up);
Debug.Log("time(s) = " + _timer + " | y(m) = " + this.transform.position.y + " | My_y(m) = " + -gravityAcceleration * _timer * _timer / 2); // formula is -0.5gt^2
_timer += Time.fixedDeltaTime;
}
}
}
And here are the results I get :
So “time(s)” is the time elapsed since the beginning of the fall,
“y(m)” is the y position of the ball in the world at time = “time(s)”, based on Unity’s physics
And “My_y(m)” is the estimated position of the ball in the world at time “time(s)”, based on my calculations.
We can see that there is a small difference, but a difference noticeable as I want to achieve high precision.
I also tried with an AddForce to apply the weight myself (see lines 40-41)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test1 : MonoBehaviour
{
public float gravityAcceleration;
private Rigidbody _ballRb;
private float _mass;
private bool fall = false;
private float _timer = 0;
private void Start()
{
gravityAcceleration = Vector3.Magnitude(Physics.gravity);
_ballRb = this.GetComponent<Rigidbody>();
_ballRb.isKinematic = true;
_mass = _ballRb.mass;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Z))
{//Triggers the fall
fall = true;
}
if (Input.GetKeyDown(KeyCode.E))
{//Resets ball position to (0,0,0)
_ballRb.isKinematic = true;
_ballRb.useGravity = false;
this.transform.position = Vector3.zero;
_timer = 0;
fall = false;
}
}
private void FixedUpdate()
{
if (fall)
{
_ballRb.isKinematic = false;
//_ballRb.useGravity = true;
_ballRb.AddForce(-_mass * gravityAcceleration * Vector3.up);
Debug.Log("time(s) = " + _timer + " | y(m) = " + this.transform.position.y + " | My_y(m) = " + -gravityAcceleration * _timer * _timer / 2); // formula is -0.5gt^2
_timer += Time.fixedDeltaTime;
}
}
}
But I got exactly the same results.
It seems that the weight is applied twice on the first FixedUpdate, then it is applied normally but it still carries an offset due to the twice force application in the first FixedUpdate.
Can anybody tell me what I am doing wrong?
