【问题标题】:Unity For loop inside of OnTriggerEnter2D causes sometimes multiple outcomesOnTriggerEnter2D 内部的 Unity For 循环有时会导致多个结果
【发布时间】:2022-01-22 08:01:52
【问题描述】:

嗨,我是统一和编程的新手,如果这是个愚蠢的问题,我很抱歉,我相信有更好的方法可以做到这一点。基本上我遵循了带有可拖动组件的库存教程,现在我正在实施他的方法来在我的游戏中拾取物品。我用他的 id 标记了每个项目。标签是 Item_0、Item_1、Item_2 等。我在 OnTriggerEnter2D 中使用 for 循环来确定我拾取的项目。

库存有代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    public List<Item> CharacterItmes = new List<Item>();
    public ItemDatabase itemDatabase;
    public UIInventory inventoryUI;
    [SerializeField] private GameObject inventory;

    private void Start()
    {
        inventoryUI.gameObject.SetActive(true);
     // Iniciate Items
        inventoryUI.gameObject.SetActive(false);
    }

    private void Update()
    {
        if (Input.GetButtonDown("Inventory"))
        {

            inventoryUI.gameObject.SetActive(!inventoryUI.gameObject.activeSelf);
        }
    }
    public void GiveItem(int id)
    {
        Item itemToAdd = itemDatabase.GetItem(id);
        CharacterItmes.Add(itemToAdd);
        inventoryUI.AddNewItem(itemToAdd);
       // Debug.Log("Added item: " + itemToAdd.title);
    }

    public void GiveItem(string itemName)
    {
        Item itemToAdd = itemDatabase.GetItem(itemName);
        CharacterItmes.Add(itemToAdd);
        inventoryUI.AddNewItem(itemToAdd);
       // Debug.Log("Added item: " + itemToAdd.title);
    }

    public Item CheckForItem(int id)
    {
        return CharacterItmes.Find(item => item.id == id);       
    }

    public void RemoveItem(int id)
    {
        Item itemToRemove = CheckForItem(id);
        if (itemToRemove != null)
        {
            CharacterItmes.Remove(itemToRemove);
            inventoryUI.RemoveItem(itemToRemove);
           // Debug.Log("Removed Item: " + itemToRemove.title);
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        for (int i = 0; i <= 5; i++)
        {

            if (other.gameObject.CompareTag("Item_" + i.ToString()))
            {
                GiveItem(i);
                Debug.Log("Item_" + i.ToString());
                Destroy(other.gameObject);
            }
        }

        

    }
}

我现在只有 6 个项目用于测试目的,稍后我将用 ItemDatabase 中的所有项目替换 for 循环中的长度。

我已经用正确的标签标记了所有项目,并且我检查了两次我的角色只有 1 个 Collider2D 和刚体,以及我的所有项目。只有 1 个 Collider2D 设置为触发器。所以我不知道为什么我有时会两次拿起这个物品:

This is the result

任何想法为什么它会多次拾取或一些更好的方法来处理拾取它? 我会很高兴得到任何建议。非常感谢

【问题讨论】:

  • 当您重新运行并重试时会发生什么?具体是 Item_4 出现了两次还是有所不同?

标签: c# unity3d


【解决方案1】:

不要为您拥有的每件物品都使用标签,尤其是如果这意味着每次在您的库存中拖动某些物品时您都必须循环浏览许多物品。这是不必要的计算,如果您有多种物品,可能会减慢您的游戏速度。

相反,为每个项目附加一个简单的 mb:

public class Pickupable : MonoBehaviour
{
    public int itemId;
}

然后在OnTriggerEnter2D中,检查触发器是否附加到这样的mb,如果是,则从中获取id:

Pickupable p = other.GetComponent<Pickupable>();
if (p != null)
{
    int id = p.itemId; 
    GiveItem(id);
    Debug.Log($"Item_{id}"); // format string is easier to read
    Destroy(other.gameObject);
}

【讨论】:

  • 非常感谢,这是一个更聪明的解决方案,但它并没有解决我的问题,我仍然拿起多个项目,所以问题不在 for 循环中,而是在其他地方。 imgur.com/NMWFdip 无论如何感谢您提供更好的解决方案。我未选中标签,并且项目只有 1 个 Collider2D,触发器已选中,并且带有 ID 的 Pickupable 脚本
  • 这听起来与问题中提到的问题不同。如果您想ask a new questionminimal reproducible example,包括如何从头开始设置场景、要包含的游戏对象以及重现问题所要附加的组件,当然有人可以帮助您。请参阅 this question 了解一个很好的例子。
【解决方案2】:

我很傻。我的角色确实有多个盒子对撞机。唯一的问题是他隐藏在儿童 GameObject 中并且正在为其他游戏机制提供功能,所以我删除了那个 BoxCollider 并以其他方式找出了那个机制。现在一切正常:)

因此,如果有人遇到类似问题,请务必确保您只有 1 个 BoxCollider。关于对象和角色

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多