Should we always use Events?

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Should we always use Events?

      So I'm currently implementing a RTS type game (Think Supreme Commander), which can have thousands of units in play.

      In general I like the concept of the Game Event Management system documented in the book, however the book suggests an ActorMove event shoudl be fired whenever an actor (Unit) moves.... in my case I could easily have 1000+ units moving at once, at 60+ frames per second, so that's potentially 60,000 ActorMove events per second.

      Then technically each unit potentially needs to know about other units, so all 1000+ units will need to register for the Move events for all the other units. So for each unit that moves that's 999+ delegate functions that are called.

      All in all this adds up to 60 * 1000 * 1000 = 60 million event delegate function calls per second!

      Of course you could trim this down significantly by making it so that units only register an interest in other units within a certain distance (If you divide the map into a grid or zones then you could have events for Enter\Leave zone, which other units can use to decide if the units are close enough to warrant an interest in the units move events). However, we'd still be talking about pretty large numbers of delegate calls.

      In my case, would it not just be better for each unit to not register for ActorMove events of the other units, and instead in the Units Update method it could access the list of other Units (And their position) and take appropriate action?

      I hope that question makes sense?

      Thanks
      Ben
    • RE: Should we always use Events?

      Yeah, I probably wouldn't create an actor moved event. I don't have one in my own engine either.

      What's the problem you're trying to solve? What kinds of things would you want to do in reaction to an actor moving?

      -Rez
    • RE: Should we always use Events?

      I'm sure the answer is "it depends", but I'm interested in what these guys say.

      I think the strength of events is that you've hid implementation details in a simple interface. So if a character, let's say, dies it doesn't matter if he ran out of hp, fell off a bridge, or died from an instant death spell. You just fire an event instead of repeating all the parts of death like the animation, adjusting the actor list, modifying control groups, and listeners give you a clean way to add these different components. It localized the changes compared to calling a function to do this big group of stuff.
    • With regards to moving specifically, it sounds to me like you're talking about sending a move event just because the character moved. Instead, have you considered (I'm assuming you're thinking about movement events for a particular reason) having a "changed velocity/direction" type event? Instead of saying, "Hey, this character moved," you would instead say, "Hey, this character is now moving right" or "This character is now stopped." You just assume in future frames that the character is doing whatever the last event was.

      This is of course just as easy to inter-change with something more complicated than a simple "Set Velocity" function (e.g. a "Add force" or "add motor" or "add constraint" function) depending on how your movement system works.

      In my case, would it not just be better for each unit to not register for ActorMove events of the other units, and instead in the Units Update method it could access the list of other Units (And their position) and take appropriate action?

      That sounds like an N^2 algorithm. Maybe I've misinterpreted, but it sounds like you're considering an update function that looks like this: for each unit, check all other units. Of course, you might have already considered doing something like this using a spatial partitioning data structure to reduce that N^2 to something smaller (which is kind of what you were alluding to in the previous statement about grids).

      Edit: I guess I'm also confused on what your goal is.

      The post was edited 1 time, last by geshi ().

    • Thanks all for your replies,

      To be honest I too am a little confused about the problem I'm trying to solve. :)

      Basically what I have today works, but it doesn't seem to fit elegantly with the Events system.

      Lets consider one simple case. Basically each unit needs to know if an enemy units comes into range, and if so then attack it.

      Currently my world is divided up into a grid, and each cell on the grid has a list of units within that cell. So when I update a unit it only needs to consider any other units in the same of neighbouring cells (Lets assume that the range of a unit is <= the size of a cell).

      So even if I have 1000 player units and 1000 AI units, for each unit's update I only need to consider nearby units (Maybe just 2 or 3).

      I also have other tricks, such as cells (And their units) off camera are updated less frequently.

      So this all works fine, but it just doesn't feel like its the 'correct' way to do it if you're using an Event based system.

      Maybe I'm just over thinking it?

      Thanks
      Ben

      The post was edited 1 time, last by BenS1 ().

    • After reading my post I think I forgot to make my point clear.

      I don't think it matters what the underlying algorithm is when looking at events. I think the point is to clean up the code when that event occurs and there are many possible reactions to that event. Lets say your code is:

      ...
      // Something happend (moved)
      GridPartitioningRangeThing(MoveArgs);
      }

      To me, that is no different than:

      ...
      // Something happend (moved)
      EventManager->FireEvent(ActorMoved);
      }

      AppropriateClass::ActorMovedListener(args)
      {
      // Get MoveArgs from args
      GridPartitioningRangeThing(MoveArgs);
      }

      The difference happens when you want to extend who cares about that event. The first example would become:

      ...
      // Something happend (moved)
      GridPartitioningRangeThing(args);
      DoSomething1(ApiArgs1);
      DoSomething2(ApiArgs2);
      ...
      }

      In contrast, the second version does:
      ...
      // Something happend (moved)
      EventManager->FireEvent(ActorMoved);
      } // Nothing Changed here!!! I think this is the point!!!

      AppropriateClass::ActorMovedListener(args)
      {
      // Get MoveArgs from args
      GridPartitioningRangeThing(MoveArgs);
      }

      AppropriateClass1::ActorMovedListener(args)
      {
      // GetApiArgs1 from args
      DoSomething1(ApiArgs1);
      }
      ...

      So, when you add a reaction to an event you don't need to change the original code anymore, you just make listeners in the appropriate classes to react to the event.

      At least, that is my opinion on why to use events. It just simplifies code maintenance. The decision to use an event is independent of one particular reaction to the event.

      Edit: After reading this I realize its still vague and the code doesn't really look obvious because it's missing all of the event manager code, but I'm at work and lazy. I think you use events when many things may react to that event.

      The post was edited 2 times, last by DieselMaxPower ().

    • Thanks DMP,

      I guess my point is that currently nothing actually cares about the fact a unit has moved, what things care about is the position of the units (It's irrelevant if they've just moved to that position or they've been in that position for 5 minutes).

      So in my game I have something like:

      Source Code

      1. for (auto& unit : m_Units)
      2. {
      3. auto enemies = GetEnemiesInRange(unit);
      4. for (auto& enemy : enemies)
      5. unit.ShootAt(enemy);
      6. }

      (Very over simplified, but I think you get the idea)

      Sure I can 100% see why to use the Event System for lots of other Event types, but it's just the UnitMoved event that I don't think I need.

      Maybe I just need something like a UnitStartedMoving and UnitStoppedMoving events, as these could be useful for things like the Audio system.

      Thanks again
      Ben
    • Well, I think that code would either get triggered by an event or a process. If you do it every so many frames (or after a certain time) then I think a process would call it. If you do it after some condition is met, I would think an event calls it.

      For what it's worth I have a "cooldown" process, and once it's over it starts an "actor ready" process to stall for the user (or AI) to determine what/how to attack. I think I would fit your code in here. Perhaps the outer loop would disappear since I only compute stuff for ready actors, but I guess that depends on what you want and maybe that would be inefficient. Then, the "attack" or "shoot at" is actually an event for me to update hp and health bars, etc. The end of the "shoot at" event starts the "cooldown" process, and repeat.