Abstract UpdateClass & Invoke event every update. Good practice?

I’ve made an abstract class, which adds an Update method to an UpdateManager as an Action.
The UpdateManager then adds the Action to a Queue, and on every update, an event is invoked for every Action in the Queue.

This means that in every class where I wish to add an Update method, which is called every update cycle. I can just inherit the UpdateObject class, and override the Update(GameTime gameTime) method.

Personally I love this, it’s easy to add an Update method to every class now. But now please tell me if you think this is a viable pattern, or if there’s something fundamentally wrong with this.

public abstract class UpdateObject : IUpdateObject
{
    public UpdateObject(int priority = 100)
    {
        UpdateManager.AddUpdateEvent(Update, priority);
    }

    public abstract void Update(GameTime gameTime);
}
public static class UpdateManager
{
    private static Queue<Action<GameTime>> EventQueue = new Queue<Action<GameTime>>();

    private static List<(Action<GameTime> action, int priority)> UpdateEventsWithPriority = new List<(Action<GameTime>, int)>();

    private static IEnumerable<Action<GameTime>> OrderedUpdateEvents = new List<Action<GameTime>>();

    public static void AddUpdateEvent(Action<GameTime> action, int priority)
    {
        var newEvent = (action, priority);

        // Find the index to insert the new event based on priority
        int index = UpdateEventsWithPriority.FindIndex(eventItem => eventItem.priority >= priority);

        if (index == -1)
        {
            // If no event with higher or equal priority is found, insert at the end
            UpdateEventsWithPriority.Add(newEvent);
        }
        else
        {
            // Otherwise, insert at the appropriate index
            UpdateEventsWithPriority.Insert(index, newEvent);
        }

        OrderedUpdateEvents = UpdateEventsWithPriority.Select(e => e.action);
    }

    //This is called in every Update from Game1.cs
    public static void ProcessEvents(GameTime gameTime)
    {
        foreach (Action<GameTime> action in OrderedUpdateEvents)
        {
            EventQueue.Enqueue(action);
        }

        while (EventQueue.Any())
        {
            var eventAction = EventQueue.Dequeue();
            eventAction?.Invoke(gameTime);
        }
    }
}

Why not just use GameComponent if that’s the style you’re after?

If you’re unaware of it, GameComponent (and DrawableGameComponent) are a part of XNA/MonoGame that do exactly this. You have a class that inherits from them and then add that to your game “components” and it fires their overridden update/draw(if drawable) methods. They also have UpdateOrder/DrawOrder (what you’re calling “priority”).

Basic use is to have your class inherit from either GameComponent or DrawableGameComponent (if you need draw). Write the override functions for Update/Draw/LoadContent/Whatever. In your game class’s constructor, add Components.Add(whateverClassInstance);

Yes I looked into the GameComponent.

I think the Components.Add(whateverClassInstance); part felt “bad”. I like that I can just inherit a class, and that’s it.

Fair enough. Then I’d say for you it is “good practice”. Personally, I think both approaches are too abstract. I prefer to write in all my load/update/draw/etc methods for each class manually. I.e. my game class’s Update method can be read directly like…

player.Update();
someOtherStuff.Update();
checkCollisionsOrWhatever();
etc();

Rather than having to know what Components/UpdateObjects have been added to the process, and in what order/priority.

But this is the beauty of MonoGame. It is just a framework. You write your engine your way :slight_smile:

Alright thank you for your answer. I was mostly writing here, to ensure that I didn’t do something completely wrong.