昨天在使用单例模式是出现了一个错误,在间接调用协程方法的时候Unity报错NullReferenceException
,各处检查找不到错误,万般无奈下从网上找到了解答,参考网址:http://blog.csdn.net/eijnew/article/details/41545561.
使用单利模式直接和间接调用协程是不一样的,这里使用两个类A和B举例测试。
测试类A:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34using UnityEngine;
using System.Collections;
public class A : MonoBehaviour
{
private static A instance;
private A() { }
public static A Instance
{
get
{
if (instance == null)
instance = new A();
return instance;
}
}
public void FunctionTest() //普通方法
{
Debug.Log("Here is function test.");
}
public IEnumerator CoroutinueTest() //协程方法
{
yield return new WaitForEndOfFrame();
Debug.Log("Here is coroutinue test.");
}
public void Test() //间接调用方法
{
FunctionTest();
StartCoroutine(CoroutinueTest());
}
}
测试类B:1
2
3
4
5
6
7
8
9
10
11
12
13
14using UnityEngine;
using System.Collections;
public class B : MonoBehaviour
{
// Use this for initialization
void Start()
{
A.Instance.FunctionTest(); //直接使用单例调用普通方法
StartCoroutine(A.Instance.CoroutinueTest()); //直接使用单里调用协程方法
A.Instance.Test(); //间接调用两种方法
}
}
输出结果时,就会发现直接使用单例调用协程时,协程方法和普通方法一样运行无误,经过其他方法间接调用时,普通方法也可以运行出结果,但是协程方法就会运行报错NullReferenceException
.未将对象引用到实例。
根据上面提到的博客的解释,使用new创建实例或该脚本依附的gameObject
被销毁了,都会报这种错误,因为MonoBehaviour
脚本不能独自存在,必须依附于某个GameObject
。
它的解决办法是在调用这个单例模式时,不再判断类的实例是否存在,转向判断实例所依附的gameobject
是否存在,存在就返回实例,不存在就新建一个gameobject
并添加类的组件并返回。
修改类A的单例模式是实现方式:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class A : MonoBehaviour
{
private A() { }
public static A GetA(GameObject instanceObj)
{
if (instanceObj == null)
{
return new A();
}
var AComponent = instanceObj.GetComponent<A>();
// ??操作符的作用可以理解为如果左边不为`null`就返回左边,为`null`就返回右边。
return AComponent ?? instanceObj.AddComponent<A>();
}
···
}
这时候通过间接调用协程就不出问题了。1
A.GetA(gameObject).Test();
Unity 3D论坛上的问答网址:https://answers.unity.com/questions/745685/nullreferenceexception-on-startcoroutine.html