【问题标题】:How can I stop adding the same item into list in Unity C#?如何停止将相同的项目添加到 Unity C# 中的列表中?
【发布时间】:2020-02-28 08:45:48
【问题描述】:

我正在尝试使用 unity 和 C# 制作魔方游戏。

但是当我想将一个项目添加到列表中时我遇到了问题。 问题是相同的项目不断添加到列表中,我尝试使用Contains() 函数但它不起作用。

List<node>[,,] _NodeLi;

注意:我需要在Update()方法上使用这个。

void Update()
{

    nodes = new node[3, 3, 3];
    Vector3 cubeButtonLeftDown = new Vector3((size / 2 * -1) + (size / 3), (size / 2 * -1) + (size / 3)
        , (size / 2 * -1) + (size / 3));
    for (int x = -1; x <= 1; x++)
    {
        for (int y = -1; y <= 1; y++)
        {
            for (int z = -1; z <= 1; z++)
            {
                node Node = new node(new Vector3(x, y, z), new Vector3
                   (x * size / 6,
                    y * size / 6,
                    z * size / 6));
                nodes[x + 1, y + 1, z + 1] = Node;
            }
        }
    }
    // find the faces of the cube
    //find the y faces
     foreach(node Node_ in nodes) { 
        if (Node_.InRubikCubePos.y == 1)
        {
            if (buttonYFaces.Contains(Node_))
                buttonYFaces.Remove(Node_);

            if (!topYFaces.Contains(Node_))
                topYFaces.Add(Node_);

        }
        else if (Node_.InRubikCubePos.y == -1)
        {
            if (topYFaces.Contains(Node_))
                topYFaces.Remove(Node_);

            if (!buttonYFaces.Contains(Node_))
                buttonYFaces.Add(Node_);

        }
        else
        {
            if (buttonYFaces.Contains(Node_))
                buttonYFaces.Remove(Node_);

            if (topYFaces.Contains(Node_))
            topYFaces.Remove(Node_);

        }

    }
    // find the x faces
    foreach (node Node_ in nodes)
    {
        if (Node_.InRubikCubePos.x == 1)
        {
            if (leftXFaces.Contains(Node_))
                leftXFaces.Remove(Node_);

            if (!rightXFaces.Contains(Node_))
                rightXFaces.Add(Node_);

        }
        else if (Node_.InRubikCubePos.x == -1)
        {
            if (rightXFaces.Contains(Node_))
                rightXFaces.Remove(Node_);

            if (!leftXFaces.Contains(Node_))
                leftXFaces.Add(Node_);
        }
        else
        {
            if (leftXFaces.Contains(Node_))
                leftXFaces.Remove(Node_);

            if (rightXFaces.Contains(Node_))
                rightXFaces.Remove(Node_);

        }
    }
    // find the z faces
    foreach (node Node_ in nodes)
    {
        if (Node_.InRubikCubePos.z == 1)
        {
            if (leftZFaces.Contains(Node_))
                leftZFaces.Remove(Node_);

            if (!rightZFaces.Contains(Node_))
                rightZFaces.Add(Node_);
        }
        else if (Node_.InRubikCubePos.z == -1)
        {
            if (rightZFaces.Contains(Node_))
                rightZFaces.Remove(Node_);

            if(!leftZFaces.Contains(Node_))
            leftZFaces.Add(Node_);
        }
        else
        {
            if (leftZFaces.Contains(Node_))
                leftZFaces.Remove(Node_);

            if (rightZFaces.Contains(Node_))
                rightZFaces.Remove(Node_);
        }
    }
    // find the vert positions
    if (vertPositions.Count < 8)
    {
        foreach (float x in _One)
        {
            foreach (float y in _One)
            {
                foreach (float z in _One)
                {
                    vertPositions.Add(new Vector3(x, y, z));
                }
            }
        }
    }
    foreach(Vector3 n in vertPositions)
    {
        Debug.Log(n);
    }
        Debug.Log(vertPositions.Count);
    Debug.Log("Y :" + topYFaces.Count +",,,,, :" +buttonYFaces.Count);
    }
private void OnDrawGizmos()
{
    if (nodes != null)
    {
        foreach (node n in nodes)
        {
            Gizmos.DrawWireCube(n.inWorldPos, Vector3.one * (size / 6));
        }
    }
}

这是节点类:

public class node{
    public Vector3 InRubikCubePos;
    public Vector3 inWorldPos;
    //IRCPos mean's " InRubikCubePos " and the IWPos mean's " inWorldPos " 
    public node(Vector3 IRCPos, Vector3 IWPos)
    {
        InRubikCubePos = IRCPos;
        inWorldPos = IWPos;
    }
}

【问题讨论】:

  • 您可以使用HashSet 而不是List 来确保不会向集合中添加重复项
  • 可能node 是一个没有相等比较器的结构。你能告诉我node的类吗?
  • @JackMariani 我一定会告诉你的

标签: c# unity3d game-engine


【解决方案1】:

我无法发表评论,所以我在这里回答。您必须覆盖 Equals 方法。如果您这样做,请不要忘记覆盖 GetHashCode-Method。

[这里解释为什么]Why is it important to override GetHashCode when Equals method is overridden?

覆盖 Equals 的示例:

public override bool Equals(object obj)
    {
        return obj is node candidate && this.inWorldPosition.ExampleInt == candidate.ExampleInt;
    }

这是包含方法的工作原理:

public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value) {
        ICollection<TSource> collection = source as ICollection<TSource>;
        if (collection != null) return collection.Contains(value);
        return Contains<TSource>(source, value, null);
    }

    public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
    {
        if (comparer == null) comparer = EqualityComparer<TSource>.Default;
        if (source == null) throw Error.ArgumentNull("source");
        foreach (TSource element in source)
            if (comparer.Equals(element, value)) return true;
        return false;
    }

【讨论】:

    【解决方案2】:

    Node 是一个没有 equals 方法的类,这意味着将使用reference equality。但是,“nodes”数组是用全新的对象创建的,因此“buttonYFaces”或任何其他列表都不可能包含这些相同的对象。

    解决方案是重写 Equals 方法,最好还实现IEquatable&lt;node&gt; 接口。这应该使 contains 方法按您的预期工作

    【讨论】:

    • 很抱歉,当我使用 IEquatable 接口时我应该使用什么类型
    • @Yacine_Dev_Artist 使用要比较的类型,所以在这种情况下与类本身相同,即公共类节点:IEquatable
    猜你喜欢
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多