code wont enter for/foreach loops

    public void AddLvl(GameObject button)
    {
        Debug.Log(((button.transform.parent).transform.parent).name);
        Player currentPlayer = null;
        for (int i = 0; i < Players.Count; i++)
        {
            Player player = Players[i];
            Debug.Log("Player name: " + player.Name);
            if (player.Name + " menu" == ((button.transform.parent).transform.parent).name)
            {
                currentPlayer = player;
                Debug.Log("Set current player to: " + currentPlayer);
            }
        }
        Debug.Log("Current player is: " + currentPlayer);
        currentPlayer.Lvl += 1;
        currentPlayer.Statpoints += 3;
        UpdateStats(currentPlayer);
        Debug.Log("Level added");
        Debug.Log("player has " + currentPlayer.Statpoints);
    }


This is the output
Line 311 ----> line 16 in thread

Help would be much appreciated, if more info is required feel free to ask

Im guessing the line 5 here is the 311 mentioned in the error?

Line 311 ----> line 16 in thread it is said in the original post but all good

It seems the players list is empty. Try to print the list count, if it’s 0, you need to collect your players first.

1 Like

I have checked and it is empty but I am not sure why because I am adding a player to it every time the confirm button is pressed in this code

    public void ConfirmPlayer(GameObject readyPlayerBox)
    {
        if (tempPlayer == lastMade)
        {
            return;
        }
        Vector3 scale = new Vector3(1f, 1f, 1f);
        RectTransform originalRectTransform = readyPlayerBox.GetComponent<RectTransform>();

        Vector2 newBoxPos = new Vector2(originalRectTransform.anchoredPosition.x + Players.Count * 130 + 130, originalRectTransform.anchoredPosition.y);
        GameObject playerBox = Instantiate(readyPlayerBox);
        RectTransform newRectTransform = playerBox.GetComponent<RectTransform>();
        TextMeshProUGUI playerText = playerBox.GetComponentInChildren<TextMeshProUGUI>();
        playerText.rectTransform.SetParent(playerBox.transform.GetChild(0).parent);
        playerBox.transform.SetParent(readyPlayerBox.transform.parent);

        playerBox.transform.name = tempPlayer.Name + " player button";
        newRectTransform.localScale = scale;
        playerText.enableWordWrapping = false;
        playerText.name = tempPlayer.Name + " Text";
        playerText.text = tempPlayer.Name;
        playerText.rectTransform.anchoredPosition = new Vector2(0 , 0);
        playerText.rectTransform.offsetMax = new Vector2(-5, -5);
        playerText.rectTransform.offsetMin = new Vector2(5, 5);
        newRectTransform.anchoredPosition = newBoxPos;
        Players.Add(tempPlayer);
        Debug.Log(Players.Count);
        lastMade = Players.Last();

which is ran before it is even possible to run the code in the original post

EDIT: this is not the entire code just the chunk of it that matters

well… one obvious answer is that there is no guarantee you find a player matching your criteria, as a result you exit the loop and its still null.

Yep, I suspect something wonky is going on with this line of code:

if (player.Name + " menu" == ((button.transform.parent).transform.parent).name)

I would debug this hideous part of the condition above, as what it’s returning could be different than what you expect:

((button.transform.parent).transform.parent).name)

It probably wouldn’t hurt to debug the player name portion as well (the part that appends “menu” to the end of the player’s name; is the player’s name what it should be?).

I don’t quite follow your debugging logic here. So you have checked and the list is empty. So that explains the issue you had presented in this thread. You think the list shouldn’t be empty, so that’s the next thing you should look for. Are you sure that method you’ve shown that is adding players to that list is actually executed? If the answer is yes, are you sure that this is the “same” Players list? Common errors are executing methods on prefabs instead of the proper instances in the scene. This happens when you setup references to the wrong objects.

You can use the second argument in the Debug.Log call and provide a “context” object that is linked with the log message. When you click on the log message in the console, Unity will highlight this context object. This can help figuring out on what objects which methods are actually executed. We can’t really help you since we don’t have your project. We don’t even know if all the code you’ve shown is in the same script, where that script might be attached to and if there’s additional code which may actually remove players or cliears the Players list at some point. Debugging is the most important skill a developer must master. When you encounter a bug it’s important to understand it in order to solve it. Or like Ryan Hipple would say:

.

2 Likes

That is just issues prone to happen all over and over again.

But first:
button.transform.parent.parent.name
gives you the same name.

But this makes the hierarchy rigid, any reparenting will break this code, same for renaming. Assign an Inspector reference or use GetComponent(s)InParent.

2 Likes

Firstly thank you all for the replies
Secondly, I am unable to add a reference because this is a dynamic object, it’s being added while the game is running this is why I have to use this, unless you have another way if you do I would love it hear it

I have already debugged that it returns what I want it to return

I have checked everything, it is the same list, it adds it, it doesn’t remove it anywhere and pretty much everything you can think of. For some reason the list goes empty once it goes into the AddLvl function have you ever encountered something like that? what was the problem?

Thank you for replying btw

OK,so this feels a bit more long shot but

 Players.Add(tempPlayer);

tempPlayer is not a local instance variable but a class wide by the looks of it, therefore you could ad 1000 players and they’d all be the same most likely… the last one…

Can you show the code? all of it? for that class, Im assuming confirmplayer is in the same class yes?

I can put the code here but its kind of long and messy so get ready lol

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Linq;

public class PlayerManager : MonoBehaviour
{
    [SerializeField] private Canvas canvas;
    private Player lastMade, tempPlayer;
    public GameObject playerMenu;
    public TextMeshProUGUI strText, dexText, consText, chaText, wisText, arcmText;
    public string characterName, tempName;
    public List<Player> Players = new List<Player> {};
    public int statsPerLevel = 3;
    TextMeshProUGUI playerStrText = null, playerDexText = null, playerConsText = null, playerChaText = null, playerWisText = null, playerArcmText = null, Level = null, StatPoints = null;

    public class Player
    {
        private int str, wis, cons, cha, arcm, dex, lvl, statpoints;
        private string name;
        public int Str { get { return str; } set { str = value; } }
        public int Wis { get { return wis; } set { wis = value; } }
        public int Cons { get { return cons; } set { cons = value; } }
        public int Cha { get { return cha; } set { cha = value; } }
        public int Arcm { get { return arcm; } set { arcm = value; } }
        public int Dex { get { return dex; } set { dex = value; } }
        public int Lvl { get { return lvl; } set { lvl = value; } }
        public int Statpoints { get { return statpoints; } set { statpoints = value; } }
        public string Name { get { return name; } set { name = value; } }


        public Player(string name, int str, int wis, int cons, int cha, int arcm, int dex, int lvl, int statpoints)
        {
            this.name = name;
            this.str = str;
            this.wis = wis;
            this.cons = cons;
            this.arcm = arcm;
            this.dex = dex;
            this.lvl = lvl;
            this.statpoints = statpoints;
        }


    }
    public void UpdateName(string name) { tempName = name; }

    public Player crateCharacter(string name)
    {
        bool are30 = false;
        int statsum = 0;
        int[] stats = new int[6];
        while (are30 == false)
        {
            for (int i = 0; i < stats.Length; i++)
            {
                stats[i] = Random.Range(1, 30);
            }
            for (int i = 0; i < stats.Length; i++)
            {
                statsum = statsum + stats[i];
            }
            if (statsum == 30)
            {
                are30 = true;
            }
            statsum = 0;
        }
        int str = stats[0], wis = stats[1], cons = stats[2], cha = stats[3], arcm = stats[4], dex = stats[5];
        Player player = new(name, str, wis, cons, cha, arcm, dex, 0, 0);
        player.Cha = stats[3];
        return player;
    }
    public void SetPlayer()
    {
        Player player = null;
        foreach (Player player1 in Players)
        {
            if (player1.Name == tempName)
            {
                Debug.Log("Name exists.");
                return;
            }
        }
        player = crateCharacter(tempName);
        Debug.Log(player.Name);
        tempPlayer = player;
        strText.text = player.Str.ToString();
        dexText.text = player.Dex.ToString();
        consText.text = player.Cons.ToString();
        chaText.text = player.Cha.ToString();
        wisText.text = player.Wis.ToString();
        arcmText.text = player.Arcm.ToString();
        Debug.Log("Temp player is: "+tempPlayer.Name);
        Debug.Log("List length in SetPlayer is: " + Players.Count);
    }

    public void ConfirmPlayer(GameObject readyPlayerBox)
    {
        Debug.Log("Temp player in ConfirmPlayer is: " + tempPlayer.Name);
        if (tempPlayer == lastMade)
        {
            return;
        }
        Vector3 scale = new Vector3(1f, 1f, 1f);
        RectTransform originalRectTransform = readyPlayerBox.GetComponent<RectTransform>();

        Vector2 newBoxPos = new Vector2(originalRectTransform.anchoredPosition.x + Players.Count * 130 + 130, originalRectTransform.anchoredPosition.y);
        GameObject playerBox = Instantiate(readyPlayerBox);
        RectTransform newRectTransform = playerBox.GetComponent<RectTransform>();
        TextMeshProUGUI playerText = playerBox.GetComponentInChildren<TextMeshProUGUI>();
        playerText.rectTransform.SetParent(playerBox.transform.GetChild(0).parent);
        playerBox.transform.SetParent(readyPlayerBox.transform.parent);

        playerBox.transform.name = tempPlayer.Name + " player button";
        newRectTransform.localScale = scale;
        playerText.enableWordWrapping = false;
        playerText.name = tempPlayer.Name + " Text";
        playerText.text = tempPlayer.Name;
        playerText.rectTransform.anchoredPosition = new Vector2(0 , 0);
        playerText.rectTransform.offsetMax = new Vector2(-5, -5);
        playerText.rectTransform.offsetMin = new Vector2(5, 5);
        newRectTransform.anchoredPosition = newBoxPos;
        Players.Add(tempPlayer);
        Debug.Log(Players.Count);
        lastMade = Players.Last();
        Debug.Log("List length in ConfirmPlayer after setting lastmade is: " + Players.Count);
        //Specific player menu making
        GameObject MakeSpecificMenu = Instantiate(playerMenu);
        RectTransform rt = MakeSpecificMenu.GetComponent<RectTransform>();
        MakeSpecificMenu.transform.SetParent(playerMenu.transform.parent);
        MakeSpecificMenu.name = tempPlayer.Name + " menu";
        rt.position = new Vector2(500, 50);
        rt.localScale = new Vector3(1, 1, 1);
        //List of stat texts
        TextMeshProUGUI[] stats = MakeSpecificMenu.GetComponentsInChildren<TextMeshProUGUI>();
        foreach (var stat in stats)
        {
            if (stat.name == "LevelNum")
            {
                stat.name = tempPlayer.Name + " LevelNum";
                stat.text = tempPlayer.Lvl.ToString();
            }
            else if (stat.name == "StatPointsNum")
            {
                stat.name = tempPlayer.Name + " StatPointsNum";
                stat.text = tempPlayer.Statpoints.ToString();
            }
            else if (stat.name == "StrenghNum")
            {
                stat.name = tempPlayer.Name + " StrenghNum";
                stat.text = tempPlayer.Str.ToString();
            }
            else if (stat.name == "DexterityNum")
            {
                stat.name = tempPlayer.Name + " DexterityNum";
                stat.text = tempPlayer.Dex.ToString();
            }
            else if (stat.name == "ConstitutionNum")
            {
                stat.name = tempPlayer.Name + " ConstitutionNum";
                stat.text = tempPlayer.Cons.ToString();
            }
            else if (stat.name == "CharismaNum")
            {
                stat.name = tempPlayer.Name + " CharismaNum";
                stat.text = tempPlayer.Cha.ToString();
            }
            else if (stat.name == "WisdomNum")
            {
                stat.name = tempPlayer.Name + " WisdomNum";
                stat.text = tempPlayer.Wis.ToString();
            }
            else if (stat.name == "ArcmanaNum")
            {
                stat.name = tempPlayer.Name + " ArcmanaNum";
                stat.text = tempPlayer.Arcm.ToString();
            }
        }
    }


    public void OpenSpecificMenu(GameObject button)
    {
        PlayerManager currentMenu = null;
        PlayerManager[] menus = canvas.GetComponentsInChildren<PlayerManager>();
        string playerName = button.GetComponentInChildren<TextMeshProUGUI>().text;
        Debug.Log("List length in OpenSpecificMenu is: " + Players.Count);

        foreach (var item in menus)
        {
            Debug.Log(item.name);
        }

        foreach (var item in menus)
        {
            Debug.Log(item.name);
            if (item.name == playerName)
            {
                currentMenu = item;
            }
        }
        Debug.Log("Current menu is: " + currentMenu);
        currentMenu.SetActive(true);


    }

    public void UpdateStats(Player currentPlayer)
    {
        playerStrText.text = currentPlayer.Str.ToString();
        playerDexText.text = currentPlayer.Dex.ToString();
        playerConsText.text = currentPlayer.Cons.ToString();
        playerChaText.text = currentPlayer.Cha.ToString();
        playerWisText.text = currentPlayer.Wis.ToString();
        playerArcmText.text = currentPlayer.Arcm.ToString();
        Level.text = currentPlayer.Lvl.ToString();
        StatPoints.text = currentPlayer.Statpoints.ToString();
    }
    //Start of buttons

    //Levels
    public void AddLvl(GameObject button)
    {
        Debug.Log(button.transform.parent.parent.name);
        Player currentPlayer = null;
        Debug.Log(Players.Count, button);
        for (int i = 0; i < Players.Count; i++)
        {
            Player player = Players[i];
            Debug.Log("Player name: " + player.Name);
            if (player.Name + " menu" == button.transform.parent.parent.name)
            {
                currentPlayer = player;
                Debug.Log("Set current player to: " + currentPlayer);
            }
        }
        Debug.Log("Current player is: " + currentPlayer);
        currentPlayer.Lvl += 1;
        currentPlayer.Statpoints += 3;
        UpdateStats(currentPlayer);
        Debug.Log("Level added");
        Debug.Log("player has " + currentPlayer.Statpoints);
    }
    public void RemoveLvl(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Lvl <= 0)
            return;
        currentPlayer.Lvl -= 1;
        currentPlayer.Statpoints -= 3;
        UpdateStats(currentPlayer);
        Debug.Log("Level removed");
    }
    //Strengh
    public void AddStr(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Statpoints <= 0) { return; }
        currentPlayer.Str += 1;
        currentPlayer.Statpoints -= 1;
        Debug.Log("Strengh added");
        UpdateStats(currentPlayer);
    }
    public void RemoveStr(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Str <= 0)
            return;
        currentPlayer.Str -= 1;
        currentPlayer.Statpoints += 1;
        Debug.Log("Strengh removed");
        UpdateStats(currentPlayer);
    }
    //Dexterity
    public void AddDex(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Statpoints <= 0) { return; }
        currentPlayer.Dex += 1;
        currentPlayer.Statpoints -= 1;
        Debug.Log("Dexterity added");
        UpdateStats(currentPlayer);
    }
    public void RemoveDex(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Dex <= 0)
            return;
        currentPlayer.Dex -= 1;
        currentPlayer.Statpoints += 1;
        Debug.Log("Dexterity removed");
        UpdateStats(currentPlayer);
    }
    //Constitution
    public void AddCons(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Statpoints <= 0) { return; }
        currentPlayer.Cons += 1;
        currentPlayer.Statpoints -= 1;
        Debug.Log("Constitution added");
        UpdateStats(currentPlayer);
    }
    public void RemoveCons(GameObject button)
    {
    Player currentPlayer = null;
    foreach (var player in Players)
    {
        if (player.Name == (button.transform.parent).name)
        {
            currentPlayer = player;
        }
    }
    if (currentPlayer.Cons <= 0)
            return;
        currentPlayer.Cons -= 1;
        currentPlayer.Statpoints += 1;
        Debug.Log("Constitution removed");
        UpdateStats(currentPlayer);
    }
    //Charisma
    public void AddCha(GameObject button)
    {
        Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
            currentPlayer = player;
            }
        }
        if (currentPlayer.Statpoints <= 0) { return; }
        currentPlayer.Cha += 1;
        currentPlayer.Statpoints -= 1;
        Debug.Log("Charisma added");
        UpdateStats(currentPlayer);
    }
    public void RemoveCha(GameObject button)
    {
    Player currentPlayer = null;
    foreach (var player in Players)
    {
        if (player.Name == (button.transform.parent).name)
        {
            currentPlayer = player;
        }
    }
    if (currentPlayer.Cha <= 0)
            return;
        currentPlayer.Cha -= 1;
        currentPlayer.Statpoints += 1;
        Debug.Log("Charisma removed");
        UpdateStats(currentPlayer);
    }
    //Wisdom
    public void AddWis(GameObject button)
    {
    Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Statpoints <= 0) { return; }
        currentPlayer.Wis += 1;
        currentPlayer.Statpoints -= 1;
        Debug.Log("Wisdom added");
        UpdateStats(currentPlayer);
    }
    public void RemoveWis(GameObject button)
    {
            Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Wis <= 0)
            return;
        currentPlayer.Wis -= 1;
        currentPlayer.Statpoints += 1;
        Debug.Log("Wisdom removed");
        UpdateStats(currentPlayer);
    }
    //Arcmana
    public void AddArcm(GameObject button)
    {
            Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Statpoints <= 0) { return; }
        currentPlayer.Arcm += 1;
        currentPlayer.Statpoints -= 1;
        Debug.Log("Arcmana added");
        UpdateStats(currentPlayer);
    }
    public void RemoveArcm(GameObject button)
    {
            Player currentPlayer = null;
        foreach (var player in Players)
        {
            if (player.Name == (button.transform.parent).name)
            {
                currentPlayer = player;
            }
        }
        if (currentPlayer.Arcm <= 0)
            return;
        currentPlayer.Arcm -= 1;
        currentPlayer.Statpoints += 1;
        Debug.Log("Arcmana removed");
        Debug.Log("Player has arcmana: " + currentPlayer.Arcm);
        UpdateStats(currentPlayer);
    }
    /// </End of button

    public void FixedUpdate()
    {
        //playerStrText.text = currentPlayer.Str.ToString();
        //playerDexText.text = currentPlayer.Dex.ToString();
        //playerConsText.text = currentPlayer.Cons.ToString();
        //playerChaText.text = currentPlayer.Cha.ToString();
        //playerWisText.text = currentPlayer.Wis.ToString();
        //playerArcmText.text = currentPlayer.Arcm.ToString();
        //Level.text = currentPlayer.Lvl.ToString();
        //StatPoints.text = currentPlayer.Statpoints.ToString();
    }
}

OK

so looking at your original code (and the scope of the full code - btw, im a strong believer in function first, pretty second)
so, it seems ConfirmPlayer must happen before you can call the others, this is not apparently the case in the debug shown… therefore players.count would be zero… as none of the debug messages from confirmplayer were in the log.

As others have mentioned it also could be 2 copies of this code. Its not like this is a singleton etc

That’s good to hear lol would have been bad if you were the other way around
And about the debug I have added the debug messages in the ConfirmPlayer after I posted this so they are not in the original pic I sent
and as far as the player list being empty it is physically impossible I will explain why in the following photo
9745471--1394524--upload_2024-4-2_18-2-40.png
Log after plus button being pressed:
9745471--1394527--upload_2024-4-2_18-3-27.png
and therefore it’s impossible to press the button while the list is empty

EDIT: The first menu is open by clicking the big Plus button near the player button

well if the list is empty you have a second copy of the class somewhere

Add a Start and debug GetInstanceID() and name

that way you can find out where the instances are

I have only two scripts on this project so far - PlayerManager and DragDrop. DragDrop takes care of exactly what it sound like, dragging objects. All of the other stuff is being taken care off in PlayerManager

What does GetInstanceID() do?

The instance id does change what does that mean?

it means you have multiple copies dear
you sure the script is not on things you’re spawning?