Task.Spawn Problem

Hi,
I have some problems using task.spawn(). I need to run the code for every object in the for loop at the same time, but I get it running one after another only if the first object ends executing the code and it may take alot of time. I have The following code bellow if you have any suggestions!

local function regen(player)
	
	local profile = Manager.Profiles[player]
	
	if not profile then return end

	local run = game:GetService("RunService")

	local defVal = player:WaitForChild("def")
	
	local defFolder = game.Workspace:WaitForChild("defFolder")

	local randTime = {}
	
	run.Heartbeat:Connect(function()
		
		for _, def in pairs(defVal:GetChildren())do
			
			task.spawn(function()

				if profile.Data[def.Name].hp < profile.Data[def.Name].maxHp then
					
					if #randTime == 0 then
						table.insert(randTime, os.time())
					end
					
					local diffTime = os.time() - randTime[#randTime]
						
					if diffTime == profile.Data[def.Name].coolDown and def then
						
						profile.Data[def.Name].hp += profile.Data[def.Name].regenEffect

						defVal[def.Name].hp.Value = profile.Data[def.Name].hp
						
						if #defFolder:GetChildren() > 0 then

							defFolder[def.Name].PrimaryPart.regen:Emit()

						end
						
						table.remove(randTime, #randTime)
						
					end
					
				end
				
			end)
			
		end
		
	end)
	
end

I hope I understood correctly, here I send you a code that I hope solves your problem

local function regen(player)
    local profile = Manager.Profiles[player]

    if not profile then return end

    local run = game:GetService("RunService")

    local defVal = player:WaitForChild("def")
    local defFolder = game.Workspace:WaitForChild("defFolder")

    run.Heartbeat:Connect(function()
        for _, def in pairs(defVal:GetChildren()) do
            task.spawn(function()
                if profile.Data[def.Name].hp < profile.Data[def.Name].maxHp then
                    local randTime = os.time()
                    local diffTime = randTime - profile.Data[def.Name].lastRegenTime

                    if diffTime >= profile.Data[def.Name].coolDown then
                        profile.Data[def.Name].lastRegenTime = randTime
                        profile.Data[def.Name].hp = math.min(profile.Data[def.Name].hp + profile.Data[def.Name].regenEffect, profile.Data[def.Name].maxHp)

                        defVal[def.Name].hp.Value = profile.Data[def.Name].hp

                        if #defFolder:GetChildren() > 0 then
                            defFolder[def.Name].PrimaryPart.regen:Emit()
                        end
                    end
                end
            end)
        end
    end)
end

Actually regenEffect is stored in profile service and I don’t change it at all. The problem I have is that the objects from the for loop are not running all at once, they run one after another. Every object has its own values stored in profile service. And I am looping on the object folder to check if their “hp” value is decreasing and then executing the code.

Then use task.spawn outside the loop to parallelize the regeneration process for each object, and may need to ensure that the values specific to each object are captured correctly within the spawned tasks.

local function regen(player)
    local profile = Manager.Profiles[player]

    if not profile then return end

    local run = game:GetService("RunService")

    local defVal = player:WaitForChild("def")
    local defFolder = game.Workspace:WaitForChild("defFolder")

    run.Heartbeat:Connect(function()
        for _, def in pairs(defVal:GetChildren()) do
            local defProfile = profile.Data[def.Name]  -- capture object-specific profile data

            task.spawn(function()
                if defProfile.hp < defProfile.maxHp then
                    local randTime = os.time()
                    local diffTime = randTime - defProfile.lastRegenTime

                    if diffTime >= defProfile.coolDown then
                        defProfile.lastRegenTime = randTime
                        defProfile.hp = math.min(defProfile.hp + defProfile.regenEffect, defProfile.maxHp)

                        defVal[def.Name].hp.Value = defProfile.hp

                        if #defFolder:GetChildren() > 0 then
                            defFolder[def.Name].PrimaryPart.regen:Emit()
                        end
                    end
                end
            end)
        end
    end)
end

I think the problem is that I have the time checking and its just waiting for that to past and then start from the first object again until the task is complete and then jumping to the next one. It annoying because I have to check if the past time is equal with my waiting till regen time and the only way to do it is with os.time() which I have to reset every time the checking is complete, but I think that time is not applying for every individual object. So I have to find a way to do it.

I managed to solve it. It was indeed the time problem. The thing was that I had if #randTime == 0 then. The first object always managed to pass because the condition was true, but for the next one the condition was false because #randTime was not 0 anymore so I changed it like this if #randTime < #defVal:GetChildren() then. Thank you for your time wasted to reply me!

1 Like

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