Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Why does this incomplete Capture Point script lag so much?

local redcapturemultiplier = 0
local bluecapturemultiplier = 0

script.Parent.Touched:connect(function(hit)
	local player = game.Players:FindFirstChild(hit.Parent.Name)
	local debounce = false
	if player ~= nil and debounce == false then
		if hit.Name == "Torso" then
			debounce = true
			if hit.Parent:FindFirstChild("capture") == nil and hit.Parent.Humanoid.Health > 0 then
				local CaptureValue = Instance.new("StringValue")
				CaptureValue.Name = "capture"
				CaptureValue.Parent = hit.Parent
				print("made value")
				if tostring(player.TeamColor) == "Bright red" then
					script.Parent.Parent.RedsOnPoint.Value = script.Parent.Parent.RedsOnPoint.Value + 1
				else
					script.Parent.Parent.BluesOnPoint.Value = script.Parent.Parent.BluesOnPoint.Value + 1
				end
			end
			debounce = false
		end
	end
end)

script.Parent.TouchEnded:connect(function(hit)
	local player = game.Players:FindFirstChild(hit.Parent.Name)
	local debounce = false
	if player ~= nil and debounce == false then
		if hit.Name == "Torso" then
			debounce = true
			if hit.Parent:FindFirstChild("capture") ~= nil then
				hit.Parent.capture:Destroy()
				if tostring(player.TeamColor) == "Bright red" then
					script.Parent.Parent.RedsOnPoint.Value = script.Parent.Parent.RedsOnPoint.Value - 1
				else
					script.Parent.Parent.BluesOnPoint.Value = script.Parent.Parent.BluesOnPoint.Value - 1
				end
				print("destroy value")
			end
		end
	end
end)

script.Parent.Parent.BluesOnPoint.Changed:connect(function(NewValue)
	bluecapturemultiplier = NewValue
end)

script.Parent.Parent.RedsOnPoint.Changed:connect(function(NewValue)
	redcapturemultiplier = NewValue
end)

local stop = false

while wait(0.9) do
	if script.Parent.Parent.BluesOnPoint.Value > 0 and script.Parent.Parent.RedsOnPoint.Value > 0 then
		stop = true
	end
	if stop == false then
		if script.Parent.Parent.BluesOnPoint.Value > 0 then
			if script.Parent.Parent.CaptureProgress.Value ~= -100 then
				wait(0.1)
				script.Parent.Parent.CaptureProgress.Value = script.Parent.Parent.CaptureProgress.Value + (-1 * bluecapturemultiplier)
				if script.Parent.Parent.CaptureProgress.Value == -100 then
					script.Parent.Parent.Owner.Value = "Blue"
					script.Parent.BrickColor = BrickColor.new(315)
					script.Parent.Parent.Union.BrickColor = BrickColor.new(23)
					script.Parent.Parent.Particles.ParticleEmitter.Color = ColorSequence.new(Color3.fromRGB(0,170,255))
					print("Blue has captured the point!")
				end
				if script.Parent.Parent.CaptureProgress.Value == 0 then
					script.Parent.Parent.Owner.Value = "Nobody"
					script.Parent.BrickColor = BrickColor.new(1001)
					script.Parent.Parent.Union.BrickColor = BrickColor.new(199)
					script.Parent.Parent.Particles.ParticleEmitter.Color = ColorSequence.new(Color3.fromRGB(255,255,255))
					print("Point has been uncaptured!")
				end
			end
		end
		if script.Parent.Parent.RedsOnPoint.Value > 0 then
			if script.Parent.Parent.CaptureProgress.Value ~= 100 then
				wait(0.1)
				script.Parent.Parent.CaptureProgress.Value = script.Parent.Parent.CaptureProgress.Value + (1 * redcapturemultiplier)
				if script.Parent.Parent.CaptureProgress.Value == 100 then
					script.Parent.Parent.Owner.Value = "Red"
					script.Parent.BrickColor = BrickColor.new(21)
					script.Parent.Parent.Union.BrickColor = BrickColor.new(21)
					script.Parent.Parent.Particles.ParticleEmitter.Color = ColorSequence.new(Color3.fromRGB(255,0,0))
					print("Red has captured the point!")
				end
				if script.Parent.Parent.CaptureProgress.Value == 0 then
					script.Parent.Parent.Owner.Value = "Nobody"
					script.Parent.BrickColor = BrickColor.new(1001)
					script.Parent.Parent.Union.BrickColor = BrickColor.new(199)
					script.Parent.Parent.Particles.ParticleEmitter.Color = ColorSequence.new(Color3.fromRGB(255,255,255))
					print("Point has been uncaptured!")
				end
			end
		end
	end
	stop = false
end

This is a script for an FPS I am working on - basically, its a control point that you can capture. For some reason, this server script lags the whole game whenever someone enters the the point. Is there any reason why? I can see it being linked to the while loop, but I don't know whats wrong with it.

1 comment

0

Why do you have the denounce reset immediately after touch? If its the touch event that causes the lag, that would be the problem

2 answers

Try setting some variables and functions. These both increase efficiency hugely.

Main tip for functions by the way: a function should only do one thing, and generally be a few lines long. If it needs to do more, then make two functions.

This script doesn't lag on its own (I tested it in a blank place, though I did comment out the ParticleEmitter lines). For lag, you should look at what else might be running - any other scripts that might be listening to the .Touched event of the control point, of the .Changed of any of the IntValues, etc.

On a separate note, I recommend these changes to improve the quality of your script:

  • Instead of having script.Parent and script.Parent.Parent everywhere, save those values to a local variable (like local parent = script.Parent and local data = parent.Parent, for example). It will make your script easier to work with.
  • You have lines like local debounce = false which make no sense. You don't use this variable, nor would you want to. Debounce is meant to prevent a function from running multiple times simultaneously for a length of time - but your function returns immediately (no 'wait') and isn't recursive, so 'debounce' would never come into play. Further, since you declared it 'local', its value isn't saved between function calls, so it becomes literally useless. You do have that "capture" value that you put into character models which acts like a per-player debounce -- that's a good thing; keep it (and remove the 'debounce' variable).
  • Use HumanoidRootPart instead of Torso if you want to support R15 character models (which don't have a Torso).
  • TouchEnded doesn't always fire (I found this during testing). Ideally, in your .Touched event, you should have a loop (only run it if you create that 'capture' object, and only after you've done everything else) that periodically checks to see if the player left the game, is dead, or if their HumanoidRootPart is at least 0.75*capturePointSize away from the centre of the capture point (the 0.75 is an approximation of the math; math.sqrt(2)*capturePointSize/2 is closer). Do those checks in that order to ensure that the HumanoidRootPart even exists.
  • Use game.Players:PlayerFromCharacter(hit.Parent) instead of local player = game.Players:FindFirstChild(hit.Parent.Name). If you have projectiles in your game, hit.Parent might be nil (which would cause an error), and PlayerFromCharacter is guaranteed to work regardless of what name the character's model is and regardless of what children happen to be in Players (though your line will probably work for your game if you really want it)
  • Consider using constants (ex "local CAPTURE_MAX = 100" near the top of the script - all capitals with underscores in between words is a suggested style for naming constants) so that if you change it later (ex maybe you want players to only have to capture to 20), you need only change it in one place. It also increases readability; compare data.CaptureProgress.Value ~= 100 to data.CaptureProgress.Value ~= CAPTURE_MAX. Specifically, it's easier to understand and verify the logic when using the constant.

This discussion is preserved as it was. New answers, comments, and votes are closed.