I’ve had this problem plaguing my game for ages now, and it’s driving me insane that I don’t know how to fix it. The main point of the game is crashing cars, and the crash mechanics I have laid down are fairly solid. The issue is when cars crash into each other, they’re supposed to break apart and explode. Well, it does that, but then it keeps doing it. Sometimes for ever 30 seconds after the actual crash happened.
The script that runs this is as follows (sorry if the formatting is bad, this isn’t the whole script. It’s only the parts that have to do with inter-car collisions)
local connections = {}
for i, v in pairs(car:GetChildren()) do
connections[v] = v.Touched:Connect(function(hit)
onTouched(hit, v)
end)
end
function onTouched(hit, hitter)
if not hit.Parent or not hit.Parent.Parent or hit.Parent.Name ~= "Car" or hit.Parent == car then return end
local function awardMoney()
local cc = player.leaderstats["Crash Cash"]
local isPrem = player.MembershipType
local isVip = player:FindFirstChild("isVip")
if isPrem == Enum.MembershipType.Premium and isVip ~= nil then
cc.Value = cc.Value + (4 * game.Workspace.Assets.CashMultiplier.Value)
elseif isPrem == Enum.MembershipType.Premium or isVip ~= nil then
cc.Value = cc.Value + (2 * game.Workspace.Assets.CashMultiplier.Value)
else
cc.Value = cc.Value + (1 * game.Workspace.Assets.CashMultiplier.Value)
end
end
local yourVel = car.Parent.Config.Velocity.Value
if yourVel >= breakSpeed then
awardMoney()
hit:BreakJoints()
if playSound then
playSound = false
local sound = Instance.new("Sound", hit)
sound.SoundId = smashSounds[rand:NextInteger(1, 2)]
sound.Volume = 0.75
sound:Play()
game.Debris:AddItem(sound, sound.TimeLength + 0.5)
wait(0.1)
playSound = true
end
if yourVel >= explodeSpeed and Explode then
Explode = false
if connections[hitter] ~= nil then
connections[hitter]:Disconnect()
connections[hitter] = nil
end
local f = Instance.new("Fire"); f.Parent = hit
local boom = Instance.new("Explosion")
local sound = Instance.new("Sound"); sound.Parent = hit
boom.BlastRadius = 1
boom.Position = hit.Position
boom.Parent = hit
sound.SoundId = "rbxassetid://142070127"
sound.Volume = 1
sound:Play()
game:GetService("Debris"):AddItem(sound, sound.TimeLength + 0.5)
wait()
Explode = true
end
end
I added a lot of print statements to see what was going on and it’s just wayyyyy too many .Touched events firing all at once to the point the server can’t keep up. Any ideas on how to slow that down a bit?
When creating the touched events for each car part, also create a debounce variable just above the connection within the for loop. In the touched event, check if this debounce variable is false, and if so, change that debounce to true, and trigger whatever effect you want.
Updating a Region3 to constantly match the vehicles CFrame is going to be extremely expensive.
In reality, the best thing to do ( to achieve the perfect effect ) would be to create some kind of collision prediction system. One that can detect the closest two points between two cars, and create damage near those points on both vehicles just before a high speed impact.
EgoMoose’s module is actually pretty efficient and isn’t as expensive as you would think.
Depending on the hitbox’s size, you probably won’t be needing to run it every frame, either.
At a drastic scale maybe every .Stepped or Heartbeat.
As I said before, .Touched is too buggy and easily abused by exploiters.
The best solution if your really worried about performance is using :GetTouchingParts().
Raycasts are actually fairly lightweight depending on their length.
The longer that they are, the more performance they take, so if you just keep the raycasts fairly small (maybe 50 studs at max), you shouldn’t experience any issues.
Compared to region3, the raycasts will win easily.
.Stepped might be a little overkill.
I recommend just experimenting with different times to see what feels good, as I sadly on mobile so I’m unable to test it for you.