Multiple raycasting being a lot more expensive than usual, what is going on?

What I’m trying to code here is a “shotgun shell” for a cannon, name being a canister shot. How I’ve created it is having a table that indexes all of the actual bullets, then for every frame calculate each shot by iterating over a table. (Key of the table is the bullet, value of the table is the actual velocity) IMO this seems quite resource heavy but I really don’t know what else to do. This is done on the server side.

My problem is, I have a quite large game; the place itself starts with a heartbeat delta time of 60 fps, and whenever I fire a canister shot the heartbeat time (or whatever it is called) drops significantly to about 20fps, and causes the bullet trajectory to slow down. Does anyone else have any advice on how to remedy this? (but on my separate place (which is bare and just the cannons), there is no distinct delta time drop when the canister is fired) If you need more info please let me know, elsewise if this is just a game thing that can’t be changed let me know as well

	for i=1,30 do
		local InaccuracyFactor = Muzzle.CFrame:VectorToWorldSpace(Vector3.new(math.random(-40,40)/100,math.random(-40,40)/100,math.random(-10,10)/100))
		local Velocity = (Muzzle.CFrame.LookVector) * 10 + InaccuracyFactor
		local newpart = CanisterRoot:Clone()
		newpart.Parent = CanisterModel
		newpart.Orientation = Muzzle.Orientation 
		newpart.Position = Muzzle.Position
		CanisterList[newpart] = Velocity
	end

	coroutine.resume(coroutine.create(function()
		local StartTick = tick()
		repeat
			RunService.Heartbeat:Wait()
			for Part,Vel in pairs(CanisterList) do
				local ray = Ray.new(Part.Position,Vel)
				local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, IgnoreList)
				Part.Position = position
				CanisterList[Part] = Vel - Vector3.new(0,.1,0)
				if hit and hit.Parent:FindFirstChild("Humanoid") then
					HandleCanisterDamage(position, hit, Occupant)
					CanisterList[Part] = nil
					Part:Destroy()
				end
				if hit and hit.Name ~= "CanisterHitDirt" and hit.CanCollide and not hit.Parent:FindFirstChild("Humanoid") then 
					HandleCanister(position)
					Debris:AddItem(Part, 10)
					CanisterList[Part] = nil
				end
			end
		until tick() - StartTick >= 10
		for i,v in pairs(CanisterList) do
			Debris:AddItem(i, 10)
			CanisterList[i] = nil
		end
	end))
1 Like

Two things.

  1. Possible solution: Do the raycasting on the client-side. This is also good because if you have many players the raycasting lag on the server, which is small by itself, could really add up.
  2. I have run into this problem myself with my projectile guns, where the bullet lags and doesn’t move smoothly (I used BodyVelocity). A solution to this is to insert a script into the bullet which changes the CFrame quickly (or lerp the CFrame, never tried that), but that adds an ugly curve to the bullet if it has mass. Eventually, I just made the shot instantaneous with a “trail” part.

-Scepter_ofDarkness

I have indeed considered doing the raycasting on the client side however it posed a few problems which stuck out to me. One of them being that an exploiter could easily manipulate the raycast and do something with the remote events tied with it. The other being that the raycast would be dependent on the client’s machine; meaning if someone with a potato computer is firing the cannon and has shoddy FPS, it would be reflected in game. I will have to find a different solution for this.

2 Likes

Hi, cooldeath!

THE LAG
Could it be because you’re raycasting as fast as Roblox can handle (renderstepped.Heartbeat:wait() , which is lagging the game? Try raycasting only once and tell me if that solves the lag issue

Making it harder to exploit
As somebody once said on a similar problem:

Client raycasts are apparently more accurate, so you should consider doing that.

I’m raycasting multiple raycasts to simulate “bullet drop”, multiple small rays combined together simulate bullet drop. I will see this article.

1 Like