【问题标题】:Unity: How to remove inactive gameObject from ListUnity:如何从列表中删除不活动的游戏对象
【发布时间】:2017-07-17 02:49:03
【问题描述】:

我制作了一个当前在我的盒子碰撞器中的游戏对象列表,它可以工作。但是,当我将游戏对象设置为非活动时,

gameObject.SetActive(false); // 消灭敌人

游戏对象保留在列表中而不会被删除。如何从另一个类的 OnTriggerEnter 函数的 List 中删除 gameObject?

PlayerLifeClass:

     private List<GameObject> ObjectsInRange = new List<GameObject>();
        public void OnTriggerEnter(Collider collider)
        {
            if (collider.tag != "Player" && collider.tag == "Zombie")
            {
                ObjectsInRange.Add(collider.gameObject);
                damage = ObjectsInRange.Count; //amount of zombies inside collider
               //***Over here***

                zombie.DamagePlayer(damage);
                Debug.Log(damage);
            }
        }
        public void OnTriggerExit(Collider collider)
        {
            if (collider.tag != "Player" && collider.tag == "Zombie")
            {
                //Probably you'll have to calculate wich object it is
                ObjectsInRange.Remove(collider.gameObject);
                Debug.Log(ObjectsInRange);
            }
        }

--

ZombieClass:

    public class Zombie : MonoBehaviour
    {
        public int currentHealth;
        private Player player;
        private PlayerLifeCollider playerCollider;

        public void Damage(int damageAmount)
        {
            //subtract damage amount when Damage function is called
            currentHealth -= damageAmount;

            //Check if health has fallen below zero
            if (currentHealth <= 0)
            {
                //if health has fallen below zero, deactivate it 
                gameObject.SetActive(false); //***Over here***

            }

   public void DamagePlayer(int damage)
    {
         player.Life(damage);
      }
   }

【问题讨论】:

  • 为什么不直接做Destroy(gameObject);
  • 会 Destroy(gameObject) 从列表中删除它吗?我本来打算这样做,但后来有人告诉我 SetActive(false) 性能更好。
  • 我觉得它只会使游戏对象为空,而不是从列表中删除它。
  • 我猜我听不懂你的问题,所以你想从 Zombie 类的 Damage() 函数内部的 ObjectsInRange 列表中删除游戏对象?
  • 是的。我认为替代方案的问题在于,如果您在停用后调用 List.Remove,它将无法正常工作。

标签: c# unity3d triggers gameobject


【解决方案1】:

如果我明白你想要什么,这样的事情就可以了,

PlayerLife 类

public static List<GameObject> ObjectsInRange = new List<GameObject>();

僵尸班

public void Damage(int damageAmount)
    {
        //subtract damage amount when Damage function is called
        currentHealth -= damageAmount;

        //Check if health has fallen below zero
        if (currentHealth <= 0)
        {
            //if health has fallen below zero, deactivate it
            PlayerLife.ObjectsInRange.Remove(gameObject); 
            gameObject.SetActive(false); //***Over here***
            //You can also do a Destroy(gameObject) if you'd like;

        }
    }

【讨论】:

  • 静态功能有效!但是,它迫使我将所有内容都更改为静态。有没有办法在没有静力学的情况下做一个衬里?
  • @BenSmith 如果您不想将所有变量设置为静态,您可以使用单例。请参阅下面的答案。
  • @BenSmith 它迫使你改变什么?你可以在类内外的任何地方访问静态变量。
【解决方案2】:

你有更多方法,我教你一个简单的。

修改你的僵尸类:

public bool Damage(int damageAmount)
{
    currentHealth -= damageAmount;
    if (currentHealth <= 0)
    {
        gameObject.SetActive(false); //***Over here***
        return true; 
    }
    return false;
}

和 PlayerLifeClass:

if (collider.tag != "Player" && collider.tag == "Zombie"){
    ObjectsInRange.Add(collider.gameObject);
    damage = ObjectsInRange.Count; //amount of zombies inside collider
    if(collider.GetComponent<Zombie>().Damage(damage)){
        // if zombie dead, remove him.
        ObjectsInRange.Remove(collider.gameObject);
    }
    Debug.Log(damage);
}

或类似的东西,但我认为这不是一个好的选择。

void Start(){
   playerLifeClass = GameObject.FindGameObjectWithTag("Player")>GetComponent<PlayerLifeClass>();
}
public bool Damage(int damageAmount)
{
    currentHealth -= damageAmount;
    if (currentHealth <= 0)
    {
    //if health has fallen below zero, deactivate it 
       gameObject.SetActive(false); //***Over here***
       playerLifeClass.RemoveZombie(gameObject);
    }
}

并在 PlayerLifeClass 中添加新方法:

public void RemoveZombie(GameObject zomb){
   ObjectsInRange.Remove(zomb);
}

或者使用 Singletons。 将新变量添加到 PlayerLifeClass:

...
public static PlayerLifeClass instance;
public List<GameObject> ObjectsInRange = new List<GameObject>();
...

void Start(){
    instance = this;
    ...
}

并在 Zombie.cs 中使用它:

 if (currentHealth <= 0){
    gameObject.SetActive(false); //***Over here***
    PlayerLifeClass.instance.ObjectsInRange.Remove(gameObject);
 }

【讨论】:

  • 好的,ps,我尝试了前两个,但没有成功。我得到了 NullReferenceException 或者当僵尸被停用时发生了同样的问题,而损坏没有回到零。
  • @BenSmith 是的,也许我的例子不是 100% 的解决方案,也许他们有一些错误,但他们应该给你一些想法。祝你好运)
  • 当我将zombie.DamagePlayer(damage) 声明为非静态时,我得到一个NullReferenceException。你知道如何解决吗?我觉得这只是了解基础知识。
  • 您的僵尸变量未初始化。试试看:if(collider.GetComponent()!=null){zombie = collider.GetComponent();僵尸.DamagePlayer(伤害); }}
猜你喜欢
  • 1970-01-01
  • 2021-11-22
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多