NullReferenceException in build not in editor,NullReferenceException in builds not in editor

Hey, thanks for taking the time to read this.

Getting a NullReferenceException on my Windows Standalone x86_64 build. Using Development Build and Script Debugging I have found the following error:

NullReferenceException
  at (wrapper managed-to-native) UnityEngine.GameObject.get_transform(UnityEngine.GameObject)
  at Paddles.AutomatePaddles (System.Single deltaSpeed) [0x00001] in E:\Unity\Quad Pong Xtreme\Assets\Script\Paddles.cs:79 
  at Paddles.Update () [0x00033] in E:\Unity\Quad Pong Xtreme\Assets\Script\Paddles.cs:32 

(Filename: E:/Unity/Quad Pong Xtreme/Assets/Script/Paddles.cs Line: 79)

What confuses me is that this refers to a very straightforward line of code:

Vector3 ballPositionV3 = ball.transform.position;

In case it’s useful, here’s the whole script. The variable ball is set in the inspector;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Paddles : MonoBehaviour
{
    [SerializeField] List <GameObject> balls = new List<GameObject>();
    [SerializeField] bool isAutomated;
    [SerializeField] float paddleSpeed = 15f;
    [SerializeField] float paddleLimit = 3.2f;
    [SerializeField] float aiSenseRange = 3.7f;
    [SerializeField] GameObject ball;

    float moveX;
    float moveY;
    ParticleSystem ps;
    GameplayManager gm;
    float aiDetectionPoint;


    private void Start()
    {
        gm = FindObjectOfType<GameplayManager>();
        aiDetectionPoint = paddleLimit - aiSenseRange;
        ps = transform.GetChild(0).GetChild(0).gameObject.GetComponent<ParticleSystem>();
    }

    private void LateUpdate()
    {
        float deltaSpeed = paddleSpeed * Time.deltaTime;
        if(gm.GetCurrentSceneName() == "Preload" || isAutomated) {
            transform.Translate(AutomatePaddles(deltaSpeed));
        } else {
            PlayerInput(deltaSpeed);
            PaddleMove();
        }
        ApplyPaddleLimit();
    }

    void PlayerInput(float deltaSpeed) {
        moveX = Input.GetAxis("Horizontal") * deltaSpeed;
        moveY = Input.GetAxis("Vertical") * deltaSpeed;
    }

    void PaddleMove() {
        switch(tag) {
            case "Bounce Horizontal":
                transform.Translate(moveX, 0, 0);
            break;
            case "Bounce Vertical":
                transform.Translate(0, moveY, 0);
            break;

        }
    }

    void ApplyPaddleLimit() {
        Vector3 position = transform.position;
        switch(tag) {
            case "Bounce Vertical":
                if(transform.position.y > paddleLimit) {
                    position.y = paddleLimit;
                } else if(transform.position.y < -paddleLimit) {
                    position.y = -paddleLimit;
                }
            break;
            case "Bounce Horizontal":
                if(transform.position.x > paddleLimit) {
                    position.x = paddleLimit;
                } else if(transform.position.x < -paddleLimit) {
                    position.x = -paddleLimit;
                }
            break;
        }
        transform.position = position;
    }

    Vector2 AutomatePaddles(float deltaSpeed) {
        Vector3 ballPositionV3 = ball.transform.position; // <-- Line 79
        Vector2 ballPosition = new Vector2(ballPositionV3.x, ballPositionV3.y);
        Vector2 ballVelocity = ball.GetComponent<Rigidbody2D>().velocity;
        Vector2 translate = new Vector2(0, 0);

        switch(tag) {
            case "Bounce Vertical":
                if((ballVelocity.x < 0 && ballPosition.x < -aiDetectionPoint) || (ballVelocity.x > 0 && ballPosition.x > aiDetectionPoint)) {
                    translate.y = ballPosition.y - transform.position.y;
                    if(Mathf.Abs(translate.y) > deltaSpeed) {
                        if(translate.y < 0) {
                            translate.y = -deltaSpeed;
                        } else {
                            translate.y = deltaSpeed;
                        }
                    }
                }
            break;
            case "Bounce Horizontal":
                if((ballVelocity.y > 0 && ballPosition.y > aiDetectionPoint) || (ballVelocity.y < 0 && ballPosition.y < -aiDetectionPoint)) {
                    translate.x = ballPosition.x - transform.position.x;
                    if(Mathf.Abs(translate.x) > deltaSpeed) {
                        if(translate.x < 0) {
                            translate.x = -deltaSpeed;
                        } else {
                            translate.x = deltaSpeed;
                        }
                    }
                }
            break;
        }
        return translate;
    }

    public void PrepareToDestroyPaddle() {
        GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 0);
        ps.Play();
        Invoke("Kill", 2);
    }

    void Kill() {
        Destroy(gameObject);
    }
}

,Hey, thanks for taking the time to read this.

I actually want this as a WebGL build, but even in dev mode, the WebGL wasn’t giving me a usable set of errors, so I did a Windows build with dev and script debugging on. The below is the error that is caught, followed by the very simple code it references

NullReferenceException
  at (wrapper managed-to-native) UnityEngine.GameObject.get_transform(UnityEngine.GameObject)
  at Paddles.AutomatePaddles (System.Single deltaSpeed) [0x00001] in E:\Unity\Quad Pong Xtreme\Assets\Script\Paddles.cs:79 
  at Paddles.Update () [0x00033] in E:\Unity\Quad Pong Xtreme\Assets\Script\Paddles.cs:32 

(Filename: E:/Unity/Quad Pong Xtreme/Assets/Script/Paddles.cs Line: 79)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Paddles : MonoBehaviour
{
    [SerializeField] List <GameObject> balls = new List<GameObject>();
    [SerializeField] bool isAutomated;
    [SerializeField] float paddleSpeed = 15f;
    [SerializeField] float paddleLimit = 3.2f;
    [SerializeField] float aiSenseRange = 3.7f;
    [SerializeField] GameObject ball;

    float moveX;
    float moveY;
    ParticleSystem ps;
    GameplayManager gm;
    float aiDetectionPoint;


    private void Start()
    {
        gm = FindObjectOfType<GameplayManager>();
        aiDetectionPoint = paddleLimit - aiSenseRange;
        ps = transform.GetChild(0).GetChild(0).gameObject.GetComponent<ParticleSystem>();
    }

    private void LateUpdate()
    {
        float deltaSpeed = paddleSpeed * Time.deltaTime;
        if(gm.GetCurrentSceneName() == "Preload" || isAutomated) {
            transform.Translate(AutomatePaddles(deltaSpeed));
        } else {
            PlayerInput(deltaSpeed);
            PaddleMove();
        }
        ApplyPaddleLimit();
    }

    void PlayerInput(float deltaSpeed) {
        moveX = Input.GetAxis("Horizontal") * deltaSpeed;
        moveY = Input.GetAxis("Vertical") * deltaSpeed;
    }

    void PaddleMove() {
        switch(tag) {
            case "Bounce Horizontal":
                transform.Translate(moveX, 0, 0);
            break;
            case "Bounce Vertical":
                transform.Translate(0, moveY, 0);
            break;

        }
    }

    void ApplyPaddleLimit() {
        Vector3 position = transform.position;
        switch(tag) {
            case "Bounce Vertical":
                if(transform.position.y > paddleLimit) {
                    position.y = paddleLimit;
                } else if(transform.position.y < -paddleLimit) {
                    position.y = -paddleLimit;
                }
            break;
            case "Bounce Horizontal":
                if(transform.position.x > paddleLimit) {
                    position.x = paddleLimit;
                } else if(transform.position.x < -paddleLimit) {
                    position.x = -paddleLimit;
                }
            break;
        }
        transform.position = position;
    }

    Vector2 AutomatePaddles(float deltaSpeed) {
        Vector2 ballPosition = ball.transform.position; <---- Line 79
        Vector2 ballVelocity = ball.GetComponent<Rigidbody2D>().velocity;
        Vector2 translate = new Vector2(0, 0);

        switch(tag) {
            case "Bounce Vertical":
                if((ballVelocity.x < 0 && ballPosition.x < -aiDetectionPoint) || (ballVelocity.x > 0 && ballPosition.x > aiDetectionPoint)) {
                    translate.y = ballPosition.y - transform.position.y;
                    if(Mathf.Abs(translate.y) > deltaSpeed) {
                        if(translate.y < 0) {
                            translate.y = -deltaSpeed;
                        } else {
                            translate.y = deltaSpeed;
                        }
                    }
                }
            break;
            case "Bounce Horizontal":
                if((ballVelocity.y > 0 && ballPosition.y > aiDetectionPoint) || (ballVelocity.y < 0 && ballPosition.y < -aiDetectionPoint)) {
                    translate.x = ballPosition.x - transform.position.x;
                    if(Mathf.Abs(translate.x) > deltaSpeed) {
                        if(translate.x < 0) {
                            translate.x = -deltaSpeed;
                        } else {
                            translate.x = deltaSpeed;
                        }
                    }
                }
            break;
        }
        return translate;
    }

    public void PrepareToDestroyPaddle() {
        GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 0);
        ps.Play();
        Invoke("Kill", 2);
    }

    void Kill() {
        Destroy(gameObject);
    }
}

ball cannot be found? ok easiest way i found to fix this across both build and non build is do a simple check in Awake or start:

void Awake()
{
    if(ball == null) 
    { 
       ball = GameObject.FindObjectOfType<Ball>(); // if it has a script on it, otherwise 
       //ball = GameObject.FindGameObjectWithTag("Ball");// then add this tag to the ball.
    }
 }

Thanks for the advice. I have done various builds - WebGL, WebGL with dev mode, Windows Standalone, Windows Standalone with dev mode, Windows Standalone with dev mode and script debugging, all so far without success.

I hope I’ve understood your suggestion properly, I now have:

// variable declarations
        [SerializeField] GameObject ballPrefab;

// in the Start() method
        if(ballPrefab == null) {
            ballPrefab = Resources.Load("Prefabs/Ball") as GameObject;
        }

// in the Update method
        if(gm.balls.Count <=0) { //gm being the gameplay manager
            Instantiate(ballPrefab, Vector3.zero, Quaternion.identity);
        }

It still works in the editor, and fails in the Windows build, with this error:

ArgumentException: The Object you want to instantiate is null.
  at UnityEngine.Object.CheckNullArgument (System.Object arg, System.String message) [0x00009] in <cbc2a4dc69734303bc7c8542260e1c75>:0 
  at UnityEngine.Object.Instantiate (UnityEngine.Object original, UnityEngine.Vector3 position, UnityEngine.Quaternion rotation) [0x00001] in <cbc2a4dc69734303bc7c8542260e1c75>:0 
  at UnityEngine.Object.Instantiate[T] (T original, UnityEngine.Vector3 position, UnityEngine.Quaternion rotation) [0x00001] in <cbc2a4dc69734303bc7c8542260e1c75>:0 
  at PreloadManager.Update () [0x00033] in E:\Unity\Quad Pong Xtreme\Assets\Script\PreloadManager.cs:49 

so what do I attempt next?

it’s good to keep mind if using models through script to enable read/write