What do I want to achieve?
So I’ve been making my own FastCast system that handles projectiles on client for optimisation.
I am currently working with the Heartbeat service on the client side to make a smooth arch for projectiles like grenades.
- What is my issue?
The projectiles are spawning, but they are not following the calculated trajectory and are instead just disappearing. They have not been destroyed and seems to stay in an odd world position.
I’ve got the script to print the projectile’s position and it returns as
0, -3.4028234663852886e+38, 0
I maybe missing an error in my code as so far I haven’t gotten any errors in the outliner.
The only think I believe could be causing the issue is that I am not using the mouse position to get the direction, instead I am using the parts LookVector through this line of code:
local FireCast = workspace.FireCastServer
local Players = game:GetService("Players")
local Weapon = script.Parent.Parent
Plr = nil
local Modual = Weapon.ProjectileTest
local Mode = "Projectile"
local blackList = {}
local gunPos = Weapon.Position
local gunOr = Weapon.Orientation
local distance = Weapon.CFrame.LookVector
local rayPos = {
Origin = gunPos,
Direction = distance
}
while wait(1) do
local Projectile = require(FireCast).new(Mode, Modual, blackList)
task.synchronize()
Projectile:Cast(gunPos, rayPos, Plr)
task.desynchronize()
end
I will send the relevent sections of my script if anyone can see an issue.
Server side sends origin and direction to the client:
local RunService = game:GetService("RunService")
local Debris = game:GetService("Debris")
local BulletEvent = game.ReplicatedStorage.RemoteEvents.BulletEvent
local ProjectileEvent = game.ReplicatedStorage.RemoteEvents.ProjectileEvent
local FireCast = {}
function FireCast.new(Mode, bulletModule, blackList)
-- // Projectile Properties
local newFireCast = {}
newFireCast.Mode = Mode
newFireCast.Module = bulletModule
newFireCast.Params = RaycastParams.new()
newFireCast.Params.FilterType = Enum.RaycastFilterType.Exclude
newFireCast.Params.FilterDescendantsInstances = blackList
-- // Projectile Creation
local Bullet = game.ServerStorage.standIn:Clone()
function newFireCast:Cast(start, ray, player)
local Module = require(self.Module)
--// Raycast Veriables Setup
local function getMousePosition(unitRay, dist)
local ori, dir = unitRay.Origin, unitRay.Direction * dist
local Result = workspace:Raycast(ori, dir, self.Params)
return Result and Result.Position or ori + dir
end
local distance = Module.DropOff
local maxSpread = Module.Max_Spread
local minSpread = Module.Min_Spread
local Destination = getMousePosition(ray, distance)
local Direction = (Destination - start).Unit
local DirectionCF = CFrame.new(Vector3.new(), Direction)
local spreadDirection = CFrame.fromOrientation(0, 0, math.random(0, math.pi * 2))
local spreadAngles = CFrame.fromOrientation(math.rad(math.random(minSpread, maxSpread)), 0, 0)
local finalDirection = (DirectionCF * spreadDirection * spreadAngles).LookVector
if self.Mode == "Projectile" then
BulletEvent:FireAllClients(self.Mode, self.Module, player, start, finalDirection)
end
end
return newFireCast
end
return FireCast
And then projectile is instanced on the client side:
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local BulletEvent = game.ReplicatedStorage.RemoteEvents.BulletEvent
local fxFolder = localPlayer.Character:WaitForChild("FX")
local pbFolder = fxFolder:WaitForChild("PlayerBullets")
local bFolder = fxFolder:WaitForChild("Bullets")
local Projectile = {}
function Projectile.New(Mode, Module, Player)
local newProjectile = {}
newProjectile.Player = Player
newProjectile.Mode = Mode
newProjectile.Module = require(Module)
function newProjectile:Fire(Origin, Goal, Number)
local bulletFolder
local Bullet
local Properties = self.Module.Properties
if self.Player == localPlayer.Name then
bulletFolder = game.ReplicatedStorage.FXs.Bullets.Scripted
else
bulletFolder = game.ReplicatedStorage.FXs.Bullets.Uncripted
end
if self.Mode == "Projectile" then
Bullet = bulletFolder.ProjectilePhysic:Clone()
local Projectile = Bullet.Projectile
Projectile.Position = Origin
if Bullet:GetAttribute("Modual") then
Bullet:SetAttribute("Modual", self.Module.Name)
end
print("Firing Projectile")
if bulletFolder:GetAttribute("Player") == true then
Bullet.Parent = pbFolder
else
Bullet.Parent = bFolder
end
Projectile.CFrame = CFrame.new(Origin, Origin + Goal)
local position = Origin
local speed = self.Module.Speed
local maxDistance = self.Module.DropOff
local gravityMultiplier = self.Module.GravityMultiplier
local gravity = Vector3.new(0, -workspace.Gravity, 0) * gravityMultiplier
local Velocity = position * speed
local Distance = 0
local Connection
Connection = RunService.Heartbeat:Connect(function(deltaTime)
local stepVelocity = Velocity * gravity * deltaTime
local stepDisplacment = (Velocity + stepVelocity) / 2 * deltaTime
Velocity = stepVelocity
print(Projectile.Position)
local nextPosition = position + stepDisplacment
Projectile.CFrame = CFrame.new(nextPosition, nextPosition + Velocity.Unit)
position = nextPosition
Distance += stepDisplacment.Magnitude
if Distance >= maxDistance then
Connection:Disconnect()
end
end)
end
end
return newProjectile
end
return Projectile
If anyone needs more information on my code then please let me know, any help would be appriciated ![]()