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

Script works fine on studio play mode, but breaks partially when in-game?

I am making a tower defense style game, and I made a minigunner tower for testing. But I am having a big problem.

On studio play mode, the tower's script works perfectly fine. But when in-game or on studio test mode, it breaks partially and the shoot() function doesn't fire for some reason.

Script:

--//Services
local players = game:GetService("Players")
local debris = game:GetService("Debris")

--//Variables
local tower = script.Parent.Parent

local towerHumanoidRootPart = tower:WaitForChild("HumanoidRootPart")
local humanoid = tower:WaitForChild("Humanoid")
local minigun = tower:WaitForChild("Minigun")

local storage = tower:WaitForChild("Storage")

local animations = storage:WaitForChild("Animations")
local idleAnimation = animations:WaitForChild("Idle")

local soundEffects = storage:WaitForChild("SoundEffects")
local gunshotSFX = soundEffects:WaitForChild("GunshotSFX")

local statistics = require(storage:WaitForChild("TowerStatistics"))
local range = statistics["Range"]
local fireRate = statistics["FireRate"]
local damage = statistics["Damage"]

--//Functions
local function generateRangeMarker()
	local rangeMarker = Instance.new("Part")
	rangeMarker.Anchored = true
	rangeMarker.CanCollide = false
	rangeMarker.CFrame = towerHumanoidRootPart.CFrame *CFrame.new(0, -1.75, 0) *CFrame.Angles(0, 0, math.rad(90))
	rangeMarker.Size = Vector3.new(.1, range * 2, range * 2)
	rangeMarker.BrickColor = BrickColor.new("Deep blue")
	rangeMarker.Transparency = .5
	
	local rangeMarkerMesh = Instance.new("SpecialMesh", rangeMarker)
	rangeMarkerMesh.MeshType = Enum.MeshType.Cylinder
	
	rangeMarker.Parent = tower
end

local function startAnimation()
	wait()
	humanoid:LoadAnimation(idleAnimation):Play()
end

local function shoot() --//The function that breaks when in-game.
	while wait(fireRate) do
		local playerList = players:GetPlayers()
		
		for i = 1, #playerList do
			local target = workspace:FindFirstChild(playerList[i].Name)
			if not target then return end
			
			local targetHumanoid = target:FindFirstChild("Humanoid")
			if not targetHumanoid then return end
			
			local targetHumanoidRootPart = target:FindFirstChild("HumanoidRootPart")
			if not targetHumanoidRootPart then return end
			
			local magnitude = (towerHumanoidRootPart.CFrame.p - targetHumanoidRootPart.CFrame.p).magnitude
			
			if magnitude < range then
				towerHumanoidRootPart.CFrame = CFrame.new(towerHumanoidRootPart.CFrame.p, targetHumanoidRootPart.CFrame.p)
				towerHumanoidRootPart.Orientation = Vector3.new(0, towerHumanoidRootPart.Orientation.Y, towerHumanoidRootPart.Orientation.Z)
				
				targetHumanoid:TakeDamage(damage)
				
				local newGunshotSFX = Instance.new("Sound")
				newGunshotSFX.Name = "ClonedGunshotSFX"
				newGunshotSFX.SoundId = gunshotSFX.SoundId
				
				newGunshotSFX.Parent = minigun
				newGunshotSFX:Play()
				
				debris:AddItem(newGunshotSFX, 1)
			end
		end
	end
end

--//Callers
generateRangeMarker()
startAnimation()
shoot() --//The caller for the shoot() function.

This is the 3rd/4th time I am asking this, I didn't get a answer on the other times I asked this same question.

1 comment

0

im not gonna get fully in to this but maybe one thing that u can change and probably should change too is when u got magnitude checks, dont check using CFrame, check using HumanoidRootPart.Position

1 answer

✓ Accepted answer

This lines:

if not target then return end
if not targetHumanoid then return end

are ending your function completely rather than restarting the loop. You can either replace return with break that will break the for loop, or nest your code few more times, like this:

for i = 1, #playerList do

	local target = workspace:FindFirstChild(playerList[i].Name)
	if target then 

		local targetHumanoid = target:FindFirstChild("Humanoid")
		if targetHumanoid then 

			local targetHumanoidRootPart = target:FindFirstChild("HumanoidRootPart")
			if targetHumanoidRootPart then 

				local magnitude = (towerHumanoidRootPart.CFrame.p - targetHumanoidRootPart.CFrame.p).magnitude

				if magnitude < range then
				
					towerHumanoidRootPart.CFrame = CFrame.new(towerHumanoidRootPart.CFrame.p, targetHumanoidRootPart.CFrame.p)
					towerHumanoidRootPart.Orientation = Vector3.new(0, towerHumanoidRootPart.Orientation.Y, towerHumanoidRootPart.Orientation.Z)
					targetHumanoid:TakeDamage(damage)

					-- TIP :this code below should be outside while loop as it needs to run just once
					local newGunshotSFX = Instance.new("Sound")
					newGunshotSFX.Name = "ClonedGunshotSFX"
					newGunshotSFX.SoundId = gunshotSFX.SoundId

					newGunshotSFX.Parent = minigun
					--end of just once code
					newGunshotSFX:Play()

					debris:AddItem(newGunshotSFX, 1) --not needed when you use my tip
				end
			end
		end
	end
end
 

1 comment

0

Living legend. Thanks alot man! I was having this issue for a very long time and I am glad to have finally fixed it. Cheers!

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