我正在尝试将一个项目添加到我的LevelManager脚本中的列表中。对于敌人来说,当他死亡时,他的尸体的预制件会添加必要的碰撞器等,以便LevelManager处理。
敌人的脚本是:
using UnityEngine;
using System.Collections;
public class EnemyController : MonoBehaviour {
public Rigidbody2D rb;
public Animator anim;
public GameObject deadGuy;
public LevelManager manager;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
manager = GetComponent<LevelManager>();
}
// Update is called once per frame
void Update () {
if(anim.GetBool("Dead"))
{
StartCoroutine("Die");
}
}
private IEnumerator Die()
{
yield return new WaitForSeconds(anim.GetCurrentAnimatorStateInfo(0).length);
Instantiate(deadGuy, gameObject.transform.position, gameObject.transform.rotation);
manager.worldObjects.Add(deadGuy);
DestroyObject(gameObject);
}
}
死亡动画播放然后预制件在层次结构中被添加为“Dead Guy(clone)”,但随后动画再次播放并且实例化更多预制件。但是,如果我删除这行代码:
manager.worldObjects.Add(deadGuy);
然后播放动画,添加预制件并删除敌人对象。
答案 0 :(得分:1)
所以看起来最好的方法是将尸体处理成另一个脚本并将其附加到预制件上。因此,我可以实例化预制件,删除调用实例化的gameObject,并在Level Manager中不使用List
答案 1 :(得分:1)
简单解决方案
如评论中所述;它是因为动画师将bool Dead
设置为true,并且对于Unity的每次Update
调用,都会创建一个新的 dead player 。在播放死亡玩家的死亡动画之前,活着的玩家GameObject不会被销毁,并且在该动画期间将多次调用更新。
要解决此问题,请在您的课程中添加一个bool,例如;
private bool m_instantiatedDeadPlayer;
然后在更新循环中,将if语句更改为;
public void Update (
{
if(anim.GetBool("Dead") && !m_instantiatedDeadPlayer)
{
m_instantiatedDeadPlayer = true;
StartCoroutine("Die");
}
}
复杂的解决方案
更好但更复杂的方法是将死亡动画包含在与你的活着的敌人相同的动画师中,激活必要的碰撞器等,并从当前的活动动画转换为死动画为{当敌人的生命值等于0时你设置的{3}}。这假设你有一个方法附着在敌人面前造成伤害,这看起来像这样;
public void ApplyDamage(int p_amount)
{
if(!m_isDead)
{
m_health = Mathf.Clamp(m_health - p_amount, 0, 100);
if(m_health == 0)
m_animator.SetTrigger("Dead");
}
}
因此你消除了对Coroutine的需求,而是在敌人产生时将敌人添加到对象列表中,并且当你需要所有死敌时,有一个方法返回附加到的私有变量m_isDead
敌人。
希望这会有所帮助,如果您想了解更多详情,请与我们联系。