[Unity3D]调用函数时出现NullReferenceException的一个可能原因

今天遇到一个报错,如下图:

NullReferenceException 
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/UnityEngineMonoBehaviour.cs:63) 
...

使用场景是这样的:

我在一个脚本中需要调用一个协程,该协程被我封装在一个新的脚本里(MyCoroutines.cs),该脚本是一个单例:

 
 
  1. // MyCoroutines.cs
  2. class MyCoroutines : MonoBehavior {
  3. public static MyCoroutines Instance {
  4. get {return sInstance ?? new MyCoroutines() : sInstance;}
  5. }
  6. private MyCoroutines sInstance;
  7. public IEnumerator MethodA() {
  8. // ...
  9. }
  10. }

是这样调用的:

 
 
  1. ...
  2. // 在此处调用
  3. StartCoroutine(MyCoroutines.Instance.MethodA());
  4. ...

然后运行,程序报错。 
百思不得其解。 
明明是个单例,不应该出现NullReference。

网上查了一下,才恍然,其实是我对Unity的运行机制没有理解,先看看别人的解释:

Well, i just guess that the script (and / or the gameobject it's attached to) has been destroyed, or you created the Wait-instance with "new" which would result in the same behaviour since a MonoBehaviour can't live on it's own.

这段就解释的很清楚了:使用new创建实例或该脚本依附的gameObject被销毁了,都会报这种错误,因为MonoBehaviour脚本不能独自存在,必须依附于某个GameObject

所以解决的办法就是让这个脚本依附于某个GameObject就可以了,于是我修改了MyCoroutines类的实现:

 
 
  1. public class MyCoroutines : MonoBehaviour {
  2. private MyCoroutines() { }
  3. static public MyCoroutines GetOrCreate(GameObject gameObject) {
  4. if (gameObject == null) { return new MyCoroutines(); }
  5. var existed = gameObject.GetComponent <MyCoroutines>();
  6. return existed ?? gameObject.AddComponent <MyCoroutines>();
  7. }
  8. }
  9. // 调用:
  10. StartCoroutine(MyCoroutines.GetOrCreate(gameObject).MethodA());

这可能不是最好的解决办法,不过可以正常运行了。

下面是更详细的解释,有兴趣的童鞋可以继续看:

In C# / .NET / Mono instances actually can't be destroyed since they live in a managed memory environment. Objects are destroyed when all references to the object are gone, no longer valid. After that the garbage collector eventually kicks in and removes the object.

However in Unity, since it's core is written in C++, (native) objects can be destroyed on command (with Destroy to be more precise). The Destroy method actually only destroys the object on the c++ side. The managed representation of the object (your MonoBehaviour script) will still be there since the GC can only collect the object when there are no references anymore. That's why Unity actually "fakes" that the reference is null when the object has lost it's native counterpart.

If you use the "new" keyword to create an instance of a MonoBehaviour derived class the instance doesn't have a native counterpart and will always pretend to be null. If you want to create an instance at runtime it has to be attached to a gameobject. This is done with AddComponent

原文地址:http://answers.unity3d.com/questions/745685/nullreferenceexception-on-startcoroutine.html

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
unity贪吃蛇游戏源码+AI-游戏源码: 1.利用ngui插件对界面进行了仿写 在仿写界面途中发现,贪吃蛇这个游戏在界面适应屏幕分辨率,所以在开发中需要注意界面对屏幕的适应性。通过每个图片的宽高 和uiroot的比值,在start方法中对他进行了缩放。 2.利用 ngui 自带的uidragdropItem实现摇杆 界面完成之后,首先对贪吃蛇的摇杆进行了编程。 在unity中的NGUI上,给sprite创建添加一个uidragdropitem 实现了sprite的拖动。 AI的开始,移动逻辑: 整体只考虑三个前景: 1.首先先判断蛇首的简介范围是否有其他蛇死亡了留下的食物,如果有的话设置当前朝向为星星方向,便设置移动倍率为2,否则判断第三种情况; 3.随机朝某个位置移动。如果每帧AI都在更新的话,蛇的反映速度依然会更快,需要设置一下AI的更新间隔,通过调整这个间隔和蛇首的简介方位来调整AI的反映速度,目的是能够让玩家有机会撞死AI。 AI 移动的方向分析: AI在一个平面上运动,坐标就只有两个<x,y> 把他用0和1表示为: ----- 4个方向 上下左右 (0,0) (0,1) (0,-1) (-1,0) (1,0) 四个角度 象限。 (-1,1) (1,1) (-1,-1) (1,-1) 设计思路就是把AI蛇也当作是用摇杆来控制的。那么AI就方便写多了,只是 在还没开始写之前,要考虑的就是AI蛇多了之后程序会不会卡死了。在使用线程控制的过程中发现了一个问题,cup利用率太高。所以想先尝试一下在update上操作。如果不行的在想其他的办法。 设计: 把每个AI蛇都相当于人在控制他。那么想象一下虚拟摇杆,用一个数组来存这些虚拟摇杆的位移坐标 把每条AI蛇的长度也记录下来,默认长度就20 错误: NullReferenceException: Object reference not set to an instance of an object AI6control.flootAIOneBody6 (Vector3 V) (at Assets/AI6control.cs:57) AI6control.AIsix () (at Assets/AI6control.cs:40) AI6control.Update () (at Assets/AI6control.cs:13) 该错误在百度上说:没有实例化的问题 最后一个下午的代码调试 发现由于自己的粗心 导致了把<符号写成了<=符号 就因为这个问题,让贪吃蛇变成了 卡神,害我看了好几天,现在解决了,贪吃蛇也变流畅了好多. Ai蛇也需要吃食物。长大,在游戏刚启动的候就让Ai蛇在地图中吃食物,成长,当用户进入游戏的候AI蛇已经吃到了一定的食物。测试了AI蛇确实发现他能吃食物。死后的处理也处理了。 在AI蛇吃食物的候 ,地图中食物太多,控件太多。没法知道他是什么候,查了资料说是要遍历地图中的对象,测试了一下,发现对象太多,程序卡得不要不要的,只能用触发器,避免遍历食物让程序运行不流畅或者变得死机等情况。 这样的话 在游戏中运行10-20条蛇是没有问题的。 地图中有10个点,这10个点是用来AI蛇死后复活的地方。 增加了限定间模式. 经过很多的测试,也发现了很多的bug 不过都基本改完了,现在暂没有发现bug

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值