Search Unity

Advice/best practices for interaction between gameobjects

Discussion in 'Scripting' started by dukedirt, Sep 15, 2019.

  1. dukedirt

    dukedirt

    Joined:
    Aug 29, 2019
    Posts:
    3
    I have some superficial experience with c# programming, and understand most of its syntax. I probably should have done more research before making this post, but I was hoping for a pointer in the right direction from someone who has used unity.

    What is the best way to interact with another gameobject's custom variables from a current behavior script? I've seen people use 'GameObject.Find("foo").GetComponent(bar).DoSomething()', and I saw a section on the messaging system in the unity manual.

    Say in a basic pong game, I have a script for the score textbox. When the ball hits the "Finish" collider, I want the score to go up. What's the best way to do this?

    Thanks in advance for any replies and sorry if this is a stupid question or asked in the wrong place.
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    The best practice depends a bit on the type of interation we are talking about.
    If we are, for example, talking about the collided gameobjects in some collision, then you get that from the collider and can work with it inside of the current scope. So that's the obvious case.
    When we are talking about a bit more permanent relation between gameobjects, say for example an object that orbits around another object, then you'd most likely end up assigning the other gameobject to a public variable of the script through the inspector.
    In some other cases a Manager / Controller class is responsible for handling interactions between specific gameobjects.
    (Also used for performance reasons sometimes, since lots of Monobehaviors tend to get slow)

    If at all possible, i'd avoid using GameObject.Find(). It's mostly for quick prototyping imho. If you have to use it, make sure you only use it in Start() and, if at all possible, never in Update(), since it's a quite expensive operation.

    For the Pong collider example, i'd probably assign a script to the collider object that has a reference to the textbox. When the ball hits the collider, the script handles despawning (or replacing) the ball to its new position, incrementing the score, updating the textfield and then starting the next round or something like that.
    As long as you get what you want, most approaches are fine tho. Some are just a bit less performant than others, and some may be preferable in specific situations.

    Hope this helps.
     
  3. dukedirt

    dukedirt

    Joined:
    Aug 29, 2019
    Posts:
    3
    Thanks, that definitely helps.
     
  4. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    You most basic way is to use a static event:

    FinishScript:
    Code (csharp):
    1. public static event Action OnHit;
    2.  
    3. void OnTriggerEnter(Collider collider)
    4. {
    5.     OnHit?.Invoke();
    6. }
    'ScoreText' script:
    Code (csharp):
    1. int score;
    2. Text guiText;
    3.  
    4. void OnEnable()
    5. {
    6.     FinishScript.OnHit += UpdateText; // Run UpdateText when OnHit is invoked.
    7. }
    8.  
    9. void OnDisable()
    10. {
    11.     FinishScript.OnHit -= UpdateText;
    12. }
    13.  
    14. void UpdateText()
    15. {
    16.     score++;
    17.     guiText.text = score.ToString();
    18. }
    Ideally your UI script would be referencing a score script (the score data has no business being inside a UI script). There are many other ways to do it. Score could even be a ScriptableObject which means it's easier to reference and could avoid some coupling.
     
    brohr likes this.