Unity Physics — Drawing Our Trajectory Prediction

Sean Duggan
3 min readJun 4, 2024

--

So we now have our obstacles moved into our physics simulation scene and rendered invisible. Now, we want to instantiate our projectiles for the simulation. We’ll create a function, SimulatedTrajectory, that will create our projectile and add it to the physics scene.

public void SimulatedTrajectory(AirmailPackage package, Vector3 pos, Vector3 velocity)
{
AirmailPackage instance = Instantiate(package, pos, Quaternion.identity);

if(instance.TryGetComponent<Renderer>(out Renderer renderer))
{
renderer.enabled = false;
}

SceneManager.MoveGameObjectToScene(instance.gameObject, _simulatedScene);

instance.ApplyImpulse(velocity);
}

This is basically the same things that we’ve done before. We’re creating the projectile, making it invisible, moving it to the our physics simulation scene, and then applying the impulse just like we do the regular projectile. We can call this every frame to simulate the current trajectory.

void Update()
{
_simulatedScene.SimulatedTrajectory(_projectile, _originPoint.position, _force * transform.forward);

if (Input.GetKeyDown(KeyCode.Space))
{
AirmailPackage projectile = Instantiate(_projectile, _originPoint.position, _originPoint.rotation);
Debug.Log($"Force of {_force * _originPoint.forward}");
projectile.ApplyImpulse(_force * _originPoint.forward);
}
}

Running this, we get a whole slew of invisible projectiles piling up in the scene. Next, we need to make sure they eventually go away, and also produce a visual indication of their trajectory.

First off, we’ll add a Line Renderer to our launcher object, and create a reference to it in the SimulatedScene script instance. It will initially show up magenta because it doesn’t have a material (and the default material is the built-in rendering pipeline), so we’ll assign a white unlit material to it. Then, all we need to do is, each time we instantiate our projectile and add it to the simulation, set the Line Renderer points to match its position for a number of physics systems interactions. Oh, and then get rid of it since we don’t need it anymore.

// Set the points for the line renderer for the simulated projectiles
_lineRenderer.positionCount = _maxPhysicsInteractions;

for(int i=0; i < _maxPhysicsInteractions; i++)
{
_physicsScene.Simulate(Time.deltaTime);
_lineRenderer.SetPosition(i, instance.transform.position);
}

Destroy(instance.gameObject);

It’s a bit jittery, but we can see that it’s generating the trajectory and shooting the package and shooting it along the path based on our changed force.

There are a few things we can do to improve this. We should generate our simulated path on FixedUpdate, not Update, and using FixedDeltaTime instead of DeltaTime. Lastly, we really don’t need to simulate every frame. Every three frames or so will work just fine.

--

--