Someone help make this code more optimized please

local Turret = script.Parent.Turret

while task.wait(0.035) do
	local Player = Players:GetPlayers()
	local playerTable = {}

	for Index, Value in pairs(Player) do
		pcall(function()
			if Value.Character:FindFirstChild("Humanoid") and Value.Character.Humanoid.Health > 0 then
				table.insert(playerTable, #playerTable+1, Value.Character)
			end
		end)
	end

	local VisionDistance = 150
	local Target

	for _, Value in pairs(playerTable) do
		local Humrp = Value.HumanoidRootPart
		local Distance = (Humrp.Position-Turret.Cube.Position).Magnitude
		local RayParams = RaycastParams.new()
		RayParams.FilterType = Enum.RaycastFilterType.Exclude
		RayParams.FilterDescendantsInstances = Turret.Parent:GetDescendants()

		local CanSee = workspace:Raycast(Turret.Cube.Position, (Humrp.Position-Turret.Cube.Position).Unit*VisionDistance, RayParams)

		if Distance < VisionDistance and CanSee and CanSee.Instance:IsDescendantOf(Value) then
			Target = Humrp
			VisionDistance = Distance
		end
	end	

	if Target then
		print("target found")
		Turret.Cube.CFrame = CFrame.new(Turret.Cube.Position, Target.Position)
	elseif not Target then
		print("no target")
	end
end

This code is fully functional, but it lags my game, I can only imagine how bad it would be if multiple players spawned in a turret like this… So what I want to do is optimize the code so it doesn’t lag my game. I was thinking instead of using a while true loop, maybe do Players.PlayedAdded for the player table, and a run service when it finds a player to rotate the turret towards the player, I don’t really know how to do that, does anyone mind helping me out?

2 Likes

There may be more but here’s a list of things you could fix/modify

  • Use one of the RunService events as opposed to an infinite wait loop (probably Heartbeat)
  • Separate the player target table from the loop
    • Realistically, you don’t need to update the list every every frame, just whenever a character is modified/a change to the list would need to be made. (ex: A player dies, a new character is added)
  • In addition to that last note, remove the GetPlayers from the main loop
  • Move the RayParams establishment outside of the loop. (and FilterType =)
    • You don’t need to make a new RayParams every frame, just to update the FilterDescendantsInstances value of it
  • Although it’s slightly more work than the other optimization methods and won’t provide as much as a payoff…
    …You could disable CanQuery on all of the accessory BaseParts on all the characters, subsequentially exempting them from the raycast, and swap out IsDecendantOf(Value) to a Parent == Value comparison

tldr; use more events and move non-changing variables outside of the loop

1 Like

Removing the :GetPlayers() from the loop, how would i add another player to the table when a new one joins… I know there’s Players.PlayerAdded() but I wouldn’t know how to implement that.

Something like this:

-- services
local Players = game:GetService("Players") -- Just getting the service
-- variables
local targetList = {} -- List of all the characters to be targetted
-- logic
Players.PlayerAdded:Connect(function(addedPlr)
	addedPlr.CharacterAdded:Connect(function(addedChar)
		targetList[addedPlr] = addedChar -- Uses the addedPlr as the index for the character, so it can be easily removed later
	end)
end)
Players.PlayerRemoving:Connect(function(removingPlr)
	targetList[removingPlr] = nil -- Removes any previously stored character of the leaving player
end)

You can also use events like CharacterRemoving, Humanoid.Died, or Instance.Destroying on the character to determine if the character/character root needs to be removed from the target list.

I recommend looking into learning events if you’ve yet to, they’ll change your life.

edit: if the code’s local then you’d want to connect the added event & then sort through all the already existing players, incase a player joins later

Let’s say a character dies, and i do

Character.Humanoid.Died:Connect(function()
      --remove player from list--
end)

how would I place him back into the table when he respawns?

CharacterAdded gets fired whenever a character respawns as well, or should at least. I believe calling Player:LoadCharacter() may not fire CharacterAdded but I’m unsure off the top of my head

Yeah but the character added only gets called when a player gets added.

I’m unsure of what you’re trying to say

You’re saying that CharacterAdded gets fired whenever a character respawns as well, but in the script character added is only being called when a player is added, so if a player is added and it dies, when it respawns the characteradded event wont fire.

The CharacterAdded event is an event attached to the Player, not the Players service

" The CharacterAdded event fires when a player’s character spawns (or respawns). This event fires soon after setting Player.Character to a non-nil value or calling Player:LoadCharacter(), which is before the character is parented to the Workspace."

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.