Attempt to call nil error

  1. What do you want to achieve? Keep it simple and clear!
    An intermission system.

  2. What is the issue? Include screenshots / videos if possible!
    An “attempt to call nil” error comes up in the output and it doesn’t say where the error is being generated in.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried changing up some things but they didn’t work. Everything seems fine in my opinion.

Here is the code:

local CountdownInitiatedEvent=game.ReplicatedStorage.CountdownInitiatedEvent
local CountdownTimeCoroutine=coroutine.wrap(function(CountdownTime,Desc)
	for Time=CountdownTime,0,-1 do
		CountdownInitiatedEvent:FireAllClients(Time,Desc)
		print (Time)
		wait(1)
	end
end)

function StartRound(CountdownTime)
	CountdownTimeCoroutine(CountdownTime,"round in progress...")
end

function CallIntermission()
	CountdownTimeCoroutine(60,"Intermission")
end

CallIntermission()
wait(60)
print "Intermission Ended!"
StartRound(360)

The time comes up as normal and the “Intermission finished” print sign even comes up so I know the problem is with the StartRound function. I am sure that the error is in this script because it occurs only once the timer finishes and it is a server-generated error. If somebody with more experience could help it would be nice.

1 Like

I think you misunderstand the usage of that coroutine.wrap.

Here is a simple example, that resembles your code, that shows the problem.
Try to run this, and study what occurs in the Output-panel.

local coFunc = coroutine.wrap(function(a)
  print(a)
  wait(1)
  print("done")
end)

coFunc("first call")
wait(2) -- <-- Also try change this to wait(0.5), and see what then happens.
coFunc("second call")

Your “attempt to call nil” error, can be achieved in the above example, by changing the wait(2) to wait(0.9) or lower.


May I suggest that you use spawn() instead, and possibly with support for an “when finished, then call this method”-feature, which can be used to “chain” what should happen after the for-loop has finished:

local function CountdownFunc(countdownTime, desc, whenFinished)
  spawn(function()
    for count=countdownTime,0,-1 do
      CountdownInitiatedEvent:FireAllClients(count,desc)
      print(count)
      wait(1)
    end
    if nil ~= whenFinished then
      whenFinished()
    end
  end)
end

CountdownFunc(
  60,
  "Intermission",
  function()
    print("Intermission Ended!")
    CountdownFunc(
      360,
      "round in progress...",
      function()
        print("Round Ended!")
      end
    )
  end
)
2 Likes

I read your script and have understood what you mean. Basically tour saying that coroutines aren’t simple and can have lots of issues so I should use the spawn() function instead? Thanks for helping! I think it would actually be easier to use it.

1 Like