我最近开始学习C#,但遇到一个错误,希望你们中的一些人能帮我解决。我们正在用Unity5开发一款游戏,当玩家的生命值降为0时,布娃娃功能就会启动,但不幸的是我无法调用死亡方法,因为它是一个方法组…你们有什麼想法吗?谢谢。这里是我的代码(我已经注释掉了它,这样我就能在Unity中进入播放模式,因为这个错误让我无法在第47行和第53行进入):
using UnityEngine;using System.Collections;public class EnemyAI_Basic : MonoBehaviour{ private EnemyAI_Basic enemyAI_Basic; Animator controller; float health; Animator anim; bool Alive = true; public bool Dead = false; int pointValue = 5; private Collider myCollider; private Rigidbody myRigidbody; CapsuleCollider capsuleCollider; void Start() { controller = GetComponentInParent<Animator>(); health = 40; capsuleCollider = GetComponent<CapsuleCollider>(); anim = GetComponent<Animator>(); } void Update() { if (!Dead) { anim.SetTrigger("Alive"); } } void Death() { Dead = true; Alive = false; capsuleCollider.isTrigger = true; anim.SetTrigger("Dead"); Destroy(gameObject, 4f); } void OnEnable() { SetInitialReferences(); enemyAI_Basic.Death += ActivateRagdoll; } void OnDisable() { enemyAI_Basic.Death -= ActivateRagdoll; } void SetInitialReferences() { enemyAI_Basic = transform.root.GetComponent<EnemyAI_Basic>(); if (GetComponent<Collider>() != null) { myCollider = GetComponent<Collider>(); } if (GetComponent<Rigidbody>() != null) { myRigidbody = GetComponent<Rigidbody>(); } } void ActivateRagdoll() { if (myRigidbody != null) { myRigidbody.isKinematic = false; myRigidbody.useGravity = true; } if (myCollider != null) { myCollider.isTrigger = false; myCollider.enabled = true; } }}
回答:
我明白了你的问题。你把死亡方法当成委托来处理,而它实际上不是。在这种情况下,你只能将方法注册到委托或事件上,不能将方法注册到方法组。对于你的情况,有几种解决方法。
第一种解决方案,也是最简单的方法,就是在Death函数内部调用ActivateRagdoll方法,像这样:
void Death(){ Dead = true; Alive = false; capsuleCollider.isTrigger = true; anim.SetTrigger("Dead"); ActivateRagdoll(); Destroy(gameObject, 4f);}
然后删除以下代码:
enemyAI_Basic.Death += ActivateRagdoll;
和
enemyAI_Basic.Death -= ActivateRagdoll;
从OnEnable和OnDisable方法中删除这些代码,这样应该可以消除任何编译错误。现在,要使用这个方法,你只需要在代码中的某个地方调用它。根据你如何杀死AI,你可能需要考虑将该方法设为公共的,或者在更新循环中加入一些死亡逻辑,
if(health <= 0){ Death(); enabled = false; //禁用该组件,以免更新循环多次重复死亡过程,Unity可能会不高兴。}
另一种方法,也就是你试图使用的方法,是创建一个事件,让类可以订阅方法。这个事件将调用所有订阅的方法,为它们提供一种被通知的手段,每当发生有趣的事情时,比如在这种情况下AI死亡。这对于外部类来说非常有用,这些类不应该总是检查AI的死亡状态,事实上,如果AI处于满血状态,它们可能并不关心AI。它们只需要知道AI何时死亡。事件非常适合这种情况。
要创建一个事件,你需要做类似这样的事情:
public class EnemyAI_Basic : MonoBehaviour{ //你的其他变量 public delegate void EnemyDies(); //声明可以注册到事件的方法类型 public event EnemyDies onEnemyDeath; //声明事件,使用委托作为方法类型 //这里是其他方法 private void OnEnable() { //必须与事件的方法类型相同,如果不是,编译器会告诉你 onEnemyDeath += Death; onEnemyDeath += ActivateRagdoll; } private void OnDisable() { onEnemyDeath -= Death; onEnemyDeath -= ActivateRagdoll; } //这里是其他东西 //不必是公共的,万一你想用一颗子弹杀死敌人 public void KillAi() { //检查是否为null基本上是说:有人注册了吗?如果没有,就没有必要调用。 //如果没有注册方法就试图调用事件,它会很不高兴,所以需要检查。 if(onEnemyDeath != null) { onEnemyDeath(); } } void Death() { Dead = true; Alive = false; capsuleCollider.isTrigger = true; anim.SetTrigger("Dead"); //ActivateRagdoll(); 现在你不必手动调用这个,调用事件会为你调用它。 //注册顺序很重要,我觉得。尝试一下 :) Destroy(gameObject, 4f); }}
还有其他几种方法可以设置这样的系统,但在你的情况下,这可能就是你想要的。
一些阅读资料:
事件: https://www.codeproject.com/Articles/11541/The-Simplest-C-Events-Example-Imaginablehttps://www.tutorialspoint.com/csharp/csharp_events.htm
委托: https://msdn.microsoft.com/en-us/library/ms173171.aspx
方法组: C#中的方法组是什么?
希望这对你有帮助。