Search Unity

Communication between Components

Discussion in 'Scripting' started by SrackinKush, Aug 22, 2014.

  1. SrackinKush

    SrackinKush

    Joined:
    Feb 15, 2014
    Posts:
    4
    Hey guys, I have a question about the actual implementation of communicating between components. This is my first post, so bear with me :)

    I dont have any formal training in programming or game design, but have been programming games for a couple of years now. Lately I felt the urge to move away from class hierarchies, and am now trying to wrap my head around the idea of a component based design. I have read a lot of articles and posts about the subject and feel like I understand the idea behind it. However I am now in a situation where I need to actually code the "register as a client" and "listen for events". Below is an example (because I read the theoretical stuff and it didnt help me).

    I am trying to implement different units into the game right now. In earlier versions this was done by inheriting from a base "Unit" class that did all the moving, collision, etc. With the component-based approach I want to create Components like "Moving", "Health", "ShootProjectile", etc. that can be attached to different units according to their behaviour. I also have a Component called "UnitScript" attached to each Unit, to hold basic data and to be able to store different units in a List<UnitScript>.
    Say the "Moving" Script needs to be informed as soon as the unit is deployed, so it can start moving the prefab around (units can be dragged, at which point moving, collision, etc should not work). The "isBeingDragged" variable sits inside the "UnitScript".

    How should the "Moving" Script go about getting that information from the "UnitScript"?


    My approach (which feels wrong) would be to create a Dictionary that holds a string and a delegate inside every Component. The string is to reference the Event at which all the corresponding delegates will be called.

    Dictionary<string, myDelegate>

    For example the "Moving" Script would add a method to the delegate at the entry "isBeingDraggedChanged" in the dictionary inside the "UnitScript" component. Is the "isBeingDragged" value changed, the "UnitScipt" checks wether any delegates are registered in the list corresponding to it.
    The problem however is that you need a seperate delegate-type for every function that can be called (theoretically). The "isBeingDraggedChanged" for example needs a delegate that holds a bool. Another function might need a string, float, etc. This would end up with a lot of unneccessary code that tightly couples the components together.

    I have never had anyone look over my code, so I am trying to figure stuff out myself. But I really want to do this correctly and not just come up with a semi optimal solution.
    You would help me most with pointing out my errors (e.g. the "UnitScript"; is that too much OO-thinking?) and giving me some code to work off of :)


    SHORT VERSION:
    In a pool of independent components a certain amount of components need to be informed about values changing in other components. No component knows what other components are in the pool before runtime. What's the approach?
     
  2. Zaladur

    Zaladur

    Joined:
    Oct 20, 2012
    Posts:
    392
    Components can talk to each other via GetComponent

    http://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html

    so essentially, if Moving wants to call a function of UnitScript


    Code (csharp):
    1. UnitScript unitScript;
    2.  
    3. void Start(){
    4.     unitScript = GetComponent<UnitScript>();
    5. }
    6.  
    7. private void callUnitFunction(){
    8.     unitScript.somefunction();
    9. }
    10.  
    You should generally cache your components if you need to access them more than once, as too many GetComponent calls in an Update loop can cause some performance issues.
     
  3. SrackinKush

    SrackinKush

    Joined:
    Feb 15, 2014
    Posts:
    4
    First of all thanks for your answer Zaladur!

    I know of the GetComponent<> method :)

    The problem is that I still need to couple all methods that might need information from one another together in code. Like I would with class hierarchies.
    Say a parameter in "Moving" might change depending on a value in "ShootProjectile". I would put a GetComponent<ShootProjectile>() into the "Moving" Script. But what if a unit has "Moving" but not "ShootProjectile" attached? The GetComponent<ShootProjectile>() would be useless and I would also have to write a lot of these dependencies straight into the code. This would not allow me to swap out Components with Components already written for another project, since I'd have to change the code for each Script according to the new situation.

    Hope this makes sense :)
     
    Last edited: Aug 23, 2014
  4. geroppo

    geroppo

    Joined:
    Dec 24, 2012
    Posts:
    140

    watch that (the first 15/20 minutes at least)