UnityTest with WaitForSeconds()

Hey Gamers & Game Makers!

I’ve been writing a few test for my new game package and trying to figure out why WaitForSeconds(1) is not waiting for 1 second, hence causing my test to fail.

I would expect WaitForSeconds(1); to cause Time.DeltaTime to move 1 second so my Skill::Recharge method would recharge for 1s…

        public virtual void Recharge()
        {
            // Only recharge if we are not at max charges
            if (currentCharges < maxCharges)
            {
                // Advance the recharge timer... accounting for the recharge booster also.
                rechargeTimer += Time.deltaTime * rechargeBooster;

                if (rechargeTimer >= rechargeValue)
                {
                    currentCharges++;
                    rechargeTimer -= rechargeValue;
                    Debug.Log($"{name} charge gained! Charges available: {currentCharges}");
                }
            }
            else
            {
                rechargeTimer = 0f;
            }
        }

Anything obvious I am doing wrong?

        [UnityTest]
        public IEnumerator Skill_WhenRechargedWithBooster_CanUse()
        {
            // Arrange
            const float booster = 2;
            Skill skill = ScriptableObject.CreateInstance<Skill>();
            skill.Initialize(1, 1, 2, booster);

            // Act
            skill.Use();
            yield return new WaitForSeconds(1);
            skill.Recharge();

            // Assert
            Assert.True(skill.CanUse());
        }

That’s not how that works. Time.deltaTime is how long it’s been since the last frame. At 60fps, you’re only incrementing rechargeTimer by 0.016667 * rechargeBooster. What your code is doing is waiting for a second, doing nothing, then incrementing.

1 Like

why are you expecting delta time be 1 second?

time.deltatime is only time since last frame Id be worried if the time since last frame was 1 second.

You would have to do some form of charge time, so grab the time, see how much time passed, then use that, so in this case the time passed would be 1 second… such as while holding key down time, etc

I guess it’s working in your game because your calling Recharge() from a MonoBehaviours Update(). I like using my own classes when Unit testing so I can mock them. You could use yield return new WaitForSeconds(1) with a mocked MonoBehaviour that calls Recharge() in Update(). You can also use Time.captureDeltaTime which will set Time.DeltaTime after the next update e.g.

Time.captureDeltaTime = 1.0f;
yield return null;
Debug.Log(Time.deltaTime); // 1

I think one issue I’ve had with this in the past is that it didn’t seem to like changing Time.captureDeltaTime more than once.

Thank you guys! I should be good to go now!