- Home /
CharacterController on prefab null after changing scenes.,
Hi All,
Im creating a VR game and on my player/XR Origin object I have two things that keep failing. Of note they dont seem to fail at the same time always which makes me think something with how scenes load.
I have a character controller on my prefab and also a button mapping for a jump function.
In the first scene everything works fine. After moving to another scene (but not always) when I get to the scene and press the jump button I get the following two errors:
MissingReferenceException: The object of type 'CharacterController' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
PlayerControllerJump.OnJump (UnityEngine.InputSystem.InputAction+CallbackContext obj) (at Assets/VR_Avatar/PlayerControllerJump.cs:37)
UnityEngine.InputSystem.Utilities.DelegateHelpers.InvokeCallbacksSafe[TValue] (UnityEngine.InputSystem.Utilities.CallbackArray`1[System.Action`1[TValue]]& callbacks, TValue argument, System.String callbackName, System.Object context) (at Library/PackageCache/com.unity.inputsystem@1.2.0/InputSystem/Utilities/DelegateHelpers.cs:46)
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)
And followed behind it (again not always)
MissingReferenceException while executing 'performed' callbacks of 'XRI RightHand Interaction/Jump[/OculusTouchControllerOpenXR1/primarybutton]'
UnityEngine.InputSystem.LowLevel.NativeInputRuntime/<>c__DisplayClass7_0:<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType,UnityEngineInternal.Input.NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType,intptr)
Below is the script for jump and also the script for changing scenes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerControllerJump : MonoBehaviour
{
[SerializeField] private InputActionReference jumpActionReference;
[SerializeField] private InputActionReference exitActionReference;
[SerializeField] private float jumpHeight;
private CharacterController controller;
private Vector3 playerVelocity;
private bool groundedPlayer;
private float gravityValue = -9.81f;
void Start()
{
controller = GetComponent<CharacterController>();
jumpActionReference.action.performed += OnJump;
exitActionReference.action.performed += ExitGame;
}
// Update is called once per frame
void Update()
{
groundedPlayer = controller.isGrounded;
if (groundedPlayer && playerVelocity.y < 0)
{
playerVelocity.y = 0f;
}
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
private void OnJump(InputAction.CallbackContext obj)
{
if (controller.isGrounded)
{
playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
}
}
private void ExitGame(InputAction.CallbackContext obj)
{
Application.Quit();
}
}
Script for changing scenes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class commons_zone : MonoBehaviour
{
//METHOD 1
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
StartCoroutine(ChangeScene(other.gameObject));
}
}
IEnumerator ChangeScene(GameObject other)
{
SceneManager.LoadScene(4, LoadSceneMode.Additive);
//Note that SceneManager is keeping it's own array of scenes below. Not to be confused with the build settings list of scenes.
Scene nextScene = SceneManager.GetSceneAt(1);
yield return null;
SceneManager.UnloadScene(0);
}
//METHOD 2
/*void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
SceneManager.LoadScene();
}*/
}
Here is what I have tried:
Create a prefab in each scene (the setup for the code above currently)
tried adding and removing a script on the prefab that has DontDestroyOnLoad() for both the prefab as a whole and just the characterController.
Also tried taking prefab out of the other scene and using scenemanager to move it over to the new scene. (not represented in the code anymore).
No progress with either attempts. Any help would be appreciated!
,
Answer by damisco · Apr 03 at 01:24 PM
I wouldn't say I "fixed" this but I have at least come up with a temporary solution. I realized that when I made the character controller and called DontDestroyOnLoad() on it I still crashed but didn't have the missing ref exception for the char controller on it anymore. It did still the one for the righthand interaction. Looking a little closer at that, I found there was a call being made to verify the status of the XR Interactor Line Visual component from the XR Origin.
Technically if I want to use that component for any reason this is still broken. But for the most part I find it good for testing out VR Rigs and can get away with disabling it for now.
Answer by Vannerss · Apr 01 at 02:50 AM
Hello this might not be the right I answer but I feel it might be worth a try. if you add a requirecomponent attribute on top of playercontrollerclass it might fix it. https://docs.unity3d.com/ScriptReference/RequireComponent.html
[RequireComponent(typeof(CharacterController))]
public class PlayerControllerJump : MonoBehavior
{
private CharacterController controller;
private void Start()
{
controller = GetComponent<CharacterController>();
}
}
Also in the case you are not using the character controller default values you can change them in the start method after getting the component.
[RequireComponent(typeof(CharacterController))]
public class PlayerControllerJump : MonoBehavior
{
private CharacterController controller;
private void Start()
{
controller = GetComponent<CharacterController>();
controller.slopeLimit = 75;
controller.stepOffset = 0.7f;
}
}
So it didn't fix my situation but it got me thinking along the right track. Posting my answer below.