Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Checking a List Not Working

Discussion in 'Scripting' started by DRRosen3, Dec 22, 2014.

  1. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. [System.Serializable]
    6. public class Moves : MonoBehaviour {
    7.  
    8.     public List<Move> moves;
    9.     public List<Move> movesToLearn = new List<Move>();
    10.  
    11.     void Start(){
    12.         moves = gameObject.GetComponent<Monster>().monstersMoves;
    13.     }
    14.  
    15.     public void AddMoves(int level, List<Move> moves){
    16.         foreach(Move move in movesToLearn){
    17.             if(level >= move.levelLearned){
    18.                 if(!moves.Contains(move)){
    19.                     moves.Add(move);
    20.                 }
    21.             }
    22.         }
    23.     }
    24.  
    25. }
    26.  
    There's the code... Here's the problem...

    I call this function in the script that handles all of the properties of the monster. If the list of Moves already has the move in it, I don't want to add it again. Whenever I call this function, it adds the move to the list even if the list already has the move in it. I don't understand what I'm doing wrong.
     
  2. renman3000

    renman3000

    Joined:
    Nov 7, 2011
    Posts:
    6,697
    Must run a series of prints, or debug.logs. Place them strategically, from start to end. This will help you indentity the issue.
     
  3. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    The problem has to do with how the Contains() compares objects.

    The default behaviour is for the list to Compare object references. If the list contains a reference to the exact added object, Contains() will return true.

    Without seeing the code for your move class I'm not too sure, but I'm betting you're doing something functionally similar to this:

    Code (CSharp):
    1. public class Move {
    2.     int data = 0;
    3.  
    4.     public Move (int data) {
    5.         this.data = data;
    6.     }
    7. }
    8.  
    9. public class Comparer : MonoBehaviour {
    10.  
    11.  
    12.     List<Move> moveList = new List<Move>();
    13.  
    14.     void Update () {
    15.  
    16.         Move move = new Move(1);
    17.  
    18.         if (!moveList.Contains (move)) {
    19.  
    20.             Debug.Log("Added");
    21.  
    22.             moveList.Add(move);
    23.         }
    24.  
    25.     }
    26.  
    27. }
    28.  
    Notice that, even though the data contained within the new move instance is the same, it's going to keep adding this move to the moveList because the references arn't the same.

    What you need to do is have your move class implement the interface IEquatable:

    Code (CSharp):
    1. public class Move : IEquatable<Move> {
    2.     #region IEquatable implementation
    3.  
    4.     public bool Equals (Move other)
    5.     {
    6.         return this.data == other.data;
    7.     }
    8.  
    9.     #endregion
    10.  
    11.     int data = 0;
    12.  
    13.     public Move (int data) {
    14.         this.data = data;
    15.     }
    16. }
    17.  
    18. public class Comparer : MonoBehaviour {
    19.  
    20.  
    21.     List<Move> moveList = new List<Move>();
    22.  
    23.     void Update () {
    24.  
    25.         Move move = new Move(1);
    26.  
    27.         if (!moveList.Contains (move)) {
    28.  
    29.             Debug.Log("Added");
    30.  
    31.             moveList.Add(move);
    32.         }
    33.  
    34.     }
    35.  
    36. }
    37.  
    Now it's going to use your custom Equals method to compare the objects. How you go about actually implementing it depends on your class, but in the case of this example, if the data is the same, it'll behave as you expect.
     
    DRRosen3 and Crayz like this.
  4. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Thanks a lot @BenZed. I've never seen the IEquatable interface, but it looks like that will work. I'll give it a shot later today when I get home. Learn something new every day. :D
     
  5. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Worked like a charm! Thanks!
     
    BenZed likes this.