Search Unity

list.Count shows 2 different values

Discussion in 'Scripting' started by semir91, Jan 28, 2020.

  1. semir91

    semir91

    Joined:
    Jul 8, 2017
    Posts:
    24
    Hi guys, I got a really strange behavior of list.Count.

    My code:
    Code (CSharp):
    1. public void TakeNextCard()
    2.     {
    3.         activePlayer = GetMe();
    4.         if (FindObjectOfType<MyHand>().CountCards() >= 2 ||
    5.             cardList.Count <= 0) { return; }
    6.         else
    7.         {
    8.             int randomCardNumber = GetRandomCardNumber();
    9.             int cardInt = cardList[randomCardNumber];
    10.            
    11.            
    12.             if ( activePlayer.tag == "Me")
    13.             {
    14.                 Debug.Log(cardsInDeck.Count);
    15.                 FindObjectOfType<RoundSession>().
    16.                     StartCoroutine(FindObjectOfType<CardAnimation>().
    17.                     GiveCard(activePlayer, cardsInDeck.Count, cardInt));
    18.                 cardsInDeck.RemoveAt(cardsInDeck.Count - 1);
    19.                 activePlayer.addCard();
    20.                 cardList.RemoveAt(randomCardNumber);
    21.             }
    22.         }
    23.     }
    Code (CSharp):
    1. public void Update()
    2.     {
    3.         if(count % 100 == 0) {
    4.             Debug.Log(cardsInDeck.Count);
    5.         }
    6.         count++;
    7.     }
    The Update() method logs 2 before and after calling the TakeNextCard() method, but the log from the TakeNextCard() method logs 0. Both methods are from the same class and the other methods in TakeNextCard() don't change the cardsInDeck variable. Do you have an explanation for that?
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Update() doesn't call TakeNextCard though?
     
  3. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    What is
    cardsInDeck.Count
    at the end of
    TakeNextCard
    ? What happens if you log it after
    cardList.RemoveAt( ... )
    ?

    It is probably also a good idea to disambiguate the two log statements by appending an identifying string to the log message.
     
    Joe-Censored likes this.
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Are they in the same instance? That is, do you have more than one copy of this class in your scene? (If you pass "gameObject" as a second argument to Debug.Log, then clicking on the log message will highlight the object that emitted the message in your hierarchy view.)

    Where is the variable defined?

    Is TakeNextCard() throwing an exception? If not, then the "0" message is probably not coming from where you think it is, because line 18 should throw an ArgumentOutOfRangeException if cardsInDeck.Count is 0. You can't RemoveAt(-1).
     
  5. semir91

    semir91

    Joined:
    Jul 8, 2017
    Posts:
    24
    It's called on a click event.

    The code after StartCoroutine() isn't called, because it doesn't return from the coroutine. There's an ArgumentOutOfRangeException.
     
    Last edited: Jan 28, 2020
  6. semir91

    semir91

    Joined:
    Jul 8, 2017
    Posts:
    24
    There's only one instance of this class in the scene. But it's instantiated by a different class. I added the gameObject to the Debug.Log as you suggested and when I click on the log with the "0" it doesn't highlight the instance in the hierarchy. What do I need to do to make this work? It seems that by calling "this" I'm not calling this instance. Why does it work in the Update() method and doesn't work in my TakeNextCard() method?

    The variable is defined in the Start() method.

    That part of the code isn't called because I get ArgumentOutOfRangeException already in the coroutine.
     
  7. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    If you're getting an exception, you should probably lead with that. What line does the exception point to?
     
    Madgvox likes this.
  8. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    If it works for other messages but not for that exact message, then that message is probably not coming from the code that you think it's coming from.

    You probably mean that the variable is initialized in the Start() method. If it's declared in Start() then it won't be accessible from other methods.

    You haven't posted a coroutine.
     
    Last edited: Jan 28, 2020
  9. semir91

    semir91

    Joined:
    Jul 8, 2017
    Posts:
    24
    The exception gets thrown because of the cardsInDeck.Count is 0. It's on the line deck.GetChild(deckCount -1)

    It looks like the Update() function calls the instance in the scene and the TakeNextCard() calls something else.

    Yeah, sorry. The variable is a field in this class and is initialized in the Start() method.

    The coroutine isn't that important, because the Exception is thrown because of the cardsInDeck.Count being 0.
     
  10. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Look, if you think you know everything, why are you even asking us? You are asking about 'strange behaviour', but you are posting code that does not contain relevant invocations. You refer to unplublished code as 'something else' as if that was irrelevant. You then mention a hereto undocumented and unspecified coroutine but claim that, too, is unimportant -- even though that one throws an exception.

    This makes assisting you not only frustratingly difficult; it may turn off other kind people who might have otherwise been inclined to help you.

    The originally posted code has no problem. Therefore, at least one of the following two is true: you omitted relevant code, or you are simply hallucinating.
     
  11. semir91

    semir91

    Joined:
    Jul 8, 2017
    Posts:
    24
    I know how to C#. The problem is in the code I posted, because the Debug.Log() from the Update() always returns a 2 and the Debug.Log() from the TakeNextCard() returns a 0. If I comment the start of the coroutine out (just like in the code below, I'm getting the ArgumentOutOfRangeException in the line 15, because as I said cardsInDeck.Count is equal 0.

    Code (CSharp):
    1. public void TakeNextCard()
    2.     {
    3.         activePlayer = GetMe();
    4.         if (FindObjectOfType<MyHand>().CountCards() >= 2 ||
    5.             cardList.Count <= 0) { return; }
    6.         else
    7.         {
    8.             int randomCardNumber = GetRandomCardNumber();
    9.             int cardInt = cardList[randomCardNumber];
    10.          
    11.          
    12.             if ( activePlayer.tag == "Me")
    13.             {
    14.                 Debug.Log(cardsInDeck.Count);
    15.                 cardsInDeck.RemoveAt(cardsInDeck.Count - 1);
    16.                 activePlayer.addCard();
    17.                 cardList.RemoveAt(randomCardNumber);
    18.             }
    19.         }
    20.     }
     
  12. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    The fact that you discovered a symptom in this bit of code doesn't imply that the problem is necessarily in this bit of code.

    It's also difficult to follow your explanations when you are messing up basic terminology like defined vs initialized and calling vs called on, and first tell us there's an exception in a coroutine and then tell us the coroutine doesn't matter because the exception is being thrown from some other place. These distinctions are important to understanding what's going on.



    Look: odds of a fundamental bug in the List<T> class are pretty darn slim, so the only realistic options I can see here are (A) something is changing the contents of the list between these two functions, or (B) the two functions are actually using different variables named "cardsInDeck" (e.g. from different instances of the class, or as a result of shadowing). Either of those would imply that the problem is somewhere other than in the code you have posted.
     
    StarManta and Brathnann like this.