Gravity Sim Job System - Video 03 - Updating Acceleration Velocity and Position

YouTube Video #3 - Gravity Series

In this video we look at the math for taking forces and computing acceleration, change in velocity and change in position and then handing that to another job to update transforms for all the GameObjects that are in the gravity simulation. This is done over two jobs.

These two jobs represent the second and third stage in the data processing pipeline that is managed by the GravitySystem (more on that in the next video).

Concept

We need a formula for taking the force vector and turning that into an acceleration vector that is appropriate for that object. The heavier the object (more mass), the slower it should adjust its movement and we see that this bears out with the a = F/m formula.

Code

Here is the code for the two jobs.

GravityAccelerationVelocityAndPositionJob.cs

using Unity.Jobs;
using Unity.Burst;
using Unity.Collections;
using Unity.Mathematics;

using UnityEngine;

[BurstCompile]
public struct GravityAccelerationVelocityAndPositionJob : IJob
{
    [ReadOnly] public NativeArray<float3> Forces;
    public NativeArray<GravityComponent> Bodies;
    public float DeltaTime;


    public static JobHandle Begin(
        NativeArray<float3> newForces,
        NativeArray<GravityComponent> bodies,
        JobHandle dependency
    )
    {
        var job = new GravityAccelerationVelocityAndPositionJob()
        {
            Forces = newForces,
            Bodies = bodies,
            DeltaTime = Time.deltaTime
        };

        return IJobExtensions.Schedule(job, dependency);
    }

    public void Execute()
    {
        for(int index = 0; index < Bodies.Length; index++)
        {
            Bodies[index] = UpdateComponent(Bodies[index], index);
        }
    }

    private GravityComponent UpdateComponent(GravityComponent body, int index)
    {
        body.Acceleration = ComputeAcceleration(index);
        body.Velocity = body.Velocity + ComputeVelocityChange(body.Acceleration);
        body.Position = body.Position + ComputePositionChange(body.Velocity);
        return body;
    }

    private float3 ComputeAcceleration(int index)
        => Forces[index] / Bodies[index].Mass;

    private float3 ComputeVelocityChange(float3 acceleration)
        => acceleration * DeltaTime;

    private float3 ComputePositionChange(float3 velocity)
        => velocity * DeltaTime;
}

TranslationJob.cs

using Unity.Burst;
using Unity.Mathematics;
using Unity.Collections;
using Unity.Jobs;

using UnityEngine.Jobs;

[BurstCompile]
public struct TranslationJob : IJobParallelForTransform
{
    [ReadOnly] public NativeArray<GravityComponent> Bodies;

    public static JobHandle Begin(
        NativeArray<GravityComponent> bodies,
        TransformAccessArray transforms,
        JobHandle dependency
    )
    {
        var job = new TranslationJob()
        {
            Bodies = bodies
        };
        return IJobParallelForTransformExtensions.Schedule(job, transforms, dependency);
    }

    public void Execute(int index, TransformAccess transform)
    {
        transform.position = Bodies[index].Position;
    }
}