Hi all,
I am currently writing some physics prediction code (ballistic trajectory). I have time (flightDuration) and a distance (a simple float). I want to calculate the start velocity for a projectile.
I have the formula and it kinda works. Yet, the point of arrival is always a bit short and I don’t quite get why.
Used formula [1]:

Code: ```
var velocity = distanceVector / time - new Vector3(0, g, 0) * 0.5f * time;
I have created a single code example which you can add to an empty scene and run. It's really bare bones, yet it shows the problem. My expectation was that the white projectiles hit the red target exactly.
However, they are always a bit short. Like this (the white one should be at the position of the red target once it intersects the ground):

[spoiler]
```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysicsPredictionTest : MonoBehaviour
{
private Material targetMaterial;
private Material groundMaterial;
private Material projectileMaterial;
IEnumerator Start()
{
var shader = Shader.Find("Standard");
targetMaterial = new Material(shader);
targetMaterial.color = Color.red;
groundMaterial = new Material(shader);
groundMaterial.color = new Color(0f, 0.7f, 0f);
projectileMaterial = new Material(shader);
projectileMaterial.color = Color.white;
var ground = GameObject.CreatePrimitive(PrimitiveType.Quad);
ground.name = "Ground";
ground.GetComponent<MeshRenderer>().sharedMaterial = groundMaterial;
ground.GetComponent<MeshCollider>().enabled = false;
ground.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
ground.transform.localScale = Vector3.one * 1000f;
var target = GameObject.CreatePrimitive(PrimitiveType.Sphere);
target.name = "Target";
target.GetComponent<MeshRenderer>().sharedMaterial = targetMaterial;
target.GetComponent<SphereCollider>().enabled = false;
target.transform.localScale = Vector3.one * 0.05f;
// Config (we derive the starting speed of the projectiles from these).
float distance = 20f;
float flightDuration = 3f;
// Spawn target
target.transform.localPosition = new Vector3(0f, 0f, distance);
// Spawn projectiles
for (int i = 0; i < 100; i++)
{
yield return new WaitForSeconds(0.1f);
spawnProjectile(distance, flightDuration);
}
}
void spawnProjectile(float distance, float time)
{
var startVelocity = calcStartVelocity(distance, time);
var projectile = GameObject.CreatePrimitive(PrimitiveType.Sphere);
projectile.name = "projectile";
projectile.GetComponent<MeshRenderer>().sharedMaterial = projectileMaterial;
projectile.transform.localScale = Vector3.one * 0.05f;
var collider = projectile.GetComponent<SphereCollider>();
collider.radius = 0.05f;
var rb = projectile.AddComponent<Rigidbody>();
rb.AddForce(startVelocity, ForceMode.VelocityChange);
}
Vector3 calcStartVelocity(float distance, float time)
{
var startPos = Vector3.zero;
var targetPos = new Vector3(0f, 0f, distance);
var distanceVector = targetPos - startPos;
// With this it is always a bit short
float g = Physics.gravity.y;
// With this it is an exact match, even across vast distances (500+). But this does not compute with my brain.
// float g = -9.87f;
// Derived from equation for motion under constant acceleration.
var velocity = distanceVector / time - new Vector3(0, g, 0) * 0.5f * time;
return velocity;
}
}
[/spoiler]
I expected my prediction to diverge from the simulation result on big distances due to floating point inaccuracy but right now it’s always off.
I feel like I am missing something very obvious (Unity 2021.2.0f1, 2022 LTS and 2023, no changes to physics settings)

Thank you.
Update: Just realized I posted it in the Scripting forum. If a mod is nearby maybe this should be moved to the physics forum. Thank you.
9091582–1259326–PhysicsPredictionTest.cs (3.08 KB)


