Processes

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

    • So, I'm just reading the Main Loop chapter from GCC4, and I am curious about whether or not I fully understand the process and process manager class.

      If I understood correctly, then any process such as physics, rendering, input, AI, etc. Will inherit from the base class such Process. So each inherited class will define the code needed to update its own section.

      The process manager will manage these process and I am making a blind assumption (I know, never make assumptions) that this makes sure each process work cooperatively.

      Please let me know if I've totally lost of the plot with this one.

      Thanks
    • RE: Processes

      This is essentially correct, although the process manager doesn't do anything specific to make sure the processes work well together. It's up to each process to make sure it plays nicely with the others. Unless you're using multi-threaded processes (that comes later in the multiprogramming chapter), you don't really have to worry about.

      The idea of a process is that it's a self-contained chunk of execution as much as possible.

      -Rez
    • I also have a question about processes but it's one that involves the Event system too.At first I thought everything is an event at first and all the handling was done by processes.
      e.g. PLAYER_MOVED and a process doing the moving.
      But as I understand it now that i have read some more some things are handled by the event system and other things are handled in the process system.
      I just want some clarification as to the line between the two.a clear line of when to use one and when the other.

      also processes are created by events right?
    • Processes and events are two totally different things that aren't directly connected.

      Processes are used when you need to do something across multiple frames. For example, moving a character from one point to another. Events are used to decouple systems. For example, it wouldn't make sense for you input system to have any knowledge of your game. Instead, it can send an event without having to know about the receivers. As another example, consider the death of an NPC in an RPG. You need to clean up a bunch of stuff. Rather than having the death system call a bunch of functions from a bunch of other systems, it can just send an event. All the other systems can register for it. Adding a new system that cares about NPC becomes trivial; that system just has to register for the event.

      Processes can be created by events, other processes, or anything else.

      -Rez
    • Would an example of how the 2 decoupled systems interact be something like...

      1) User issues "ThrowGrenade" command

      2) Game logic receives command and creates a "GrenadeThrown" event

      3) Animation system receives "GrenadeThrown" event and kicks off "AnimateThrownGrenade" process

      4) At the end of the "AnimageThrownGrenade" process, it kicks off a "GrenadeExploded" event

      5) This triggers other processes / events and so on...

      ...or is this too granular?
      -bullgoose
    • That's certainly one way to look at it. I think you might be going a bit event heavy though. Remember that events do have a cost, so sending an event to a system that's already tightly coupled to the sender doesn't buy you anything.

      Here's how I'd implement a grenade:

      1) Player hits the 'E' button.
      2) The input system translates this button into a game command.
      3) The input system pushes an event.
      4) The event is caught by the appropriate gameplay system. In this case, I would probably have the player's script representation catch the event. In Teapot Wars, this would be the _player object in ActorManager.lua, around line 111. Of course, a real game probably wouldn't have just the script component, it would likely have a full class for managing the player, of which the player's script object would be a member.
      5) The player object would do some validation, like checking to see if he has enough grenades (this is a purely script concept and shouldn't be in C++).
      6) The player would tell his animation component to animate. The animation component is tightly coupled to the player, so an event isn't necessary.
      7) In my game, I have a single process called AnimationSystem. Every time a new AnimationComponent is instantiated, a weak ref is added to the AnimationSystem. This process is always running and is responsible for updating all animations on all objects. It doesn't know no does it care about any other component or even the actor; it just updates the AnimationComponent's. So in my case, I wouldn't spin up a new process, I'd just set the appropriate animation state in the player's AnimationComponent and the rest gets taken care of.
      8) In the animation definition itself, I'd define keyframes where gameplay effects can happen. In this case, I'd probably have it send an event called SpawnObject which would take the type of object (grenade) as well as things like owner (player), the location (player + some offset), and any velocity information.
      9) This event would be caught by a generic object spawner which would stream in the XML actor definition for the grenade (if necessary; it would likely be cached already) and spawn it. The grenade would be a regular actor with a life of its own. In the script component for the grenade, I'd define the custom grenade behavior. This would probably involve spinning up a process that delayed for some tunable amount of time as well as the explosion process, which I'd attach as a child to the delay process.
      10) The explosion process would send an event to the sound system, destroy the grenade object, and replace it with the explosion particle effect. It would also send an event to the gameplay system called AreaDamage, which would have information like the point of the explosion, the radius, the damage, etc. All this would come from the tuning that was used initially to spin up these processes.
      11) The gameplay system (in Lua) would receive the event, find all effected actors, and damage them appropriately.

      Does that make sense?

      -Rez
    • Yea it does great explanation thanks, though I did have to read through it about 12 times :)

      I like letting the animation system have a weak ref to to an AnimationComponent, cause then all the actor has to do is tell the component to animate, which only involves the component changing it's own state. Then the next time the animation system frames, he takes care of the rest.

      (I guess my only question would be, who was responsible for passing the weak AnimationComponent reference to the animation system?)

      (Just finished 3D Graphics Basics, going to re-read scripting over the next day or 2 because I don't feel like I have a good grasp on it or animation yet, then it's on to shaders).
      -bullgoose

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

    • Originally posted by bullgoose311
      (I guess my only question would be, who was responsible for passing the weak AnimationComponent reference to the animation system?)

      In my engine, there's a registration process. Component processes inherit from a special interface and can register themselves with the Object system as listening for one or more types of component. Whenever a component of that type is created, it notifies any registered component processes, passing in a weak ref. So, to answer your question, the component factory ultimately passes in the weak ref to the animation system, but since it's just going through the ComponentProcess interface, it has no knowledge of the animation system itself. It just knows that it has a bunch of pointers that conform to a particular interface.

      The animation system is responsible for registering itself with the object manager, which it does in its initialization method.

      -Rez
    • Another question on processes.

      While reading the code I found that game logic updates process manager (in the Running state) and all the actors.

      Since processes are designed to fulfill the role of 'over several frames action', why do we need Update on Actor which is called every frame too?

      Theoretically we could have some script component which is updated by the parent actor thus be able to do continuous logic as well. Which things should go into processes and which into component update?
      Looking for a job!
      My LinkedIn Profile
    • Sorry for the late reply, I completely missed your response!

      You're absolutely right! Actors and components shouldn't have an Update() function!

      In my own engine, I have something I call the EntityComponentSystem. This is an object that inherits from Process and can be registered with my ObjectManager to be notified when a particular component is created. When this happens, the system can do whatever it wants. In most cases, a weak ref to the component is added to a list. The EntityComponentSystem is attached to the process manager and it goes through its list, updating each component. If an entity is destroyed, the system just lazily prunes that weak ref from the list on the next update. My AnimationComponent and RenderableComponent are examples of components that are attached to EntityComponentSystem's.

      Not all EntityComponentSystem's behave this way. Several of them have a blank OnUpdate() method and are never attached to a process manager. For example, I have an EntityClickListener component system that has no OnUpdate(). Instead, it responds to input events to see if anything with a clickable component was clicked. There's no need to udpate this component every frame. Most of my components don't even get registered with an EntityComponentSystem. My ScriptComponent is an example of something that's not registered with any EntityComponentSystem.

      So why does Game Coding Complete tick the Actor and Components directly? Because it's a lot easier to understand. Game Coding Complete is not a high-performance game engine, it's a game engine on training wheels designed to teach you the fundamentals of game architecture. Creating the system I described above would have added a lot of complexity and several more layers (GCC doesn't even have an ObjectManager class; it's just a std::map in the game logic) that would have made understanding the core component architecture much more difficult.

      Besides, ticking the actor and components is perfectly valid. Even Unity does it. If you only have a few actors on screen, it's just fine. If you want hundreds of actors, well, you'll need something more sophistocated.

      Oh, one last thing, it's generally not good to tick the scripting system. Worst-case, you could have an update on a very infrequent basis, but my general rule is that script never has a per-frame Update() function. It's just too slow to call into Lua. Calling C++ from Lua is very fast, but the reverse is not true. I tend to call into script with events rather than just updating it. For example, I built a simple simulation game over the Christmas break. In that game, I have the concept of Actions, which exist purely in Lua. An Action is a thing that the entity is doing, which is composed of multiple states. The states are really just phases of the action. So, if the farmer wants to go and maintain a bee hive, he runs the MaintainBeeHive action. The first state in that action is the RouteToObject state. This creates a Primitive, which is a C++ Process that's spun up from script and attached to the gameplay process manager. Once attached, the script returns. The C++ Primitive process is just like any other process. It does the actual A* pathfinding and handles updating the position of the entity each frame. The Action is effectively asleep on the script side. Once the route is complete (or fails), it sends an event back down to script, which advances to the next state. Some states spin up primitives like that, other states just run some Lua code. The point is, Lua is never ticked on a per-frame basis.

      Anyway, the answer to your original question is yes, your instincts are 100% correct.

      -Rez
    • Originally posted by rezination
      You're absolutely right! Actors and components shouldn't have an Update() function!

      Nice to see I'm on the right track! :)

      On that EntityComponentSystem. I suppose you have several systems for each component or group of components (which behave similarly), then you attach some of those systems to the global process manager. Every system receives events for creating/destroying components and handles various component states (e.g. active, paused, resumed). Finally, not all components have corresponding system and live on their own w/o ticking. Your ObjectManager sends events when it creates entities (I like that word more than 'actor' too). EntityComponentSystem's catch those events and do stuff.

      Alright, but I still have some confusion. Imagine that some entity was created with the animation component on it. Then the animation component would generally be ticked until the entity dies, however, obviously, we need to update it only when some animation should be played. How this is handled? By the EntityComponentSystem or something else?

      It seems similar to usual actor ticking. Tick an actor while it's alive, don't tick when it's dead :) And why can't we just keep the list of updatable components on the actor? If an actor doesn't have updatable components, then it's not even updated itself (this leads to the conclusion that we need two lists for actors too, first for the updatable actors, second for passive, actors can go into different lists depending on the game progress). Does this even makes sense? :)

      One way or another, I understand that only C++ systems must be ticked (rendering, audio, pathing, animation etc) and all gameplay scripts must work with events and processes. So the processes in the first place are instruments for creating gameplay, because LUA calls shouldn't be in a tight loop. Is this correct?

      Originally posted by rezination
      Besides, ticking the actor and components is perfectly valid. Even Unity does it.

      Funny enough, but I got the GCC book because I disappointed in Unity after couple of years I worked with it :)
      Looking for a job!
      My LinkedIn Profile

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


    • On that EntityComponentSystem. I suppose you have several systems for each component or group of components (which behave similarly), then you attach some of those systems to the global process manager. Every system receives events for creating/destroying components and handles various component states (e.g. active, paused, resumed). Finally, not all components have corresponding system and live on their own w/o ticking. Your ObjectManager sends events when it creates entities (I like that word more than 'actor' too). EventComponentSystem's catch those events and do stuff.

      That's basically correct.


      Alright, but I still have some confusion. Imagine that some entity was created with the animation component on it. Then the animation component would generally be ticked until the entity dies, however, obviously, we need to update it only when some animation should be played. How this is handled? By the EventComponentSystem or something else?

      This is actually handled by the animation component. The intelligence is in the animation component; all the EntityComponentSystem does is provide the update. The interface is also in the animation component, so setting a new animation state is done through there.


      It seems similar to usual actor ticking. Tick an actor while it's alive, don't tick when it's dead :) And why can't we just keep the list of updatable components on the actor? If an actor doesn't have updatable components, then it's not even updated itself (this leads to the conclusion that we need two lists for actors too, first for the updatable actors, second for passive, actors can go into different lists depending on the game progress). Does this even makes sense? :)

      You certainly could, but then you're ticking every single entity. Maybe this is fine since you assume that every entity needs to render, but in practice, you want this functionality separate. One big reason is that the EntityComponentSystem often needs to know about the actual component itself rather than the base Component interface class. For example, you might have an AI component that is only updated every N seconds. You could write an if statement in your loop, but that means the entity needs to know that it has an AI component, which breaks the engine layering.

      The intelligence of updating should be in the component, but WHEN to update is often in the EntityComponentSystem object. This isn't always the case, but it's a good rule of thumb.


      One way or another, I understand that only C++ systems must be ticked (rendering, audio, pathing, animation etc) and all gameplay scripts must work with events and processes. So the processes in the first place are instruments for creating gameplay, because LUA calls shouldn't be in a tight loop. Is this correct?

      Yes.

      Originally posted by rezination
      Besides, ticking the actor and components is perfectly valid. Even Unity does it.

      Funny enough, but I got the GCC book because I disappointed in Unity after couple of years I worked with it :)[/quote]
      Yeah, Unity does a lot of things in a bad way, but it also majorly simplifies a lot of stuff. It's a great tool for indie developers to get a leg-up.

      -Rez
    • Originally posted by rezination
      One big reason is that the EntityComponentSystem often needs to know about the actual component itself rather than the base Component interface class. For example, you might have an AI component that is only updated every N seconds. You could write an if statement in your loop, but that means the entity needs to know that it has an AI component, which breaks the engine layering.

      The intelligence of updating should be in the component, but WHEN to update is often in the EntityComponentSystem object. This isn't always the case, but it's a good rule of thumb.


      Aha, this actually clears the situation!

      Many thanks for the in-depth explanation. Maybe I'll try to implement this entitycomponentsystem approach as an exercise.
      Looking for a job!
      My LinkedIn Profile
    • Reading further into processes, one thing drew my attention.

      Quote from the book, page 182

      If a process is successful and it has a child process attached, that child will be promoted into the ProcessManager's list. It will get initialized and run the next frame.


      Here's the source of ProcessManager::Update

      Source Code

      1. ...
      2. switch (pCurrProcess->GetState())
      3. {
      4. case Process::SUCCEEDED :
      5. {
      6. pCurrProcess->VOnSuccess();
      7. StrongProcessPtr pChild = pCurrProcess->RemoveChild();
      8. if (pChild)
      9. AttachProcess(pChild);
      10. else
      11. ++successCount; // only counts if the whole chain completed
      12. break;
      13. }
      14. ...
      Display All


      So as we see, when the process completes successfully, it immidiately adds its child to the std::list (that what AttachProcess does).

      As we travel through the collection each loop step we check this

      Source Code

      1. ...
      2. ProcessList::iterator it = m_processList.begin();
      3. while (it != m_processList.end())
      4. {
      5. ...


      As far as I understand if we add the child to the list we will effectively process it this very frame and not the next frame as said above! Adding the child will just move end of the collection further from the current iterator.

      Another issue that if we are on the last item in the process list, this will not hold true! Because we increase iterator before we handle that switch. In this case child of the last element will be processed in the next frame, because current iterator already points to the list end.

      This is the link to the process manager class code:
      code.google.com/p/gamecode4/so…inloop/ProcessManager.cpp
      Looking for a job!
      My LinkedIn Profile
    • You are correct, that looks like a bug. The fix is simple, use push_front() rather than push_back(), although it probably doesn't matter. Process timing isn't meant to be exact and there shouldn't be any side effects from running the child process this frame or next.

      -Rez
    • Process timing isn't meant to be exact and there shouldn't be any side effects from running the child process this frame or next.


      I was afraid of possible case when the process is instant and it has a child and a child has a child... or even the chain is endless (I can't think of any feature which could be done this way for now, however this is possible). If we process everything in the same frame we could get a spike or even halt.

      Well, pushing to the front solves anything anyway! :)
      Looking for a job!
      My LinkedIn Profile
    • Nice catch! I think you get added to the 5th edition beta reader list.
      Mr.Mike
      Author, Programmer, Brewer, Patriot