Search Unity

How can you get a reference to the player after it is spawned

Discussion in 'Scripting' started by KenClemson, Dec 16, 2016.

  1. KenClemson

    KenClemson

    Joined:
    Oct 6, 2016
    Posts:
    24
    HI in my scene the player is spawned into the scene a second or two after it starts. I have an object that needs to get the position of the player. At the moment I'm using an Coroutine in Start() to wait for some seconds after the player is spawned then get a reference that way, but Im worried iff this gets played on a slow device that it will not get the refrence and cause bad stuff to happen. Is there another way of getting the reference like iff the object was to listen out for the Player to spawn then get its reference ?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class  SomeClass : MonoBehaviour
    5. {
    6.  
    7.     public float loadTime = 5.0f;
    8.     private GameObject player;
    9.  
    10.     void Start()
    11.     {
    12.         player = GameObject.FindGameObjectWithTag("Player");   //first way but throws exception
    13.         StartCoroutine(getPLayer());  //This way works but is a worry, what iff is played on a slow machine and takes longer to load.
    14.        
    15.     }
    16.  
    17.  
    18.  
    19.     IEnumerator getPLayer()
    20.     {
    21.         yield return new WaitForSeconds(loadTime);
    22.         player = GameObject.FindGameObjectWithTag("Player");
    23.     }
    24. }
     
  2. Joboto

    Joboto

    Joined:
    Sep 12, 2013
    Posts:
    64
    Hey Ken,

    There are many solutions to this problem, you are right that the above solution potentially could have an issue.

    It would be improved if it were polling, so if after N seconds the player object is still null then retry after another N seconds and so on. This would be the simple solution that's closest to where you are.

    A more involved approach might be to use an event based System. If you have an object, thats responsibility is to load the player, it could send an event to the component to alert it that the player is ready and available.

    https://unity3d.com/learn/tutorials/topics/scripting/events
    https://docs.unity3d.com/ScriptReference/Events.UnityEvent.html

    Kind Regards,
     
  3. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    You can also flip the dependency. Let the object have a public property (or method) and have the player find the object when he/she spawns, and call that function.

    Pseudocode:
    Code (CSharp):
    1. public class SomeObject
    2. {
    3.     private PlayerObject player;
    4.    
    5.     public PlayerObject Player
    6.     {
    7.         get { return _player; }
    8.         set { _player = value; }
    9.     }
    10. }
    11.  
    12. public class PlayerObject
    13. {
    14.     void Awake()
    15.     {
    16.         ((SomeObject)FindObjectOfType<SomeObject>()).Player = this;
    17.     }
    18. }
     
  4. CrymX

    CrymX

    Joined:
    Feb 16, 2015
    Posts:
    179
    I like to use static classes like this :

    Code (csharp):
    1.  
    2. public static class GameManager : MonoBehavior
    3. {
    4.    public List<GameObject> players = new List<GameObject>();
    5. }
    6.  
    7. public class SomeClass : MonoBehaviour
    8. {
    9.  
    10.  
    11.   void Start {
    12.  
    13.                 //instanciate your player or drag it in the editor in the class GameManager
    14.   // player = Instanciate...
    15.     //GameManager.players.Add(player);
    16.  
    17.    }
    18.  Update()
    19. {
    20.   //use your player
    21.  player =  GameManager.players[0];
    22. }
     
  5. SwagRogerCoolAid

    SwagRogerCoolAid

    Joined:
    Aug 17, 2016
    Posts:
    20
    Add the player tag to your player and then use
    Code (CSharp):
    1. GameObject instance = GameObject.FindGameObjectsWithTag("Player");  
    in your Start();

    It should find any players you spawn into the scene, but it'll only be one. You would have to then add them to some sort of list at a guess so something like
    Code (CSharp):
    1. Playerlist.add(instance);
    if it's a scene where you need to keep track of players.

    Depends what you're using it for tbh.

    I should probably mention that playerList would be a
    Code (CSharp):
    1. List<GameObject> = new List<GameObject>;
     
  6. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Or like this
    Code (CSharp):
    1. public class Player
    2. {
    3.     public static Player instance;
    4.     void Awake()
    5.     {
    6.         instance = this;
    7.     }
    8. }
    Now you can refer to Player.instance from any other script, assuming there only ever is 1 of them. Why did i use Player type instead of GameObject? Because it's much faster to refer then Player.instance.gameObject, instead of Player.instance.getComponent<Player>()
     
    DBarlok likes this.