Unfortunately fastcast doesn’t support immediate raycasting but we can achieve that ourselves by raycasting in segments along the projectile motions equation.
I’m assuming the fastcast bullet is client sided with a remote telling the server “Hey I fired” and a remote telling the server “Hey this bullet I fired hit” and the system uses a bullet ID method like @BIackShibe fps framework tutorial credits to him. He uses a math.random method of generating an ID, I’m using HttpService Generate GUID to generate a unique ID (similar methods random number). (For obvious reason client sided = better responsiveness)
This will be the first sanity check of detecting walls which @DevSneed is concerned about, makesure to set raycast params to only detect walls, don’t want to hit anything else during this instantaneous projectile path.
raycastAlongQuadraticPath
--g gravity, v velocity, t time, p initial position
local function projectileMotionEquation(g, v, initialPosition, t)
--See Ego Mooses tutorial on integrating projectile motion equation
return 0.5 * g * t ^ 2 + v * t + initialPosition
end
local function raycastAlongQuadraticPath(g, v, initialPosition, endTime, raycastParams)
local segments = 10*math.round(endTime*3) -- based on default beam adjust if needed
local timeGapIncrements = endTime/segments
local currentTime = 0
for i=1, segments do
local point1 = projectileMotionEquation(g,v,initialPosition,currentTime)
local point2 = projectileMotionEquation(g,v,initialPosition,currentTime+timeGapIncrements)
local direction = point2-point1
local rayResult = workspace:Raycast(point1,direction,raycastParams)
if rayResult then
return rayResult
end
currentTime += timeGapIncrements
end
end
Now the question is how do you find the end time in which the projectile has reached the target?
Personally I use the closest distance between the projectile path and the instance hit position. Assuming the projectile path has been validated by the server already (projectile origin is close to the player and all that).
pointToQuadraticClosestPointAproximation
local bulletExpireTime = 30
local timeIncrementToVelocityRatio = 0.05/1500 -- balance iteration count and velocity speed accuracy
local function pointToQuadraticClosestPointAproximation(point, g, v, initialPosition)
local increment = v.Magnitude*timeIncrementToVelocityRatio
local currentTime = increment --seconds
local curveToPointVector = point-projectileMotionEquation(g, v, initialPosition, 0)
local previousDistance = (curveToPointVector).Magnitude --Measure initial distance
while currentTime < bulletExpireTime do
local vectorDistance = point - projectileMotionEquation(g, v, initialPosition, currentTime)
local newDistance = vectorDistance.Magnitude
if newDistance > previousDistance then
break --already found minimum distance
end
curveToPointVector = vectorDistance
previousDistance = newDistance
currentTime += increment
end
local timeAtClosestDistance = currentTime
return previousDistance, curveToPointVector, timeAtClosestDistance --closest distance that is within bullet expire time
end
You could solve this problem as an optimization problem known as Point Quadratic distance but I don’t want to solve a cubic equation so I’m using this approximate method which guesses until the bullet expires.
Here is an illustration of what it does using beams:
On the client I moved the target closer like an exploiter:
The server will detect this error between the projectile path created and the server object, the threshold will depend up to you. Higher the threshold more forgiving to laggy players but eh it’s your choice.
This function will return the end time when the projectile should hit the instance with some error management because of client-server delays and all that. How you deal with that error is up to you.
Please comment if there are any more sanity checks I should be covering. This will also help my in my game.