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
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:
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)
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.