Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

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

Asked by 4 years ago

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.

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 Gameplayer365247v2 1055 — 4y

1 answer

Log in to vote
0
Answered by
sleazel 1287 Moderation Voter
4 years ago

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

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! arthurdaniel91 72 — 4y
Ad

Answer this question