Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Input System calling additional times after loading new scenes

Discussion in 'Input System' started by brandonschlosser101, Mar 28, 2021.

  1. brandonschlosser101

    brandonschlosser101

    Joined:
    Apr 19, 2018
    Posts:
    15
    For some reason when I call actions in a new scene it will call an extra time, which can cause a pair of errors like this:

    MissingReferenceException while executing 'canceled' callbacks of 'Combat/Aim[/DualShock4GamepadHID/leftTrigger]'

    and

    MissingReferenceException: The object of type 'PlayerControls' has been destroyed but you are still trying to access it.

    When I then go back into the previous scene (or any new scene I imagine) and try to do the action again, I get another pair, so in my 2nd scene I get 4, 3rd I get 6, etc.

    So it's calling an additional time every time new scene is loaded and I'm not sure how to fix this.
    I'm on the latest as of now (2021.1.0f1)

    Any ideas or help is much appreciated!!
     
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,907
    Do you use an event scheme? You probably don't unregister your events. If you show us your code we can tell you more. If you decide to do so, please use the code formatting option in the post editor toolbar.
     
  3. brandonschlosser101

    brandonschlosser101

    Joined:
    Apr 19, 2018
    Posts:
    15
    I'm not entirely sure that it means to "unregister" them. I thought that meant disabling them, but that doesn't fix it.

    Here's my code. I marked the line it highlights when this particular error happens when I "un-aim" and go back to a normal rotation. Line 212.

    Code (CSharp):
    1. public class PlayerControls : MonoBehaviour
    2. {
    3.     //player actions
    4.     public PlayerControlInputs playerControls;
    5.     public Combat combatScript;
    6.     private PlayerStats playerStatScript;
    7.     public float deadzone;
    8.     private Rigidbody player;
    9.     public float turnSmoothTime;
    10.     private float turnSmoothVelocity;
    11.     private Vector2 moveDirection;
    12.     public bool isRunning;
    13.     public float currentSpeed;
    14.     public float runSpeed;
    15.     public float strifeSpeed;
    16.     public float walkSpeed;
    17.  
    18.  
    19.     //main camera
    20.     public Transform camera;
    21.     public Transform cameraAnchor;
    22.     public Transform focalPoint;
    23.     private Vector2 lookDirection;
    24.     public float lookSensitivity;
    25.     public float minimumX;
    26.     public float maximumX;
    27.     private float horizontal;
    28.     private float vertical;
    29.     public float rotationSpeed;
    30.  
    31.     //Occlusion
    32.     public Transform desiredCameraPosition;
    33.  
    34.  
    35.     //Aiming camera
    36.     private Vector3 standardCamLocation;
    37.     public Vector3 playerModelRotation;
    38.     public bool isAiming;
    39.     public bool hasWeaponEquipped;
    40.     public Transform aimingTransform;
    41.     public Transform playerModel;
    42.  
    43.     public float reorientProgress;
    44.     public Quaternion currentPlayerRotation;
    45.     public float reorientSpeed;
    46.     public GameObject reticle;
    47.     private Quaternion targetAimRotation;
    48.     private bool isUnaiming;
    49.  
    50.     //AdditionalControls
    51.     //UI
    52.     public GameObject startMenu;
    53.  
    54.  
    55.     //quickturn
    56.     private float quickturnProgress = 1;
    57.     private float quickturnStartingValue;
    58.  
    59.  
    60.     private void Awake()
    61.     {
    62.         playerControls = new PlayerControlInputs();
    63.         player = this.gameObject.GetComponent<Rigidbody>();
    64.         playerStatScript = gameObject.GetComponent<PlayerStats>();
    65.         combatScript = this.gameObject.GetComponent<Combat>();
    66.  
    67.         playerControls.General.Move.performed += context => moveDirection = context.ReadValue<Vector2>();
    68.         playerControls.General.Look.performed += context => lookDirection = context.ReadValue<Vector2>();
    69.         playerControls.General.Run.started += context => ToggleRun();
    70.         playerControls.General.Quickturn.performed += context => Quickturn();
    71.         playerControls.Combat.Aim.performed += context => Aim();
    72.         playerControls.Combat.Aim.canceled += context => Revert();
    73.         playerControls.Combat.Reload.performed += ContextMenu => Reload();
    74.         playerControls.UI.Pause.performed += context => Pause();
    75.  
    76.         playerModelRotation = playerModel.localEulerAngles;
    77.         standardCamLocation = camera.transform.localPosition;
    78.         camera.transform.position = desiredCameraPosition.position;
    79.  
    80.     }
    81.  
    82.     private void OnEnable()
    83.     {
    84.         playerControls.Enable();
    85.     }
    86.  
    87.     void Pause()
    88.     {
    89.         startMenu.SetActive(true);
    90.     }
    91.  
    92.     public void ToggleRun()
    93.     {
    94.         if (isRunning)
    95.         {
    96.             isRunning = false;
    97.             currentSpeed = walkSpeed;
    98.         }
    99.  
    100.         else if (isRunning == false)
    101.         {
    102.             isRunning = true;
    103.             currentSpeed = runSpeed;
    104.         }
    105.  
    106.         else
    107.         {
    108.             currentSpeed = walkSpeed;
    109.             isRunning = false;
    110.         }
    111.    
    112.     }
    113.     private void FixedUpdate()
    114.     {
    115.    
    116.         if (isAiming && playerStatScript.isBeingParalyzed != true)
    117.         {
    118.             // Debug.Log("walking");
    119.             float h = moveDirection.x;
    120.             float v = moveDirection.y;
    121.             Vector3 dir = new Vector3(h, 0, v).normalized;
    122.  
    123.             if (dir.magnitude > deadzone)
    124.             {
    125.                 currentSpeed = strifeSpeed;
    126.                 float targetAngle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg + camera.eulerAngles.y;
    127.                 Vector3 moveDirection = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
    128.                 player.velocity = moveDirection.normalized * currentSpeed *Time.deltaTime;            
    129.             }
    130.             else player.velocity = Vector3.zero;
    131.         }
    132.  
    133.         else if(isAiming != true && playerStatScript.isBeingParalyzed != true)
    134.         {
    135.             float h = moveDirection.x;
    136.             float v = moveDirection.y;
    137.             Vector3 dir = new Vector3(h, 0, v).normalized;
    138.  
    139.             if (dir.magnitude > deadzone)
    140.             {
    141.                 float targetAngle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg + camera.eulerAngles.y;
    142.                 float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
    143.                 transform.rotation = Quaternion.Euler(0f, angle, 0f);
    144.                 Vector3 moveDirection = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
    145.                 player.velocity = moveDirection.normalized * currentSpeed * Time.deltaTime;
    146.             }
    147.  
    148.             else
    149.             {
    150.                 player.velocity = Vector3.zero;
    151.             }
    152.  
    153.         }
    154.  
    155.         if (walkSpeed <= 75)
    156.         {
    157.             walkSpeed = 75;
    158.         }
    159.  
    160.         if(runSpeed <=75)
    161.         {
    162.             runSpeed = 75;
    163.         }
    164.  
    165.         if(strifeSpeed <= 75)
    166.         {
    167.             strifeSpeed = 75;
    168.         }
    169.  
    170.     }
    171.  
    172.     void Reload()
    173.     {
    174.         if(isAiming)
    175.         {
    176.             combatScript.Reload();
    177.         }
    178.     }
    179.  
    180.     void Quickturn()
    181.     {
    182.         quickturnStartingValue = horizontal;
    183.         quickturnProgress = 0;
    184.  
    185.     }
    186.  
    187.     void Aim()
    188.     {
    189.         if(hasWeaponEquipped)
    190.         {
    191.             //Debug.Log("setting rotation");
    192.             standardCamLocation = camera.transform.localPosition;
    193.             isAiming = true;
    194.             isRunning = false;
    195.             currentPlayerRotation = transform.rotation;
    196.             reticle.SetActive(true);
    197.         }
    198.  
    199.     }
    200.  
    201.  
    202.     void Revert()
    203.     {
    204.         playerControls.Combat.Aim.Enable();
    205.         isAiming = false;
    206.         isUnaiming = true;
    207.         currentSpeed = walkSpeed;
    208.         if(reticle != null)
    209.         {
    210.             reticle.SetActive(false); // comes up as null for soem reason in new room at first?
    211.         }
    212.         currentPlayerRotation = transform.localRotation; //<---- this is where the null reference points to. If I get rid of this, the error doesn't happen for "PlayerControls"
    213.  
    214.     }
    215.  
    216.     private void Update()
    217.     {
    218.         if (isAiming)
    219.         {
    220.             if (reorientProgress < 1)
    221.             {
    222.                 reorientProgress += Time.deltaTime * reorientSpeed;
    223.                 transform.rotation = Quaternion.Slerp(currentPlayerRotation, targetAimRotation, reorientProgress);            
    224.                 camera.transform.localPosition = Vector3.Lerp(standardCamLocation, aimingTransform.localPosition, reorientProgress);
    225.  
    226.             }
    227.  
    228.             else if(reorientProgress >= 1)
    229.             {
    230.                 transform.rotation = targetAimRotation;
    231.                 reorientProgress = 1;
    232.             }
    233.         }
    234.  
    235.         else if(isUnaiming)
    236.         {
    237.             if (reorientProgress > 0)
    238.             {
    239.  
    240.                 reorientProgress -= Time.deltaTime * reorientSpeed;
    241.                 //turns camera
    242.                 transform.rotation = Quaternion.Slerp(Quaternion.Euler(0, targetAimRotation.eulerAngles.y, targetAimRotation.eulerAngles.z), currentPlayerRotation, reorientProgress);
    243.                 //turns player
    244.                 camera.transform.localPosition = Vector3.Lerp(standardCamLocation, aimingTransform.localPosition, reorientProgress);
    245.  
    246.             }
    247.  
    248.             else if (reorientProgress <= 0)
    249.             {
    250.                 reorientProgress = 0;
    251.                 isUnaiming = false;
    252.             }
    253.         }
    254.  
    255.         if(quickturnProgress < 1)
    256.         {
    257.             quickturnProgress += Time.deltaTime * reorientSpeed;
    258.             horizontal = Mathf.Lerp(quickturnStartingValue, quickturnStartingValue + 180, quickturnProgress);
    259.             transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, horizontal, transform.rotation.z);
    260.         }
    261.  
    262.     }
    263.     private void LateUpdate()
    264.     {
    265.         CamControl();
    266.         CameraOcclusionandCollisionDetection();
    267.     }
    268.  
    269.     void CamControl()
    270.     {
    271.         if(playerControls.General.Look.enabled)
    272.         {
    273.             horizontal += lookDirection.x * rotationSpeed * Time.deltaTime;
    274.             vertical -= lookDirection.y * rotationSpeed * Time.deltaTime;
    275.             vertical = Mathf.Clamp(vertical, minimumX, maximumX);
    276.             camera.transform.LookAt(focalPoint);
    277.             cameraAnchor.rotation = Quaternion.Euler(vertical, horizontal, 0);
    278.             if (isAiming)
    279.             {
    280.                 targetAimRotation = Quaternion.Euler(vertical, horizontal, 0);
    281.  
    282.             }
    283.         }
    284.      
    285.     }
    286.  
    287.     void CameraOcclusionandCollisionDetection()
    288.     {
    289.         RaycastHit hit;
    290.  
    291.         if (Physics.Linecast(cameraAnchor.transform.position, desiredCameraPosition.position, out hit))
    292.         {
    293.             if (hit.collider.gameObject.tag != "Player")
    294.             {
    295.                 camera.transform.position = hit.point;
    296.             }
    297.  
    298.             if (camera.transform.position != desiredCameraPosition.position)
    299.             {
    300.                 RaycastHit occludedHit;
    301.  
    302.                 if (Physics.Linecast(desiredCameraPosition.position, cameraAnchor.position, out occludedHit))
    303.                 {
    304.                     if (occludedHit.transform.gameObject.tag == "Player")
    305.                     {
    306.                         return;
    307.                     }
    308.                 }
    309.  
    310.             }
    311.         }
    312.  
    313.         else if (isAiming != true)
    314.         {
    315.             camera.transform.position = desiredCameraPosition.position;
    316.         }
    317.  
    318.     }
    319.  
    320.     private void OnDisable()
    321.     {
    322.       playerControls.Disable();
    323.     }
    324. }
     
  4. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,907
    Do you make this object "DontDestroyOnLoad"? Because what you're experiencing looks like you are double-registering.
    This thing:
    playerControls.General.Move.performed +=
    called event registration. You need to unregister when you are done. I usually advise against leaving like this even if you need it for the entire application lifespan. It is just bad habit. So what you can do is to unregister from these events
    [whatever event].performed -=
    pattern. It is important to unregister the same methods what you have registered. And I advise that way because if you change your mind later and destroy the object early, you're leaking memory.
    More info here:
    https://docs.microsoft.com/en-us/do...w-to-subscribe-to-and-unsubscribe-from-events
     
  5. brandonschlosser101

    brandonschlosser101

    Joined:
    Apr 19, 2018
    Posts:
    15
    Yeah its on the Player which is not destroyed on load.

    So to unregister, I just put the same thing but -= and right before I load the scene or do I put it also in the variable space?

    Thanks for your help! I've never used delegates before so learning the new input system has been a journey!
     
  6. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,907
    I usually register onEnable and unregister on onDisable. Also make sure you don't create another player object when you load the next scene.
     
    brandonschlosser101 likes this.
  7. brandonschlosser101

    brandonschlosser101

    Joined:
    Apr 19, 2018
    Posts:
    15
    Yup that's what the issue was. I feel silly. I had the player prefab in every room and forgot to check for and destroy copies.

    Plus I de-registered.

    Thanks so much!!!
     
    Lurking-Ninja likes this.
  8. X3doll

    X3doll

    Joined:
    Apr 15, 2020
    Posts:
    33
    Sorry but, do you manage to use one player input component per scene? I struggle to understand what happen when you have to spread this component into multiple scenes.

    As i know from the documentation: 1 player input component = 1 user = 1 different control scheme

    If i had one player input component per scene, i still have this issue?