【问题标题】:Pickups spawned using coroutines do not behave as they should使用协程生成的拾取器行为不正常
【发布时间】:2020-08-10 06:39:27
【问题描述】:

我创建的这个简单游戏围绕着玩家收集不同的拾取物来得分。我在拾取的 GameObject 上实现了协程,因此它们每隔几秒就会有规律地生成。

但是,我创建的拾取器在第二次生成后无法使用。这个名为 Jeans 的 GameObject 是一个拾取物,玩家收集这些拾取物来得分。

但是,第二个和后续的拾取器生成的所有“对应”都与第一个生成的拾取器“对应”。意思是,如果有 3 个生成的游戏对象实例,如果我要收集预制件 2 或 3,游戏对象 1 将消失并添加分数。但是,无法收集游戏对象的未来生成。玩家只会通过它们。

这些是代码:

Consumable.cs

public class Consumable{
      
    // declare a variable of type 'items'
    // using autoproperties {get; private set;}
    // cannot be initialised in the beginning
        
    public items type{get; private set;}
    public float damage{get; private set;}
    public float health{get; private set;}
    
    // create the constructor
    public Consumable (items type, float damage, float health){
        this.type = type;
        this.damage = damage;
        this.health = health;
    }
}

裤子.cs

public class Pants : Consumable
{
    public int amount{get ; private set;}
    public GameObject [] pants;
    private int index = 0;
    
    public Pants(items type, int amount, float damage = 0, float health = 0) : base (type, damage, health){
        this.amount = amount;
        pants = new GameObject[amount];
        ItemManager.onHit += hit;
    }
    
    public void add(GameObject pant){
        if (index < amount){
            pant.GetComponent<BasicObjectScript>().index = index;
            pant.GetComponent<BasicObjectScript>().type = type;
            pants[index] = pant;
            index ++;
        }
    }
    public void hit(items type, int index){
        if (type == this.type){
            pants[index].SetActive(false);
            amount --;
        }
    }
}

ItemManager.cs

public class ItemManager : MonoBehaviour
{
    private Pants jeans;
    
    public GameObject JeansPrefab;
    
    void Start(){
    …
        jeans = new Pants(Consumable.items.JEANS, Random.Range(1, 1), 0 ,15);
        StartCoroutine(CreateObject());
    }
    
        …
    private void instantiateJeans(){
        jeans.add(Instantiate(JeansPrefab, new Vector2(Random.Range(-rangeX, rangeX), Random.Range(-rangeY, rangeY)), Quaternion.identity));
    }
    
    IEnumerator CreateObject(){
        while(true){ 
            yield return new WaitForSeconds(Random.Range(1f, 2f));
            instantiateJeans();
        }        
     }

    ...

public void consumablesHit(float speed, Consumable.items type, int index){
    Debug.Log("consumables Hit!" + " of type " + type.ToString());
    if (onHit != null){ //check if the event has any listeners
        onHit(type, index); //if yes, call them
    }
    // score update

    if (type == Consumable.items.JEANS){
        score += (int) jeans.health;           
    }

调用 hit 方法的 BasicObjectScript:

public class BasicObjectScript : MonoBehaviour, BasicObjectInterface{
    public int index; 
    public Consumable.items type;
    public GameObject ItemManager;
  
    //this is the method that one has to implement (because of the adopted BasicObjectInterface)
    public void getHit(float speed){   
        ItemManager = GameObject.FindGameObjectWithTag("ItemManager");
        // call the ItemManager's consumables hit method, and the item manager will notify everybody
        ItemManager.GetComponent<ItemManager>().consumablesHit(speed, type, index);

    }
}

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    为了清楚起见,编辑我的答案。

    我认为每次创建新裤子时都会创建一个新数组。您可以在 ItemManager 类中创建您的裤子数组并尝试使用该数组吗?

    【讨论】:

    • 我对统一很陌生,所以当你的意思是 GetInstanceID 时,我应该为每个生成的游戏对象创建一个唯一的 ID,而不是私有 int 索引?对于禁用数组的第二种方法,我该怎么做呢?我只是 SetActive(False) consumablesHit 方法上的游戏对象吗?谢谢!
    • 我自己不是专家,但我只是想为您找到一条捷径。我将编辑我的答案以清除
    • 我已经看到你的编辑,我尝试删除 GameObject 数组但它仍然不起作用。
    • 那么请尝试将游戏对象传递给 hit 方法并尝试禁用该游戏对象。你也可以分享 BasicObjectScript 或调用 hit 方法的任何脚本
    • 我已将 basicobjectscript 添加到问题中。非常感谢您的宝贵时间。
    猜你喜欢
    • 2014-03-02
    • 2016-02-02
    • 1970-01-01
    • 2020-02-27
    • 2015-12-11
    • 2017-06-04
    • 2017-09-02
    • 2011-04-29
    • 1970-01-01
    相关资源
    最近更新 更多