I am trying to make the most optimized projectile and I am unsure if I should use a tween-based movement or a run service heartbeat projectile. Example codes are shown below. Does anyone know what the difference is and which one is better?
I am trying to make the most optimized projectile and I am unsure if I should use a tween-based movement or a run service heartbeat projectile. Example codes are shown below. Does anyone know what the difference is and which one is better?
why not just give physics a try?
That was my original projectile, but there is stutter with linear velocity unless you set network host of the projectile to the player (bad idea)
i mean you can always make 2 projectiles, one server side, and then once client side…
thats what it already is, i know how to do client server replication but the stutter on the server side makes the projectile less consistent hence I would like to not use physics. also I’m pretty sure most combat games don’t use physics since they’re so bad
Well, I guess then to answer your original question, Either works, but I personally would use TweenService
You need to raycast every single time it steps, so you’ll need to use a heartbeat regardless.
does tweening not altogether remove the need for raycasting?
Yes, but it’s less consistent and you’re better using heartbeats because at that level it’s more efficient. Plus, you can compensate for the framerate by multiplying it by the delta time.
touched events are notoriously wonky (on the server side) and as previously mentioned, tweens really cant compare to just using deltaTime, so your best bet is overlapparams + heartbeat
also, I recommend not worrying about optimization until there are complaints, because usually you wont be focusing on optimizing unless something is majorly wrong
before i did client replication the ping of the server would 4x also I want to optimize since I plan for this game to be successful with many players.
I advise against overlapparams since it’s way less efficient, unless your projectile is a chair or something where collisions matter.
This is what I did three years ago:
local gun = script.Parent
local fireSound = gun.Fire
local reloadSound = gun.Reload
local fireRate = 0.1
local ammo = 25
local damage = 5
local maxAmmo = ammo
local MaxRange = 500
local ReloadTime = 3
local shake = 1 --in degrees
local bulletCount = 1
local reloading = false
local params = RaycastParams.new()
params.IgnoreWater = true
params.FilterDescendantsInstances = {gun}
params.FilterType = Enum.RaycastFilterType.Blacklist
function reload()
if not reloading then
reloading = true
reloadSound:Play()
ammo = maxAmmo
wait(ReloadTime)
reloading = false
end
end
function fire()
if reloading then
return
end
local function r()
return Random.new():NextNumber(-1, 1)*(shake/180)
end
local look = gun.CFrame.YVector
local look2 = (look+Vector3.new(r(), r(), r())).Unit
local up = gun.CFrame.ZVector
local pos = gun.Position+(look*gun.Size.Y/2)
local dir = look2*MaxRange
local result = workspace:Raycast(pos, dir, params)
local part, position = nil, pos+dir
if result then
part, position = result.Instance, result.Position
end
local distance = (position-pos).Magnitude
local bullet = Instance.new("Part", gun)
game:GetService("Debris"):AddItem(bullet, 1)
bullet.Size = Vector3.new(1, 1, 1)
bullet.Anchored = true
bullet.CanCollide = false
bullet.Locked = true
bullet.BrickColor = BrickColor.new("Cool yellow")
bullet.Transparency = 0.5
bullet.Name = "Bullet"
local mesh = Instance.new("BlockMesh", bullet)
mesh.Scale = Vector3.new(.04, .04, distance)
bullet.CFrame = CFrame.lookAt(pos:Lerp(position, 0.5), position)
spawn(function()
for i = 0, 1, 0.01/(distance/MaxRange) do
bullet.CFrame = CFrame.lookAt(pos:Lerp(position, i), pos+dir)
mesh.Scale = Vector3.new(.04, .04, 4)
game:GetService("RunService").Heartbeat:Wait()
end
bullet:Destroy()
end)
fireSound:Play()
if part and part.Parent then
local h = part.Parent:FindFirstChildWhichIsA("Humanoid")
if h and h.Parent.Name~=script.Parent.Parent.Parent.Name then
h:TakeDamage(damage)
local tag = h:FindFirstChild('creator')
if tag then
tag:Destroy()
end
tag = Instance.new("ObjectValue", h)
tag.Name = "creator"
tag.Value = script.Parent.Parent.Parent
delay(2, function()tag:Destroy()end)
end
end
ammo-=1
if ammo<=0 then
reload()
end
end
script.Parent.Parent.Activated:Connect(function()
local activated = true
spawn(function()
while activated do
for i=1, bulletCount do
fire()
end
wait(fireRate)
end
end)
script.Parent.Parent.Deactivated:Wait()
activated = false
reload()
end)
I’ll leave you guys to decipher it.
If the system is designed with optimization in mind in the first place, it will be significantly better to deal with in the future. And you won’t forget about it if people don’t complain.
good point, but I was mostly talking about semantics and like premature optimization (the type of debates where people would argue about using game.ServerScriptService
or GetService
)
added that extra detail bc I would remember times when I wouldn’t even start working on something bc I was so anxious that a small part of it would be slightly unoptimized dark times
sorry for the miscommunication haha