【问题标题】:Unity 2D: NullReferenceException. How to add two manager scripts?Unity 2D:NullReferenceException。如何添加两个管理器脚本?
【发布时间】:2017-10-27 00:04:11
【问题描述】:

我对 Unity 很陌生,所以请忍受我可怕的解释。我在 youtube 上关注了一个关于 2D 格斗游戏的教程:https://www.youtube.com/watch?v=n8S3WgVoOmo&t=3319s 我将在下面提供我的代码。 在链接的视频中,视频制作者制作了一个PlayerManager 脚本来控制我的播放器和我的播放器的副本。通过一个简单的人工智能,复制品成为我的敌人,我们战斗。这很符合预期。

现在我想把它改成 2D 平台游戏。我拿了PlayerManager 并将它一分为二。 AIManager(与整个教程中的代码相同)和 PlayerManager 进行了一些更改。这也很有效,我可以移动,人工智能也能认出我。问题来自一个名为 DamageScript 的脚本。它会识别我是否以及何时受到伤害,并触发相关动画。

DamageScript 仅连接到PlayerManager 时,当我击中 AI 或 AI 击中我时,被击中的人都会显示伤害动画。但是在我拆分之后,使用单独的 AI 和 Player 经理,我有两个选择。要么我击中 AI,他会做伤害动画,当他击中我时,我会出错。或者他打我,我有伤害动画,当我打他时我得到一个错误。错误是这样的:

NullReferenceException: Object reference not set to an instance of an object
DamageScript.OnTriggerEnter2D (UnityEngine.Collider2D col) (at Assets/Scripts/DamageScript.cs:19)

这是原始的 DamageScript:

public class DamageScript : MonoBehaviour {

void OnTriggerEnter2D(Collider2D col)
    {
        if(col.transform.root != transform.root && col.tag != "Ground" && !col.isTrigger)
        {
            if (!col.transform.GetComponent<AIManager>().damage && !col.transform.GetComponent<PlayerManager>().blocking)
            {
                col.transform.GetComponent<AIManager>().damage = true;

                col.transform.root.GetComponentInChildren<Animator>().SetTrigger("Damage");
            }
        }
    }
}

这样我的播放器会执行伤害动画,我在击中时会收到错误消息。所以,我认为这样的事情会起作用,但我想我真的不知道如何编码:

void OnTriggerEnter2D(Collider2D col)
    {
        if(col.transform.root != transform.root && col.tag != "Ground" && !col.isTrigger)
        {
line 11           if (!col.transform.GetComponent<AIManager>().damage && !col.transform.GetComponent<AIManager>().blocking)
            {
                col.transform.GetComponent<AIManager>().damage = true;

                col.transform.root.GetComponentInChildren<Animator>().SetTrigger("Damage");
            }
            else
            {
                if (!col.transform.GetComponent<PlayerManager>().damage)
                {
line 19        col.transform.GetComponent<PlayerManager>().damage = true;

                    col.transform.root.GetComponentInChildren<Animator>().SetTrigger("Damage");
                }
            }
        }
    }
}

毫不奇怪,它不起作用,而且我仍然会在某些点击时崩溃。 如果可能的话,任何帮助将不胜感激。 谢谢!

【问题讨论】:

  • 第 19 行是哪一行?
  • 我添加了错误行。现在这取决于我是打 AI 还是他打我。如果我只留下原始代码,只有当我点击 AI 时才会出现错误。现在我可以用一次攻击击中他,并且在几秒钟内尝试它通常会崩溃。如果他撞到我也直接崩溃。我似乎无法让这两个脚本一起工作。

标签: animation unity3d unity5 unity3d-2dtools


【解决方案1】:

根据您描述的情况,我认为错误主要是由于责任委派的错误重构造成的。

更具体地说,我相信你所遵循的教程没有正确遵循single responsibility principle,而是在单个类上实现了多个职责(玩家和AI)/文件,以节省视频时间,或简化教程。

后来,在将职责拆分为两个脚本和两个对象时,作为初学者的您之前/不知道引用管理中涉及的一些细节和/或陷阱,因此未能为这两个对象分配引用,或者由于脚本现在被拆分,无法处理丢失的引用。

出现问题的原因是,如果您的播放器和 AI 现在有不同的脚本集;每个经理都有一个,但两者都没有(不像以前,玩家和 AI 对象都有“两者”);然后,无论是在第一个或第二个if*manager.damage 语句中,都不会使用GetComponent 找到有问题的经理,因为它不在该对象中,并且在尝试访问@987654325 上的字段/属性/方法时@reference,NullReferenceException 会被抛出。

解决方案只是在访问此类字段/属性/方法之前进行适当的空检查,以防止异常发生,如果发现第一个经理是 null,则继续执行第二个 if 语句。

同时,不妨缓存查询以使事情变得更好,正如 RetiredNinja 在 cmets 中推荐的那样。


代码:

void OnTriggerEnter2D(Collider2D col) {
    if(col.transform.root != transform.root && col.tag != "Ground" && !col.isTrigger) {
        //Cache to avoid multiple queries and to simplify access
        var playermanager = col.transform.GetComponent<PlayerManager>(); //One of these won't be found and will receive null instead
        var aiManager = col.transform.GetComponent<AIManager>(); //One of these won't be found and will receive null instead
        var animator = col.transform.root.GetComponentInChildren<Animator>();

        if (aiManager != null //Null-check was missing
          && !aiManager.damage && !aiManager.blocking) { //Much nicer
            aiManager.damage = true;
            if(animator!=null)
                animator.SetTrigger("Damage");
        }
        else {
            if (playerManager != null && !playerManager.damage) {
                playerManager.damage = true;

                animator.SetTrigger("Damage");
            }
        }
    }
}

【讨论】:

  • 像魅力一样工作!我真的很感激,我绝对不会自己做,现在我知道如何处理类似的问题了。
猜你喜欢
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2017-09-04
  • 1970-01-01
  • 2019-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多