Miscalculation with Velocity

Hi, I am trying to make a system that calculates the future path of a moving part. It sounds complicated so let me show you what I mean!

I have a part that is moving around in a circle, it also spins a little. It’s suppossed to simulate a car drifting or something. The parts that you can see in the video are trying to point in the direction that the part is moving in but they’re failing tremendously.

The entire scrips that controls this is here:

local Predictions = 30
local PredictionTime = 10

local Part = workspace.Part

local Points: {Part} = {}

local function CreatePoint(Index)
	local Point = Points[Index] or Instance.new("Part")
	Point.Size = Vector3.one
	Point.Shape = Enum.PartType.Ball

	Point.Anchored = true
	Point.CanCollide = false

	Point.Parent = workspace.Points

	table.insert(Points, Point)
	
	return Point
end

while true do
	local DT = task.wait()
	
	local Velocity: Vector3 = Part.AssemblyLinearVelocity * DT
	local Angular: Vector3 = Part.AssemblyAngularVelocity * DT
	
	for Index = 1, Predictions do
		local Point: Part = CreatePoint(Index)
		
		local Time = (Index / Predictions) * PredictionTime
		
		local Offset = Part.CFrame:ToObjectSpace(CFrame.new(Part.Position + Velocity * Time))
		
		Point.CFrame = (Part.CFrame * CFrame.Angles(Angular.X * Time, Angular.Y * Time, Angular.Z * Time)) * Offset
	end
end

Its definitely a calculation mistake, and since I suck at math I can’t just look at it and tell what’s wrong with it. I believe the procedure is a bit more complicated than what I currently have in my script. But I don’t know :man_shrugging:

All help is appreciated! :slight_smile:

1 Like

Angular velocity is independent of velocity, you don’t want to involve it in your predictions.

If a part was spinning and falling through the air, for instance, you don’t want to involve that spin in your prediction of how it will fall.

Instead calculate and use acceleration by tracking the previous velocity every frame.

Then the position of the part at time Time can be found with

Point.Position = Part.Position + Velocity * Time + 0.5 * Accel * Time * Time

(In this equation, Velocity should not be multiplied by DT. That’s probably most of the issue with your first attempt also)

Note how the orientation doesn’t come into play. If you want to also predict the rotation, it will be the same process, but completely independent.

Edit: forgot to add the initial position

1 Like

Thank you!

But what do you mean by same process? How would I calculate offset depending on the angular velocity?

For reference here is a well made version of what I am trying to achieve:


I sent a DM to the owner of this and he said it had to do with projectile motion calculation, he also sent an image with formulas that he used to get it to work. I have 0 clue to what these are, and I have no idea on how to implement them into the system.

The first equation there is what I posted: given the current position (x_0 in that image / Part.Position in your code), the current velocity (v_x0 / Part.AssemblyLinearVelocity), time (t / Time), and acceleration (a_x / you need to calculate it): you can calculate the predicted position.

You’ll notice the second equation in the right column is almost exactly the same as that one.

That’s because it’s doing the same thing as above, but for rotation. That’s what I meant by “it will be the same process”—It’s the same equation as above but uses orientation/assemblyangularvelocity instead of position/assemblylinearvelocity.

Just to be absolutely clear: the video you posted is not involving orientation or angular velocity at all.

That first equation, as well as calculating acceleration with (velocityLastFrame - velocityThisFrame) / DT, is all you need to calculate those parts positions.

This works really well thank you! But there is still one issue that I don’t know how to fix, its probably really easy to fix but idk, and that is that it glitches a little sometimes as shown in this video:

Nice! Can you share your new code?

My current code is:

local Predictions = 10
local PredictionTime = 1

local Part = workspace.Part

local Points: {Part} = {}

local function CreatePoint(Index)
	local Point = Points[Index] or Instance.new("Part")
	Point.Size = Vector3.one
	Point.Shape = Enum.PartType.Ball

	Point.Anchored = true
	Point.CanCollide = false

	Point.Parent = workspace.Points
	
	if (Index) then
		table.insert(Points, Point)
	end
	
	return Point
end

local RunService = game:GetService("RunService")

local PrevVelocity = Part.AssemblyLinearVelocity

RunService.Heartbeat:Connect(function(DT)
	local Velocity: Vector3 = Part.AssemblyLinearVelocity
	local Acceleration: Vector3 = (Velocity - PrevVelocity) / DT

	for Index = 1, Predictions do
		local Point: Part = CreatePoint(Index)

		local Time = (Index / Predictions) * PredictionTime

		Point.Position = Part.Position + Velocity * Time + 0.5 * Acceleration * (Time * Time)
	end

	PrevVelocity = Velocity
end)

Looks pretty good.

In the CreatePoint function needs a small tweak to the if (Index) stuff:

local function CreatePoint(Index)
	local Point = Points[Index]

	if not Point then
		Point = Instance.new("Part")
		Points[Index] = Point
	end

	Point.Size = Vector3.one
	Point.Shape = Enum.PartType.Ball
	Point.Anchored = true
	Point.CanCollide = false
	Point.Parent = workspace.Points

	return Point
end

Otherwise I think your issue is just roblox’s physics being slightly wobbly, combined with the fact that you’re measuring changes in velocity per frame.

Maybe you could try calculating the average acceleration over the last second or so and try to smooth it out a little?

That sounds like a pain. You could try using Stepped instead of heartbeat (although I would say heartbeat is correct here) and see if that smooths it out. You could also try calculating Velocity directly yourself from the change in position (the same way you calculated acceleration from change in velocity). That might give you smoother results at the cost of some accuracy.