Unexpected behaviour from timer

I wanted to create an actor that would have a stepped method (a regularly firing infinite loop). This method is intended to run all the time the actor exists, including in the editor. I ended up with this:

using FlaxEngine;
using System.Threading;

namespace testspace;

[ActorContextMenu("New/myClass")]
public class MyClass : EmptyActor
{
    private Timer _timer;
    private bool _disposed = false;

    public MyClass()
    {
        _timer = new Timer(CallbackMethod, null, 0, 1000);
        Debug.Log("started timer");
    }

    private void CallbackMethod(object state)
    {
        if (_disposed) return;
        Debug.Log("step");
    }

    private void Cleanup()
    {
        if (!_disposed)
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }

            _disposed = true;
        }
    }

    public override void OnDisable()
    {
        base.OnDisable();
        Debug.Log("OnDisable");
        Cleanup();
    }

}

When I add an instance of this class to the scene I get two “started timer” and the “Step” debug comes out twice per second.

If I save the scene and reload the project then I only get one “started timer” and one “Step” per second.

If I then delete the instance from the scene I see the “OnDisable” debug, but then I also see the “started timer” debug and “step” continues to log at one per second. Although the instance has now been removed from the scene.

A save of the scene and reload of the project then returns me to the initial state of no instance in the scene and no debug output. It feels as if whenever I create or destroy an instance of MyActor another non-scene instance is created and runs its own timer.

Any thoughts on what I’m doing wrong? Is there a better way to add a regular loop to an actor that will function in the editor (I would prefer not to add a script to the object).

If you change your timer to be created in OnEnable or OnBeginPlay instead of the constructor, does it make a difference?

1 Like

Great thanks, both of those fix the problem.

I wouldn’t rely on the constructor other than setting default values for an object. For gameplay code, I would recommend using those methods.

1 Like