Trajectory - issue with velocity and precision

Hi,

I’m trying to launch a projectile according to an angle and velocity at launch.
According to the maths, if I launch a projectile with an angle of 50.59 degrees, at a velocity launch of 10m/s, the projectile should land 10 m further.

This is “basic” physics and maths, and it’s confirmed here (Trajectories)

Now my problem is that when I launch a GameObject in Unity with those information, it reaches 9.9m, but not 10m…

On my screenshot:

• in blue the right trajectory
• in white the trajectory of the Gameobject

Here is my code, which is very simple:

``````Vector3 shootDir = Quaternion.Euler (-50.59f, 0, 0) * Vector3.forward; //Direction of the shoot
Vector3 force = shootDir * 10;

GoToLaunch.transform.GetComponent<Rigidbody>().velocity = force;
GoToLaunch.transform.GetComponent<Rigidbody> ().useGravity = true;
``````

The GameObject has an angularDrag of 0, so there is no friction.

It’s been driving me crazy for days now… any idea?

Yes I tried to modify the gravity, but it does not change anything.
The thing is that I use Physics.gravity as a variable for both the estimation and my shoot.

For the blue estimation, I use this formula:
forcet + Physics.gravitytt0.5f

and for the white I just throw the object using the same force and gravity. I used this formula in some previous projects and it was working fine, so I really don’t get why it’s not the case anymore… I am using 5.3.4 if that makes any difference.

If anybody could try this small script I put above and let me know if the object falls at (10,0,0) exactly, or 9.xx like me…

I’ve gone over all the formulas and created a few sample scenarios using [some of my previous systems][1], but haven’t been able to recreate a trajectory which falls short quite like yours have.

Granted, if Unity 5.3.4 is specifically the problem for any reason, I’m using 5.2.3 and wouldn’t be experiencing it in that exact way. On the other hand, I haven’t read anything about changes to PhysX between versions which should effect fundamental frictionless motion.

That said, how are you getting your numbers for distance traveled? In my tests, I launched from (0, 0, 0) to (0, 0, 10) and logged an impact position of (0, 0.02290, 9.90379). Without displaying more numerals [(.ToString(“F5”))][2], I was seeing 0 and 9.9 respectively.

What causes it to not hit exactly on target?

Under Edit>Project Settings>Physics, you will find “Default Contact Offset” – This creates a buffer around objects to help improve efficiency and aids in simulating visual accuracy of most collisions by helping to predict when a collision will occur. However, it will result in imperfections when you’re aiming for exact, precise collisions. Reducing the value can get you closer to an exactly matching result, but it still won’t be spot on.

For reference, my testing script looked like this:

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

public class TestTrajectory : MonoBehaviour
{
Trajectory traj;

void Start()
{
// Your version. Exactly 10 speed on launch
Vector3 versionA = Quaternion.Euler(-50.59f, 0, 0) * Vector3.forward;
versionA *= 10.0f;

// My variant. Aims at a point exactly 10 meters away
Vector3 versionB = Trajectory.HitTargetByAngle(Vector3.zero, Vector3.forward * 10, Physics.gravity, 50.59f);

Debug.Log(versionA.ToString("F5") + " --- " + versionA.magnitude.ToString("F5"));
Debug.Log(versionB.ToString("F5") + " --- " + versionB.magnitude.ToString("F5"));

traj = new Trajectory();
// Custom script -- from, to, gravity, angle
traj.SetTargetByAngle(transform.position, transform.position + Vector3.forward * 10, Physics.gravity, 50.59f);
traj.BuildPath();
}

void Update()
{
if(Input.GetKeyDown(KeyCode.P))
{
// Built inside the custom script
GetComponent<Rigidbody>().velocity = traj.velocity;
}
}

void OnDrawGizmos()
{
// Draw sample -- also from the custom script
if(traj != null && traj.path != null)
{
for(int i = 1; i < traj.iterations; i++)
{
Gizmos.DrawLine(traj.path[i - 1], traj.path*);*
``````
• `````` 	}*
``````
• `````` }*
``````
• }*

• void OnCollisionEnter()*

• {*

• `````` // One collision before launch, one upon landing. Results were reliable.*
``````
• `````` Debug.Log(transform.position.ToString());*
``````
• `````` Debug.Log(transform.position.ToString("F5"));*
``````

To someone who also suffered from this issue.

Actually, the solution is quite simple. You can try to adjust the value of the FixUpdate Timesteps (Edit>Project Settings>Time) and Default Contact Offset (Edit>Project Settings>Physics) parament in a project setting to enhance the physics accuracy.

However, you may encounter a performance issue if you tune the value to too small. So that I recommend you adjust the value via script when you need a precise simulation. Restore the value to default when you dun need it.

For my situation, I am working on a simulation in AR. The whole simulation prefab must be very small (scale = 0.01f). So that I just change the system when I spawn that prefab:

``````    private void SystemInitialize() {
Time.fixedDeltaTime = 0.001f;
Physics.gravity = Vector3.up * gravity;
scaleRef = transformRef.localScale.x;
}
private void OnDisable() {
Physics.gravity = Vector3.up * -9.80f;
Time.fixedDeltaTime = 0.01f;
}
``````