我对团结很陌生,所以请容忍我的可怕解释。我在youtube上跟随了一个关于2D战斗游戏的教程:https://www.youtube.com/watch?v=n8S3WgVoOmo&t=3319s,我将在下面提供我的代码。在链接视频中,视频制作者制作了一个PlayerManager脚本,它控制着我的播放器和我的播放器的副本。通过一个简单的人工智能,复制成为我的敌人和我们战斗。这样做的效果不出所料。
现在我想要改变它,有点像一个2D平台。我拿了PlayerManager,把它分成两部分。AIManager (与教程中的代码相同)和一个有一些变化的PlayerManager。这也很好,我可以移动,AI也承认我。问题来自一个名为DamageScript的脚本。它识别是否和何时我受到伤害,并触发相关的动画。
当DamageScript连接到PlayerManager上时,当我点击AI或AI攻击我时,被击中的人就会显示伤害动画。但是在分开之后,我有两个选择,分别是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");
}
}
}
}
}不出所料,它不起作用,我仍然会在一些命中事故。如果可能的话,任何帮助都将不胜感激。谢谢!
发布于 2017-10-27 03:08:11
从您所描述的情况来看,我将假设错误主要是由于错误的责任委托重构。
更具体地说,我认为您所遵循的教程没有正确地遵循https://en.wikipedia.org/wiki/Single_responsibility_principle,而是在单个类/文件上实现了多个职责(player和AI),以节省视频的时间或简化教程。
稍后,当将责任划分为两个脚本和两个对象时,作为初学者,您不知道引用管理中涉及的一些细节和/或缺陷,因此无法为两个对象分配引用,或者在脚本现在被拆分时没有处理丢失的引用。
之所以会出现这个问题,是因为如果您的播放器和AI现在有不同的脚本集;每个管理器都有一个脚本,但两者都没有脚本(与以前不同,当时player和AI对象都“都有”);那么,无论是在第一个或第二个if*manager.damage语句上,都不会在GetComponent中找到所讨论的管理器,因为它不在该对象中,并且在试图访问null引用上的字段/属性/方法时,将引发NullReferenceException。
解决方案只是在访问这些字段/属性/方法之前执行正确的空检查,防止异常,如果发现第一个管理器是null,则继续执行第二个null语句。
尽管如此,最好还是缓存查询以使事情更好,正如RetiredNinja在注释中所建议的那样。
代码:
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");
}
}
}
}https://stackoverflow.com/questions/46965573
复制相似问题