What do you want to achieve? Keep it simple and clear!
Make turret switch and shoot when it sees zombies
What is the issue? Include screenshots / videos if possible!
So the issue is that it locks on the first zombie, right, but then it doesn’t react to other zombies.
Video of what I mean:
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I tried using all my knowledge to fix this issue, none of it helped me.
Code:
local PlayerService = game:GetService("Players")
local Turret = script.Parent
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local HttpService = game:GetService("HttpService")
local ts = game:GetService("TweenService")
local Events = ReplicatedStorage:WaitForChild("Events")
local value = script.Parent.TurretScript.Setting:WaitForChild("Value")
local part = script.Parent.Head
local closestEnemy
local closestDistance = 0
value.Value = false
local Range = 70 -- How far the Turret can see in studs.
local FOV = 90 -- The Turret's FOV
local function GetCharacters()
local Characters = {}
for _, b in workspace.Zombies:GetChildren() do
if b.Humanoid.Health <= 0 then continue end
table.insert(Characters, b)
end
return Characters
end
local function CheckLineOfSight(Start, End)
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Turret, GetCharacters()}
Params.FilterType = Enum.RaycastFilterType.Exclude
local Raycast = game.Workspace:Raycast(Start, End - Start, Params)
if Raycast then
return false
else
return true
end
end
local closestEnemy
local closestDistance = 0
local function FOVCast()
value.Value = false
for _, b in GetCharacters() do
if b then
if closestEnemy then
if closestEnemy.Parent.Humanoid.Health > 0 then
part.CFrame = CFrame.lookAt(part.Position,closestEnemy.Position)
value.Value = true
else
continue
end
else
local NPCToCharacter = (b.Head.Position - Turret.Head.Position).Unit
local NPCLookVector = Turret.Head.CFrame.LookVector
local DotProduct = NPCToCharacter:Dot(NPCLookVector)
local Angle = math.deg(math.acos(DotProduct))
local Distance = (Turret.HumanoidRootPart.Position - b.HumanoidRootPart.Position).Magnitude
if Angle <= FOV and Distance <= Range and --[[Distance < closestDistance and]] CheckLineOfSight(Turret.Head.Position, b.Head.Position) then
local zombiepart = b.Torso
closestEnemy = zombiepart
closestDistance = Distance
part.CFrame = CFrame.lookAt(part.Position,zombiepart.Position)
value.Value = true
else
value.Value = false
continue
end
end
end
end
end
local Casting = coroutine.create(function()
while task.wait() do
FOVCast()
end
end)
coroutine.resume(Casting)
The way it shoots is by changing a variable; if its true, then another script is running.
Your initial script had a few issues that could be considered as making the code somewhat messy.
Redundant Variable Declarations: In your initial script, you declared closestEnemy and closestDistance variables at the beginning of the script and then again later inside the FOVCast function. It’s generally better to keep variable declarations close to where they are used to avoid confusion.
local closestEnemy
local closestDistance = 0
value.Value = false
Unused Variables: You declared local NPCToCharacter and local NPCLookVector in the FOVCast function, but these variables were not used. Unused variables can make the code seem cluttered.
Inefficient Looping: In the FOVCast function, you looped through GetCharacters() to check line of sight for each zombie. Instead, you can directly iterate over the zombies in GetCharacters() without the need for an additional loop.
Redundant CheckLineOfSight Function: You defined a function CheckLineOfSight for raycasting, but Lua already provides workspace:Raycast that you can use directly. The CheckLineOfSight function was redundant and added unnecessary complexity.
Unused task.wait: In your coroutine, you used task.wait without specifying the time to wait, which could lead to unexpected behavior. If you want to yield for a certain amount of time, you should pass a number to task.wait .
Improved Variable Naming: You used more meaningful variable names, such as TurretHead instead of part.
More Efficient Looping: You simplified the looping logic in the targetZombies function, directly iterating over the zombies without the need for a separate function.
Tweening for Turret Reset: You added a tween for resetting the turret to its original position, providing a smoother transition.
Cleaner Code Structure: You organized the code into functions, making it more modular and easier to read.