Hi,
I’ve been running into an issue when attempting to build my game.
The game runs perfectly in the Unity Editor on both Windows and MacOS. The MacOS build of the game also runs perfectly without issue. However, for some reason in the Windows standalone build, when I enter my main game scene I encounter a NullReferenceException when attempting to access the CharacterController on my player in order to move it.
NullReferenceException: Object reference not set to an instance of an object
at PlayerController.Update () [0x0004c] in …\Reef Rally 2019.2.7\Assets\Scripts\PlayerController.cs:111
I have attached the editor log from the most recent build run.
Here is my PlayerController script where the error is originating. I should mention that the motion controller referenced within the script should have no effect on ability to find the CharacterController.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Leap;
/*
This script controls the movement mechancics of the player when using both a keyboard or motion controller. The main function of this script
determines whether or not the player is dead or alive. Then, depending on if a hand is detected by the controller it decides whether the game will be
controlled by the keyboard or by the motion controller.
*/
public class PlayerController : MonoBehaviour
{
//Define External Scripts
[HideInInspector] HandController handPosition;
[HideInInspector] public CharacterController controller;
[HideInInspector] public GameplayController gameplayController;
//Define GameObjects
[HideInInspector] public GameObject player;
[HideInInspector] private GameObject mainCamera;
//Define player states
[HideInInspector] public enum State { None, Alive, Dead };
[HideInInspector] public State playerState;
//Add ranged slider to inspector for camera distance from player
[Range(0.0f, 20.0f)] [SerializeField] float cameraOffsetZ;
[Range(-5.0f, 5.0f)] [SerializeField] float cameraOffsetY;
//Define Leap Motion Interaction Box Vector
Vector normalized;
//Define input axis variables
float leapHorizontal;
float leapVertical;
float horizontal;
float vertical;
//Create inspector input for Movement variables
[SerializeField] float controlSpeed = 10f; //Speed in m/s^-1
//[SerializeField] float leapControlSpeed = 15f; //Speed in m/s^-1
[SerializeField] public float forwardVelocity = 5.0f;
[SerializeField] float waterGravity = 3.0f;
[SerializeField] float leapMovementScale = 1.5f;
//Throw is 1 > -1 offset from centre of controller
float xThrow;
float yThrow;
//Create inspector input for Player Rotation Variables
private float controlPitchFactor = -30f;
private float controlRollFactor = -20f;
private float leapRotationFactor = 50;
//Define Character postion as Vector3
Vector3 characterPos;
//Create floats for player movement restrictions
[SerializeField] public float xClamp = 4f;
[SerializeField] public float yClamp = 3f;
private float xLeapClampMin = -3.5f;
private float xLeapClampMax = 3.5f;
private float yLeapClampMin = 1f;
private float yLeapClampMax = 6f;
private void Awake()
{
//Access Game Objects
mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
//Access External Scripts
handPosition = GameObject.FindGameObjectWithTag("HandController").GetComponent<HandController>();
gameplayController = mainCamera.GetComponent<GameplayController>();
}
// Start is called before the first frame update
void Start()
{
//Set Player to dead, is change to alive by GameplayController after start delay
gameplayController.playerState = GameplayController.State.Dead;
player = GameObject.FindGameObjectWithTag("Player");
cameraOffsetY = 0.8f;
cameraOffsetZ = 6f;
}
// Update is called once per frame
void Update()
{
//Get HandController Data from current frame
Frame frame = handPosition.GetFrame();
//Define hand as most prominent hand detected in the frame by Leap Motion
Hand hand = frame.Hands.Frontmost;
controller = player.GetComponent<CharacterController>();
//controller.detectCollisions = false;
AccessInputVariables(frame, hand);
//Run if player is not Dead
if (gameplayController.playerState != GameplayController.State.Dead)
{
//Move player forward at specified speed m/s
controller.Move((Vector3.forward * forwardVelocity) * Time.deltaTime);
controller.Move((Vector3.down * waterGravity) * Time.deltaTime);
//If hand is detected by Motion Controller
if (hand.IsValid)
{
UseHandControls(frame, hand, leapHorizontal, leapVertical);
}
//else if no hand is detected
else
{
UseKeyControls(horizontal, vertical);
}
}
//Camera follows the player
CameraFollow();
}
private void AccessInputVariables(Frame frame, Hand hand)
{
//Access Leap Motion Interaction Box
normalized = frame.InteractionBox.NormalizePoint(hand.PalmPosition, true) * 2;
//Access input axis and Interaction Box axis
leapHorizontal = normalized.x - 1;
leapVertical = normalized.y - 1;
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
}
public void UseKeyControls(float horizontal, float vertical)
{
xPlayerMovement(controlSpeed, horizontal);
yPlayerMovement(controlSpeed, vertical);
PlayerRotation(horizontal, vertical);
}
public void UseHandControls(Frame frame, Hand hand, float horizontal, float vertical)
{
//Interaction Box Hand Controls
//xPlayerMovement(leapControlSpeed, horizontal);
//yPlayerMovement(leapControlSpeed, vertical);
//PlayerRotation(horizontal, vertical);
//Legacy Hand Controls
PlayerMovement(hand);
PlayerRotation(hand);
}
private void CameraFollow()
{
//Define characterPos as current world position of the character model
characterPos = player.transform.position;
//Set camera position to player position with a defined offset behind the player
mainCamera.transform.position = new Vector3(characterPos.x, characterPos.y + cameraOffsetY, characterPos.z - cameraOffsetZ);
}
private void xPlayerMovement(float SpeedFactor, float inputAxis)
{
//Horizontal input from controller/keyboard - joystick/a-d
xThrow = inputAxis;
//Time.deltaTime = time passed since last frame. Allows for constant velocity with varying fps distance = speed x Velocity
float xOffset = xThrow * controlSpeed * Time.deltaTime;
//Change player x-axis position with offset included
float xPos = player.transform.localPosition.x + xOffset;
//Restrict how far player can move
xPos = Mathf.Clamp(xPos, -xClamp, xClamp);
//Change position on x-axis without altering y and z axes
player.transform.localPosition = new Vector3(xPos, player.transform.localPosition.y, player.transform.localPosition.z);
}
private void yPlayerMovement(float SpeedFactor, float inputAxis)
{
//Vertical input from controller/keyboard - joystick/w-s
yThrow = inputAxis;
//Time.deltaTime = time passed since last frame. Allows for constant velocity with varying fps distance = speed X Velocity
float yOffset = yThrow * SpeedFactor * Time.deltaTime;
//Change player y-axis position with offset included
float yPos = player.transform.localPosition.y + yOffset;
//Restrict how far player can move
yPos = Mathf.Clamp(yPos, -yClamp, yClamp);
//Change position on y-axis without altering y and z axes
player.transform.localPosition = new Vector3(player.transform.localPosition.x, yPos, player.transform.localPosition.z);
}
private void PlayerRotation(float xRotation, float yRotation)
{
//Define Roll and Pitch multiplied by their control factor
float roll = xRotation * controlRollFactor;
float pitch = yRotation * controlPitchFactor;
//Transform rotation based on factored proportions in relation to position of player
player.transform.localRotation = Quaternion.Euler(pitch, 0, roll); //x, y, z
}
private void PlayerMovement(Hand hand)
{
Vector3 getHandPosition = handPosition.transform.TransformPoint(hand.PalmPosition.ToUnityScaled());
//Define X and Y axes of hand position and mulitply by leapMovementScale
float xPosHand = getHandPosition.x * leapMovementScale;
float yPosHand = getHandPosition.y * leapMovementScale;
//Set clamps for hand position
float clampedXPos = Mathf.Clamp(xPosHand, xLeapClampMin, xLeapClampMax);
float clampedYPos = Mathf.Clamp(yPosHand, yLeapClampMin, yLeapClampMax);
//Transform position of Player with position of user's hand
player.transform.position = new Vector3(clampedXPos, clampedYPos, player.transform.position.z);
}
private void PlayerRotation(Hand hand)
{
float pitch = hand.Direction.Pitch * -leapRotationFactor;
float roll = hand.PalmNormal.Roll * leapRotationFactor;
player.transform.rotation = Quaternion.Euler(pitch, 0, roll);
}
}
This is my first time posting on these threads so apologies if I have not uploaded everything in the correct format.