Hi Erik,
Generally you want to structure your program so that general stuff owns specific stuff, e.g.:
- Application has a Game
- Game has a World
- World has several Characters (AI or Player)
- Characters have a Health
...and so on. When information travels in this direction, you can usually just push it in via function calls, e.g. the standard way.
To move information in the other direction, you have several options, including:
- Return values - sometimes you can simply call a function to get a value. e.g. The player object can call Health.GetAmount to find out how much health he or she has left.
- Back-references - occasionally it makes sense for the owner to pass a reference to itself into the object. e.g. The World owns all the Characters, but when it creates them, it might also store itself inside the Character. So the Character can call functions like World.NotifyOfMovement to tell the world it's moved. Circular references like these can be tricky to manage properly in some programming languages and can cause compile errors or memory leaks.
- Events/signals/observers/etc - there are a lot of different names for this concept but usually it allows one object to 'observe' an event, and other objects can notify when the event has happened, and all the observers get that notification. For example, it's common for character animations to have events that trigger when the foot is on the floor, and other parts of the game can subscribe to this event - the audio manager plays a footstep sound when it receives the event, whereas the particle system manager shows a puff of dust.
So in your specific case, there are a few ways to consider:
- Every frame, the Character asks the Health component "am I dead?" by calling a function on it which returns a boolean, or similar.
- Pros: very easy to implement.
- Cons: you don't get notified of the death until the next time you call that update. You might lose information (e.g. if 2 people deal damage, simply asking "Am I Dead" won't give you that information.
- The Health component gets a reference to its owning Character when its created, and when that Health realises it should be dead, it can call a function on the Character to say "hey, we're dead".
- Pros: easy to implement. Death is notified instantly. Function call can contain meta data as an argument (e.g. "who killed me").
- Cons: circular reference could cause problems.
- Health components get an OnDead event, which the owning Character subscribes to. The Health component fires the event when it realises it should be dead, and the Health component gets the notification and handles the event accordingly.
- Pros: Health component doesn't need to know anything about Characters. Other components can subscribe to the event for more flexibility. Event notification can contain meta data as an argument (e.g. "who killed me").
- Cons: More complex to implement. Flow of logic may not be as clear as the previous options.