首页 > 解决方案 > Unity - C#试图在另一个列表中的对象被销毁时更改一个列表中的项目的标签

问题描述

最近参加了一个关于初学者 c# w/unity 的在线课程,不幸的是,讲师以一个损坏且未完成的代码结束了课程。有了大约 3 周的经验,我决定在继续之前学习、研究并做出可行的构建。

我有两个列表和一个变量:

private List<Widget> WidgetList = new List<Widget>();
private List<Collider2D> ItemList = new List<Collider2D>();
private Collider2D itemSpot;

然后,我在 update 方法中有一个 if 语句,单击鼠标左键后,代码会更改所单击项目的标签,将该项目添加到 a ItemList,并在该位置生成一个新的 Widget。

if (Input.GetMouseButtonDown (0)) {
        Vector2 worldPoint = Camera.main.ScreenToWorldPoint (Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast (worldPoint, Vector2.zero);
        if (hit.collider.tag == "BlankItem") {
            itemSpot = hit.collider;
            itemSpot.tag = "FullItem";
            RegisterItemSpot (itemSpot);
            MakeWidget (hit);
         }
}

这目前工作正常,尽管我觉得它不是最理想的代码(不是一个制作精良的课程)。对RegisterItemSpotMakeWidget方法的调用完美无缺,每个都正确使用 .Add 到各自的列表中。在游戏结束时,我有一个方法可以毫无问题地清除两个列表。

这是我的障碍:如果我销毁 Widget 的单个实例,我希望与之关联的 itemSpot"BlankItem"再次将其标记更改为。我使用了与之前类似的函数来销毁 Widget:

 void Update (){
        if (Input.GetMouseButtonDown (0)) {
            Vector2 worldPointt = Camera.main.ScreenToWorldPoint (Input.mousePosition);
            RaycastHit2D hitt = Physics2D.Raycast (worldPointt, Vector2.zero);
            if (hitt.collider.tag == "Tower" && destroyMode != false)
                Destroy(hitt.transform.gameObject);

            }

        }

从那里在OnDestroyWidget 类中,我将其从列表中删除,这也很好。

在我的脑海中,我想象有几行代码,在OnDestroyWidget 中,将重命名itemSpot最初与该特定已销毁 Widget 相关联的 。我不知道如何将新的 Widget 与特定的itemSpot. 类似于“如果该对象被破坏,则与该对撞机关联的对象将被重新标记”之类的东西。我有几个想法需要从头开始重建这段代码(也许制作数组而不是列表?)我觉得我的新手大脑最好继续我的下一门课程,而不是花所有时间。也许不吧?我只是需要一些更有经验的人的建议。如果我需要提供更多信息,请告诉我(10 类数百个代码似乎太多了,不能在这里抛出)。

编辑:我已经包含了 MakeWidget() 方法和 RegisterItemSpot() 和 RegisterWidget() 方法。我应该从一开始就有,非常抱歉!

    public void MakeWidget (RaycastHit2D hit){
    if (!EventSystem.current.IsPointerOverGameObject) {
        Tower newWidget = Instantiate (widgetBtnPressed.WidgetObject);
        newWidget.transform.position = hit.transform.position;
        RegisterWidget (newWidget);
        widgetBtnPressed = null;}
    }
    public void RegisterItemSpot (Collider2D itemSpot){
    ItemList.Add(itemSpot);
    }
    public void RegisterWidget (Widget widget)
    {
    WidgetList.Add(widget);
    }

标签: c#unity3d

解决方案


我认为您最好的方法是创建一个新的容器类,然后声明该类的新列表。这是一个例子

public class WidgetContainer()
{
    public Widget widget;
    public Collider2D collider;
}

然后用这个替换你的两个列表

public List<WidgetContainer> widgetContainers = new List<WidgetContainer>();

然后将您的 makewidget 和 registeritemspot 方法合并到一个方法中,并创建一个新的 WidgetContainer 并将其添加到列表中。现在,您将始终在这两个变量之间存储一个连接。

var newContainer = new WidgetContainer
{
    widget = newWidget,
    collider = itemSpot
}

最后,在您描述的上述小部件的 OnDestroy() 中,您可以执行以下操作:

widgetContainers.First(x => x == this).collider.tag = "your tag here";

“this”引用类的实例。在您的情况下,这将是您的 Widgetscript。

不要认为您需要在 Linq 脚本的顶部添加此 using 语句。

using System.Linq;

推荐阅读