Search Unity

How properly call function from another script?

Discussion in 'Scripting' started by Nibernator, Jan 14, 2019.

  1. Nibernator

    Nibernator

    Joined:
    May 25, 2018
    Posts:
    11
    I am creating a state machine currently but am running into the NullReferenceExceptions.

    I have a script attached to my MainCamera named CameraBoy. When an input is pressed CameraBoy will change state to lerp the camera using a script called SmoothERLerpCart.

    I am trying to have SmoothERLerpCart call the function MoveCamera() from the CameraBoy script. SmoothERLerpCart is not attached to anything, but is called when the CameraBoy changes that state machine state to SmoothERLerpCart state.

    I am able to get the SmoothERLerpCart to move the camera itself within its Execute() function, but I want the MainCamera to decide whether it wants to be moved or not.

    Here is the CameraBoy Script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CameraBoy : MonoBehaviour
    6. {
    7.     // Passed Parameters to SmoothERLerpCart
    8.     [SerializeField] private Transform[] views;        // Set view[0] as the starting position
    9.     [SerializeField] private float lerpTime = 2;
    10.     private Transform currentView;
    11.  
    12.     private StateMachine stateMachine = new StateMachine();
    13.  
    14.     private static bool isLerping = false;
    15.  
    16.     // Getter/setter property for bool
    17.     public static bool IsLerpingBool()  // Must be static for other scripts to find...?
    18.     {
    19.         return isLerping;
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         // Use to determine view based on inputs.
    25.         InputView();
    26.     }
    27.  
    28.     private void InputView()
    29.     {
    30.         if (Input.GetKeyDown(KeyCode.Alpha1))
    31.         {
    32.             currentView = views[0];                 // Starting position
    33.             this.stateMachine.ChangeState(new SmoothERLerpCart(this.gameObject,
    34.                         this.currentView, this.views, this.lerpTime));
    35.         }
    36.         if (Input.GetKeyDown(KeyCode.Alpha2))
    37.         {
    38.             currentView = views[1];
    39.              this.stateMachine.ChangeState(new SmoothERLerpCart(this.gameObject,
    40.                         this.currentView, this.views, this.lerpTime));
    41.         }
    42.     }
    43.  
    44.     private void LateUpdate()
    45.     {
    46.         // Execute CurrentState State Updates
    47.         this.stateMachine.ExecuteStateUpdate();
    48.     }
    49.  
    50.     public void MoveCamera()
    51.     {
    52.         Debug.Log("Moving the camera");
    53.     }
    54.  
    55. }
    56.  
    Here is the SmotherERLerpCart Script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SmoothERLerpCart : IState
    6. {
    7.  
    8.     // Passed Parameters
    9.     private GameObject ownerGameObject;
    10.     private Transform currentView;
    11.     private Transform[] views;
    12.     private float lerpTime;
    13.  
    14.     // Non-passed parameters
    15.     private float currentLerpTime;
    16.     private float t;
    17.     public bool finishedLerping = true;
    18.     private bool cartIsLerpingBool = false;
    19.  
    20.     // References
    21.     private StateMachine stateMachine = new StateMachine();
    22.     //private System.Action<LerpResults> lerpResultsCallback;
    23.  
    24.     private CameraBoy cameraBoy;
    25.  
    26.     public SmoothERLerpCart(GameObject ownerGameObject, Transform currentView,
    27.                             Transform[] views, float lerpTime)
    28.     {
    29.         this.ownerGameObject = ownerGameObject;
    30.         this.currentView = currentView;
    31.         this.views = views;
    32.         this.lerpTime = lerpTime;
    33.     }
    34.  
    35.     public void Enter()
    36.     {
    37.         Debug.Log("SmoothERLerpCart Entered.");
    38.  
    39.         cartIsLerpingBool = CameraBoy.IsLerpingBool();
    40.      
    41.     }
    42.  
    43.     public void Execute()
    44.     {
    45.         Debug.Log("SmoothERLerpCart Executing.");
    46.         cartIsLerpingBool = true;
    47.         finishedLerping = false;  
    48.  
    49.         if (currentView != null && cartIsLerpingBool == true)
    50.         {
    51.             // Calculate the step value for Lerp
    52.  
    53.             CameraBoy.MoveCamera();
    54.  
    55.             StopLerpCheck();
    56.  
    57.         }
    58.     }
    59.  
    60.     public void Exit()
    61.     {
    62.         Debug.Log("SmoothERLerpCart Exiting.");
    63.     }
    64.  
    65.     private void StopLerpCheck()
    66.     {
    67.         Debug.Log("SmoothERLerpCart StopLerpChecking.");
    68.     }
    69. }

    I thought that if I provided a reference to the CameraBoy script that the SmoothERLerpCart script should be able to access the MoveCamera() function. VisualStudio throws the error saying I need a reference, but I thought I already provided the reference...?

    Lastly, here is the full NullReference Error:
    NullReferenceException: Object reference not set to an instance of an object
    SmoothERLerpCart.Enter () (at Assets/CubeCameraSceneScipts/CameraBoyStateMachine/Scripts/SmoothERLerpCart.cs:50)
    StateMachine.ChangeState (IState newState) (at Assets/CubeCameraSceneScipts/CameraBoyStateMachine/Scripts/StateMachine.cs:30)
    CameraBoy.InputView () (at Assets/CameraBoy.cs:50)
    CameraBoy.Update () (at Assets/CameraBoy.cs:36)


    Thank you for the help!
     
  2. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    It looks like you never initialize the cameraBoy variable in SmotherERLerpCart, which is what's null. You may want to add
    this.cameraBoy = ownerGameObject.GetComponent<CameraBoy>();
    or something similar to the constructor.

    On a side note, I see that you are using classes the do not derive from UnityEngine.Object for your states. This may cause you issues in the future because Unity's serializer does not support polymorphism. You may wish to switch to ScriptableObjects.
    https://docs.unity3d.com/Manual/script-Serialization.html
     
  3. Nibernator

    Nibernator

    Joined:
    May 25, 2018
    Posts:
    11
    Thanks for the quick reply!

    I will work on this tomorrow and post an update.
     
  4. Nibernator

    Nibernator

    Joined:
    May 25, 2018
    Posts:
    11
    @WallaceT_MFM I added the line to the constructor and that fixed the problem.

    What do you mean by, "you are using classes the do not derive from UnityEngine.Object for your states."? Are you saying that the states themselves (in this case, SmoothERLerpCart) is not a ScriptableObject?
     
  5. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    Yes, that's what I meant. If you already knew about that serialization restriction, then feel free to disregard that warning.