Search code examples
c#unity-game-engineuser-interfacescriptingscriptable-object

Why does the last element instantiated on a layout group appear as first and wrong?


I am programming a card game in unity and need the cards drawn to be displayed on a UI area bound by a Horizontal Layout Group, the cards are scriptable objects written in advance and displayed when drawn, but for some reason the last card of the deck I create and shuffle is displayed as a random different card, and moved as the first child of the area.

I tried checking the logic of all the functions involved, I found out that removing the shuffling solves the problem, but while debugging the shuffle function I found everything works as intended, so I concluded it must be only a graphical issue. I've also tried adding a Layout Element and Content Size Fitter but it's no use. I'll leave the DrawCards, CreateDeck and Shuffle functions below, for reference. Update: rewriting the DrawCards function with a static hand and deck doesn't fix it either.

   public class DrawCards : MonoBehaviour
{
    public GameObject playerCard;
    public GameObject playerArea;
    public CardDisplay display; 

public List<Card> Draw(List<Card> deck, int num)
{
    List<Card> handTemp = new List<Card>();
    RectTransform root = playerArea.GetComponent<RectTransform>();
    for (int i = 0; i < num; i++)
    {
        GameObject card = Instantiate(playerCard, playerArea.transform);
        Debug.Log("card instatiated");
        LayoutRebuilder.ForceRebuildLayoutImmediate(root);
        handTemp.Add(deck[0]);
        Debug.Log(deck[0].name);
        display.Set(deck[0]);
        deck.RemoveAt(0);
    }
    return handTemp;
    
  }

}

private List<Card> CreateDeck()
{
    List<Card> deck = new List<Card>();
    for (int i = 0; i < 6; i++)
    {
        deck.Add(startingCards[0]);
    }
    for (int i = 0; i < 6; i++)
    {
        //Debug.Log(i);
        deck.Add(startingCards[i]);
    }
    //Debug.Log("deck created");
    return deck;
}

public void Shuffle(List<Card> zone)
{
    int count = zone.Count;
    //Debug.Log("count" + count);
    int last = count - 1;
    //Debug.Log("last" + last);
    for (int i = 0; i < last; i++)
    {
        int random = Random.Range(i, count);
        //Debug.Log("random " + random);
        Card tmp = zone[i];
        //Debug.Log("tmp " + tmp.name);
        //Debug.Log("og " + zone[i].name);
        //Debug.Log("random card " + zone[random].name);
        zone[i] = zone[random];
        //Debug.Log("switched card " + zone[i].name);
        zone[random] = tmp;
        //Debug.Log("switched card " + tmp.name);
        
    }
}

Solution

  • Posting just in case anyone has a similar issue: I solved the problem, the issue is on the DrawCards function: since I was calling the Set function on the top card of the deck after instantiating it, the first card would always instantiate "unset", i.e. randomly. Moving the Set call before the Instantiate fixes the glitch.