Zombie NPC won't disappear in some players' game [SvZ]

I’m currently working on an upcoming dungeon RPG game called “Swords vs Zombies”. In the tutorial (prologue), the zombies that were killed suppose to be disappeared in 3 seconds. However, some of the game testers reported the game is completely fine but some reported that the zombies won’t disappear which made the game stuck.

I’ve been trying to fix the bug but I still can’t find it. I need help to find the problem. Any feedback would help a lot. Thanks.

Game link:

Zombie died script:

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
DataStore2.Combine("DATA", "level", "xp", "gold")

local Hum = script.Parent:WaitForChild("Humanoid")

Hum.Died:Connect(function()
	for i,v in pairs(game.Players:GetPlayers()) do
		local xpDataStore = DataStore2("xp",v)
   		local goldDataStore = DataStore2("gold",v)
   		xpDataStore:Increment(script.Parent.Data.XP.Value)
   		goldDataStore:Increment(script.Parent.Data.Gold.Value)
   	end
   	wait(3)
   	script.Parent:Destroy()
end)

Pic:

I recommend tracking these errors with Google Analytics. It would take a lot of weight off your shoulders, and you could see the exact server output message. It will group identical errors, and tell you which ones are the most common.

Check out this article:
https://developer.roblox.com/en-us/articles/Using-Google-Analytics#:~:text=Start%20playing%20within%20the%20place,they%20happen%20in%20your%20game.

It’s impossible for a developer to be in every server at once, so catching these rare errors used to be far more difficult before this tool came around!

1 Like

It looks to me that you’re calling a lot of functions that yield, and since these are DataStore functions, they have the possibility to error if Roblox is unresponsive, or if you were reaching the re-entry limit. If they did error, or if the player/their data could not be found, the script will never reach the part of the code that deletes the zombie.

In fact, you are likely to reach the limit in a game where dozens of zombies could be dying at once, since every single time a zombie dies, you run :Increment().

You are likely pushing the throughput limits of Roblox’s DataStores.

The best thing to do would be to keep a record of all the zombies the player has terminated during that session by using a table on the server to store their “session kills”, and then save their new killcount on a timed interval (say, once every 30 seconds). This way, if someone kills 1,000 zombies in 30 seconds, it will not nag your DataStore 1,000 times. Just once :slight_smile:

When it comes to actually deleting the zombie with, instead of calling on yielding functions before destroying the script’s parent, I would instead invoke the mighty power of the Debris Service. You can schedule something for deletion, instead of saving it for the last line.

game:GetService("Debris"):AddItem(script.Parent,10) -- deletes the zombie's remains after 10 seconds.

You would be wise to move the code that adds Gold and XP to a script that’s not kept inside the zombie itself. This way, when the zombie gets deleted, that code can still run if it’s yielding for an exceptionally long time.

Switch out that part of the code for a BindableEvent system, where the zombie Fires a BindableEvent, and another script on the server has a listener function connected to that event. That listener function should contain your :Increment() calls. Make sure to pass all relevant information in the parameters of BindableEvent:Fire() (the player, the type of zombie, etc) when you :Fire() the event.

2 Likes

Alright, thanks for helping me find the problem :smiley:

1 Like