Search Unity

how to get references to gameobjects from inside a state machine behaviour script.

Discussion in 'Animation' started by ewanuno, May 15, 2020.

  1. ewanuno

    ewanuno

    Joined:
    May 11, 2017
    Posts:
    58
    i'm trying to set some variables on a script on a GameObject from inside a StateMachineBehavior in a state in my animator controller inside a prefab.

    if i create a public Gameobject in the script i cannot drag a gameobject from the scene into it in the inspector.

    Since StateMachineBehaviour inherits from scriptable object i can't use GetComponent and even though its a bad idea, not even GameObject.Find works.( it always returns a null reference)

    How should i be getting references to Gameobjects from inside a StateMachineBehavior?

    or am i going about communicating between the StateMachineBehaviours and GameObjects the wrong way?
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    GameObject.Find should definitely work (but is definitely a bad idea so I wouldn't recommend it).

    I've never used StateMachineBehaviours because the whole Animator Controller system is retarded, but I'm pretty sure all the StateMachineBehaviours methods have an Animator parameter which you can call GetComponent on.
     
    chr832 likes this.
  3. ewanuno

    ewanuno

    Joined:
    May 11, 2017
    Posts:
    58
    in my defense i was going to call GameObject.Find from Awake() and was considering using SharedBetweenAnimatorsAttribute so it would only be called once.

    but it definitely doesn't work.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class OccupySlot1 : StateMachineBehaviour
    6. {
    7.     public GameObject gameObject;
    8.     GameManagerScript gameManagerScript;
    9.     public void Awake()
    10.     {
    11.         Debug.Log("OccupySlot1 awake");
    12.        
    13.         gameManagerScript = GameObject.Find("GameManager").GetComponent<GameManagerScript>();
    14.         if (gameManagerScript != null) Debug.Log("OccupySlot1 found GameManger");
    15.     }
    16.  
    17.     // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
    18.  
    19.     override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    20.     {
    21.         Debug.Log("OccupySlot1 Enter");
    22.         gameManagerScript.slot1 = true;
    23.        
    24.     }
    25.  
    26.     // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
    27.     //override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    28.     //{
    29.     //  
    30.     //}
    31.  
    32.     // OnStateExit is called when a transition ends and the state machine finishes evaluating this state
    33.     override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    34.     {
    35.         Debug.Log("OccupySlot1 Exit");
    36.         gameManagerScript.slot1 = false;
    37.     }
    38.  
    39.     // OnStateMove is called right after Animator.OnAnimatorMove()
    40.     //override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    41.     //{
    42.     //    // Implement code that processes and affects root motion
    43.     //}
    44.  
    45.     // OnStateIK is called right after Animator.OnAnimatorIK()
    46.     //override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    47.     //{
    48.     //    // Implement code that sets up animation IK (inverse kinematics)
    49.     //}
    50. }
    51.  
     
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If GameObject.Find is returning null then that line would cause a NullReferenceException because you are trying to call GetComponent on a null. Are you sure you spelled the name right? Are you sure the object already exists and isn't being created later on? Are you sure it has the right component? Etc. There are loads of reasons not to use Find methods at all.

    If you are going to treat GameManagerScript (why would you put "script" in the name?) like a singleton then you might as well just make it an actual singleton. Give it a
    public static GameManagerScript Instance { get; private set; }
    and have it set
    Instance = this;
    in Awake, then you will be able to access
    GameManagerScript.Instance
    from anywhere.
     
  5. freshBakedPie314

    freshBakedPie314

    Joined:
    Jan 20, 2020
    Posts:
    2
    I know this is late but....try this.
    it looks like you were trying to change a bool parameter...
    So create a parameter in the animator of type bool....using your script that derives from state machine change the bool parameter by using animator.SetBool();
    and then reference that animator in the script deriving from monobehaviour sitting on the gameobject.
    read the bool parameter by animator.GetBool() and set it to the bool you want to change.
    you can do the same with float and int too I belive.

    this is the statemachine code.
    Code (CSharp):
    1.   override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    2.     {
    3.         Debug.Log("OccupySlot1 Enter");
    4.        animator.SetBool("boolName" , true);
    5.  
    6.     }
    this is the gameManager code
    Code (CSharp):
    1. public Animator animator;
    2. bool slot1
    3.  
    4. void Update()
    5. {
    6.      slot1 = animator.GetBool("boolName");
    7. }
    8.  
     
  6. PvsMouli

    PvsMouli

    Joined:
    Jul 30, 2021
    Posts:
    1
    Thank You So Much Man, It Helped A Lot :)