NullReferenceException可以说是unity里最常见的报错,他的意思是空指针异常,一般就是引用的东西是null了,造成错误。
而偶尔也会见到 missingGameObject,报错信息一般是 gameobject XXX已经被销毁了,但是你仍然去访问它 ,这个意思。我一直不太清楚这俩有什么明显的区别,今天在改bug的时候开了空工程做了个实验:
public class ceshi : MonoBehaviour
{
public GameObject go;
public Transform tf;
public ldkkk script;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
Destroy(go);
Debug.LogError("Go");
Debug.LogError(go == null);
Debug.LogError("TF");
Debug.LogError(tf == null);
Debug.LogError("script");
Debug.LogError(script == null);
script.Print();
}
}
}
随便写了个测试脚本 随便放在场景中一个物体上,按下D键就去删除另一个物体
待删除的物体叫willDestroy,上边也挂一个脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ldkkk : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public void Print()
{
Debug.LogError("我是挂载一个被干掉了的Gameobject上的脚本,我要发声!我要借尸还魂!");
}
// Update is called once per frame
void Update()
{
}
}
然后把willDestroy以及他的脚本都拖到manager上,运行:
按下D键位:
结果是这样,gameObject transform script都不为空,且脚本上的函数也顺利执行了,想了下,想起来unity销毁物体的机制是下一帧才会销毁,所以这同一帧就会是这样的结果。
那简单改下代码, 再测试类执行后 先按D再按P
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ceshi : MonoBehaviour
{
public GameObject go;
public Transform tf;
public ldkkk script;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
Destroy(go);
Debug.LogError("Go");
Debug.LogError(go == null);
Debug.LogError("TF");
Debug.LogError(tf == null);
Debug.LogError("script");
Debug.LogError(script == null);
script.Print();
}
//先按下D 之后再按P
if (Input.GetKeyDown(KeyCode.P))
{
Debug.LogError("Go");
Debug.LogError(go == null);
Debug.LogError("TF");
Debug.LogError(tf == null);
Debug.LogError("script");
Debug.LogError(script == null);
script.Print();
}
}
}
结果就是这样
最让我觉得奇怪的是按下P后 gameobject和transform都是null了 但是这个函数却可以输出出来,我以为会直接报空指针异常,看来monoBehaviour得脚本没我想象的那么简单,在gameobject销毁后,如果其他地方持有这个脚本的引用,仍然可以做某些操作。
但是 此时如果你在用此脚本引用去调用gameobject,那就会报错missingGamobject
比如我把借尸还魂函数加一句:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ldkkk : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public void Print()
{
Debug.LogError("我是挂载一个被干掉了的Gameobject上的脚本,我要发声!我要借尸还魂!");
Debug.LogError(gameObject == null);
}
// Update is called once per frame
void Update()
{
}
}
运行,就会这样:
大概的区别就是这样,我也不知道理解的对不对,反正之前我是觉得:
如果 XXX.func(); 若XXX是null了 那么一定会报错nullReference 今天这个操作让我知道了不一定,(= = 真是做了这么久还是这么菜的我