What I’m trying to achieve is a formula for a Projectile Firing Angle to make it go from an Origin Position to a Goal position with a set Initial Velocity and Acceleration.
The issue is the physics calculations aren’t Roblox’s itself, but the module FastCast made by Xan_TheDragon. The module runs basically as a tiny game engine, with a game loop that runs projectile physic calculations, then updates projectile positions, and even checks for hits with RayCasting. The forum post for it can be found here, Making a combat game with ranged weapons? FastCast may be the module for you! .
I’ve asked around and some formulas do exist for real physics calculations and Roblox’s, but my understanding of physics isn’t enough to make a formula for it, especially from the custom physics in FastCast.
A basic rundown of the FastCasts engine is as follows.
You start with a new Cast the main physic inputs being origin, direction, velocity, and acceleration. Then a final Velocity is constructed by multiplying the direction.Unit * velocity. These inputs are then run through a loop I’ve shortened for just the physics portion.
-- This returns the location that the bullet will be at when you specify the amount of time the bullet has existed, the original location of the bullet, and the velocity it was launched with.
local function GetPositionAtTime(time: number, origin: Vector3, initialVelocity: Vector3, acceleration: Vector3): Vector3
local force = Vector3.new((acceleration.X * time^2) / 2,(acceleration.Y * time^2) / 2, (acceleration.Z * time^2) / 2)
return origin + (initialVelocity * time) + force
end
-- A variant of the function above that returns the velocity at a given point in time.
local function GetVelocityAtTime(time: number, initialVelocity: Vector3, acceleration: Vector3): Vector3
return initialVelocity + acceleration * time
end
-- Run in a loop
local function SimulateCast(cast: ActiveCast, delta: number, expectingShortCall: boolean)
delta = 0.01667 -- 1/60th of a second, makes the physics calculations deterministic
local latestTrajectory = cast.StateInfo.Trajectories[#cast.StateInfo.Trajectories]
local origin = latestTrajectory.Origin
local totalDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime
local initialVelocity = latestTrajectory.InitialVelocity
local acceleration = latestTrajectory.Acceleration
local lastPoint = GetPositionAtTime(totalDelta, origin, initialVelocity, acceleration)
local lastVelocity = GetVelocityAtTime(totalDelta, initialVelocity, acceleration)
cast.StateInfo.TotalRuntime += delta
totalDelta = cast.StateInfo.TotalRuntime - latestTrajectory.StartTime -- Recalculate this.
local currentTarget = GetPositionAtTime(totalDelta, origin, initialVelocity, acceleration)
local segmentVelocity = GetVelocityAtTime(totalDelta, initialVelocity, acceleration)
end