简体   繁体   中英

How can I stop adding the same item into list in Unity C#?

I'm trying to make rubik's cube game using unity and C# .

But i have problem when i want to add an item into a list. The problem is that the same item is constantly added to the list, I tried to use Contains() function but it doesn't work.

List<node>[,,] _NodeLi;

Note : I need to use this on the Update() method.

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));
        }
    }
}

And this is the node class:

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;
    }
}

I can't comment so i answer here. You have to override the Equals-Method. If you do so don't forget also to override the GetHashCode-Method.

[Here is explained why] Why is it important to override GetHashCode when Equals method is overridden?

Example for overriding Equals:

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

This is how the Contain-Method works:

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;
    }

Node is a class without a equals method, meaning that reference equality will be used. However, the 'nodes' array is created with brand new objects, so there is no possibility that 'buttonYFaces' or any of the other lists contain these same objects.

The solution would be to override the Equals method, and preferably also implement the IEquatable<node> interface. This should make the contains method work as you would expect

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM