NPC only plays animation once ever?

So I have a server script that goes in the npc that’s suppose to make it attack the player every little bit, but for some reason the npc will only throw one punch and no more without any code errors. I’ve tried different ways of playing the punch animation but that didn’t work.

Code:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local Debris = game:GetService("Debris")

local function TagHumanoid(humanoid, player)
    local Creator_Tag = Instance.new("ObjectValue")
    Creator_Tag.Name = "creator"
    Creator_Tag.Value = player
    Debris:AddItem(Creator_Tag, 2)
    Creator_Tag.Parent = humanoid
end

local function UntagHumanoid(humanoid)
    for _, v in pairs(humanoid:GetChildren()) do
        if v:IsA("ObjectValue") and v.Name == "creator" then
            v:Destroy()
        end
    end
end

local function GetNearestPlayer(position, maxDistance)
    local players = game:GetService("Players"):GetPlayers()
    local nearestPlayer
    local shortestDistance = maxDistance

    for _, player in pairs(players) do
        local character = player.Character
        if character and character:FindFirstChild("Humanoid") then
            local humanoid = character:WaitForChild("Humanoid")
            local distance = (position - humanoid.Parent.PrimaryPart.Position).Magnitude

            if distance < shortestDistance then
                nearestPlayer = player
                shortestDistance = distance
            end
        end
    end

    return nearestPlayer
end

local function ThrowPunch(npc, actionName, animationId, damage, swingAudioName)
    local Remote = ReplicatedStorage:WaitForChild(actionName .. "Remote")
    local Action = ReplicatedStorage:WaitForChild(actionName)
    local Animation = Instance.new("Animation")
    Animation.AnimationId = animationId

    local function PlayPunch()
        local humanoid = npc:WaitForChild("Humanoid")
        local position = humanoid.Parent.PrimaryPart.Position
        local nearestPlayer = GetNearestPlayer(position, 5)

        if nearestPlayer then
            -- Load and play animation
            local AnimationTrack = humanoid:LoadAnimation(Animation)
            AnimationTrack:Play()

            -- Remote event call
            Remote:InvokeClient(nearestPlayer)

            -- Wait for a break before the next punch
            wait(math.random(1, 6))
        end
    end

    while wait(1) do
        PlayPunch()
    end
end

-- NPC reference
local npc = script.Parent -- Assume this script is placed in the NPC model

-- Setup left punch with Swing2 audio
ThrowPunch(npc, "LeftPunch", "rbxassetid://15479380094", 10, "Swing2")

-- Setup right punch with Swing1 audio
ThrowPunch(npc, "RightPunch", "rbxassetid://15476721938", 8, "Swing1")

Consider using coroutines or task.spawn(function()) threads to embed loops in, otherwise it will block any following code you may have.

1 Like

If you plan on switching between the swing1 and the swing2 punch, consider putting the ThrowPunch() function calls in a loop, and therefore you can get rid of the one in the ThrowPunch() function itself.

Now the npc throws 1 right punch and 1 left punch and stops.

local function ThrowPunch(npc, actionName, animationId, damage, swingAudioName)
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local Remote = ReplicatedStorage:WaitForChild(actionName .. "Remote")
    local Action = ReplicatedStorage:WaitForChild(actionName)
    local Animation = Instance.new("Animation")
    Animation.AnimationId = animationId

    local function PlayPunch()
        local humanoid = npc:WaitForChild("Humanoid")
        local position = humanoid.Parent.PrimaryPart.Position
        local nearestPlayer = GetNearestPlayer(position, 5)

        if nearestPlayer then
            -- Load and play animation
            local AnimationTrack = humanoid:LoadAnimation(Animation)
            AnimationTrack:Play()

            -- Remote event call
            Remote:InvokeClient(nearestPlayer)
        end
    end

    local function PunchLoop()
        while true do
            PlayPunch()
            wait(math.random(1, 6))  -- Wait for a break before the next punch
        end
    end

    -- Start the coroutine
    task.spawn(PunchLoop)
end



-- NPC reference
local npc = script.Parent -- Assume this script is placed in the NPC model

-- Setup left punch with Swing2 audio
ThrowPunch(npc, "LeftPunch", "rbxassetid://15479380094", 10, "Swing2")

-- Setup right punch with Swing1 audio
ThrowPunch(npc, "RightPunch", "rbxassetid://15476721938", 8, "Swing1")

Of course it stops, because (at least it seems to me) that you havent embedded the function calls in a loop, therefore they have no reason to repeat.

-- NPC reference
local npc = script.Parent -- Assume this script is placed in the NPC model

task.spawn(function()
     while task.wait() do
          -- Setup left punch with Swing2 audio
          ThrowPunch(npc, "LeftPunch", "rbxassetid://15479380094", 10, "Swing2")

          -- Setup right punch with Swing1 audio
          ThrowPunch(npc, "RightPunch", "rbxassetid://15476721938", 8, "Swing1")
     end
end)
1 Like

oh my god, I can’t believe I didn’t see that hah!

local npc = script.Parent -- Assume this script is placed in the NPC model

while wait(1) do
	local punchTypes = {"LeftPunch", "RightPunch"}
	local punchType = punchTypes[math.random(1, #punchTypes)]

	if punchType == "LeftPunch" then
		ThrowPunch(npc, "LeftPunch", "rbxassetid://15479380094", 10, "Swing2")
	elseif punchType == "RightPunch" then
		ThrowPunch(npc, "RightPunch", "rbxassetid://15476721938", 8, "Swing1")
	end
end

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