Search Unity

Question Where am I going wrong here? (UI, List and menu)

Discussion in 'Scripting' started by ElMagnifico, Nov 25, 2020.

  1. ElMagnifico

    ElMagnifico

    Joined:
    Aug 27, 2018
    Posts:
    71
    I'm testing various things, mainly a system to generate characters and display them in a list

    I have 3 main scripts: Humanoid, attached to a 2D sprite/ 3D modal a prefab:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Humanoid : MonoBehaviour
    6. {
    7.  
    8.     public string firstname;
    9.     public string lastname;
    10.     public int strength = 10;
    11.     public int agility = 10;
    12.     public int endurance = 10;
    13.     public int willpower = 10;
    14.     public int intelligence = 10;
    15.     public int constitution = 10;
    16.     public int charisma = 10;
    17.     public int dexterity = 10;
    18.  
    19.     public int[] ptraits;
    20.     public int[] mtraits;
    21.  
    22.     public int raceId;
    23.     public string raceName;
    24.  
    25.  
    26.     public void UpdateStrength(int str)
    27.     {
    28.         strength = str;
    29.     }
    30.  
    31.  
    32. }
    Then I have a the GenerateHumanoid code, which generates monsters and is called trough a button (script itself is attached to an empty game object):
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class GenerateHumanoid : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     private GameObject template;
    9.     public Transform spawn;
    10.     public List<GameObject> girlList = new List<GameObject>();
    11.  
    12.     public string[] nameList = { "Ana", "Monica", "Catty", "Izzy", "Foxy"};
    13.     public string[] lastnameList = { "Starr", "Minx", "Kat", "Purr", "LaFox" };
    14.  
    15.     //race bonus variables
    16.     public int strBonus = 0;
    17.     public int agiBonus = 0;
    18.     public int dexBonus = 0;
    19.     public int intBonus = 0;
    20.     public int willBonus = 0;
    21.     public int chaBonus = 0;
    22.     public int endBonus = 0;
    23.  
    24.     public string raceName = "mixed";
    25.  
    26.  
    27.  
    28.     public void Generate(Transform position)
    29.     {
    30.         Vector3 spawnPoint = new Vector3(spawn.position.x, spawn.position.y, spawn.position.z);
    31.         GameObject girl = GameObject.Instantiate(template, spawnPoint, spawn.rotation);
    32.         int n = girlList.Count;
    33.         girl.name = "monstergil"+n; // generte name
    34.         girlList.Add(girl); //add girl to list
    35.  
    36.         //generate random race, for breeding this shoud depend on parents.
    37.         System.Random rnd = new System.Random();
    38.         int race = rnd.Next(0, 3);
    39.         girl.GetComponent<Humanoid>().raceId = race;
    40.  
    41.         girl.GetComponent<Humanoid>().firstname = NameGen();
    42.         girl.GetComponent<Humanoid>().lastname = LastnameGen();
    43.  
    44.         GetRaceBonuses(race); // fetch race bonuses
    45.         ApplyBonuses(girl, rnd);
    46.  
    47.     }
    48.  
    49.  
    50.  
    51.     public void GenerateOffspring(Transform position, GameObject parent1, GameObject parent2)
    52.     {
    53.         Vector3 spawnPoint = new Vector3(spawn.position.x, spawn.position.y, spawn.position.z);
    54.         GameObject girl = GameObject.Instantiate(template, spawnPoint, spawn.rotation);
    55.         int n = girlList.Count;
    56.         girl.name = "monstergil" + n; // generte name
    57.         girlList.Add(girl); //add girl to list
    58.         System.Random rnd = new System.Random();
    59.  
    60.         //generate race depending on parents.
    61.         if (parent1.GetComponent<Humanoid>().raceId == parent2.GetComponent<Humanoid>().raceId)
    62.         {
    63.             girl.GetComponent<Humanoid>().raceId = parent1.GetComponent<Humanoid>().raceId;
    64.         }
    65.         else
    66.         {
    67.             int racechance = rnd.Next(0, 100);
    68.             if (racechance <= 40)
    69.             {
    70.                 girl.GetComponent<Humanoid>().raceId = parent1.GetComponent<Humanoid>().raceId;
    71.             }
    72.             else if (racechance <= 80)
    73.                 {
    74.                 girl.GetComponent<Humanoid>().raceId = parent2.GetComponent<Humanoid>().raceId;
    75.             }
    76.             else
    77.             {
    78.                 girl.GetComponent<Humanoid>().raceId = 10;
    79.                 girl.GetComponent<Humanoid>().raceName = "mixed";
    80.             }
    81.         }
    82.  
    83.     }
    84.  
    85.  
    86.     //
    87.     public void ApplyBonuses(GameObject girl, System.Random rnd)
    88.     {
    89.         // set stats based on race, with randomized element
    90.         int random = rnd.Next(9, 11);
    91.         girl.GetComponent<Humanoid>().endurance = random + endBonus;
    92.  
    93.         int random2 = rnd.Next(9, 11);
    94.         girl.GetComponent<Humanoid>().strength = random + strBonus;
    95.  
    96.         int random3 = rnd.Next(9, 11);
    97.         girl.GetComponent<Humanoid>().agility = random + agiBonus;
    98.  
    99.         int random4 = rnd.Next(9, 11);
    100.         girl.GetComponent<Humanoid>().intelligence = random + intBonus;
    101.  
    102.         int random5 = rnd.Next(9, 11);
    103.         girl.GetComponent<Humanoid>().willpower = random + willBonus;
    104.  
    105.         int random6 = rnd.Next(9, 11);
    106.         girl.GetComponent<Humanoid>().charisma = random + chaBonus;
    107.  
    108.         int random7 = rnd.Next(9, 11);
    109.         girl.GetComponent<Humanoid>().dexterity = random + dexBonus;
    110.  
    111.         girl.GetComponent<Humanoid>().raceName = raceName;
    112.  
    113.  
    114.         //re-set bonus defaults
    115.         strBonus = 0;
    116.         agiBonus = 0;
    117.         dexBonus = 0;
    118.         intBonus = 0;
    119.         willBonus = 0;
    120.         chaBonus = 0;
    121.         endBonus = 0;
    122.  
    123.         raceName = "mixed";
    124.     }
    125.  
    126.  
    127.  
    128.     // race bonuses
    129.     public void GetRaceBonuses(int raceID)
    130.     {
    131.         switch (raceID)
    132.         {
    133.             case 0:   //human
    134.                 {
    135.                     strBonus += 1;
    136.                     agiBonus += 0;
    137.                     dexBonus += 0;
    138.                     intBonus += 2;
    139.                     willBonus += 1;
    140.                     chaBonus += 0;
    141.                     endBonus += 0;
    142.  
    143.                     raceName = "human";
    144.                     return;
    145.                 }
    146.  
    147.             case 1:   //catgirl
    148.                 {
    149.                     strBonus += 0;
    150.                     agiBonus += 2;
    151.                     dexBonus += 1;
    152.                     intBonus += -1;
    153.                     willBonus += 1;
    154.                     chaBonus += 1;
    155.                     endBonus += 0;
    156.  
    157.                     raceName = "catgirl";
    158.                     return;
    159.                 }
    160.  
    161.             case 2:   //elf
    162.                 {
    163.                     strBonus += 0;
    164.                     agiBonus += 1;
    165.                     dexBonus += 1;
    166.                     intBonus += 1;
    167.                     willBonus += 1;
    168.                     chaBonus += 1;
    169.                     endBonus += 0;
    170.  
    171.                     raceName = "elf";
    172.                     return;
    173.                 }
    174.  
    175.             default:
    176.                 strBonus += 1;
    177.                 agiBonus += 1;
    178.                 dexBonus += 1;
    179.                 intBonus += 1;
    180.                 willBonus += 1;
    181.                 chaBonus += 1;
    182.                 endBonus += 1;
    183.  
    184.                 raceName = "mix";
    185.                 return;
    186.         }
    187.     }
    188.  
    189.     //clear entire list
    190.     private void ClearGirls()
    191.     {
    192.         foreach (GameObject girl in girlList)
    193.         {
    194.             Destroy(girl);
    195.         }
    196.     }
    197.  
    198.  
    199.     //name gen
    200.     private string NameGen()
    201.     {
    202.         System.Random rnd = new System.Random();
    203.         int name = rnd.Next(0, 4);
    204.         string returname = nameList[name];
    205.  
    206.         return returname;
    207.     }
    208.  
    209.     private string LastnameGen()
    210.     {
    211.         System.Random rnd = new System.Random();
    212.         int name = rnd.Next(0, 4);
    213.         string returname = lastnameList[name];
    214.  
    215.         return returname;
    216.     }
    217. }
    218.  

    And lastly, the UI Panel script, attached to the button on the monster list panel:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine.UI;
    4. using UnityEngine;
    5. using System;
    6.  
    7.  
    8. public static class ButtonExtension
    9. {
    10.     public static void AddEventListener<T> (this Button button, T param, Action<T> OnClick)
    11.     {
    12.         button.onClick.AddListener(delegate ()
    13.         {
    14.             OnClick(param);
    15.         });
    16.     }
    17. }
    18.  
    19. public class UIPanel : MonoBehaviour
    20. {
    21.  
    22.     [Serializable]
    23.     public struct Monstergirl
    24.     {
    25.         public string name;
    26.         public string desc;
    27.         public Sprite icon;
    28.     }
    29.  
    30.     public Sprite[] icons;
    31.  
    32.     //[SerializeField] Monstergirl[] allGirls;
    33.  
    34.     public GenerateHumanoid gh;
    35.     public List<GameObject> tgl;
    36.  
    37.  
    38.    public void RefreshPanel()
    39.     {
    40.         tgl = gh.girlList;
    41.  
    42.         GameObject buttonTemplate = this.transform.GetChild(0).gameObject;
    43.         GameObject g;
    44.  
    45.         int n = tgl.Count;
    46.         for (int i = 0; i < n; i++)
    47.         {
    48.             g = Instantiate(buttonTemplate, transform);
    49.  
    50.             if (tgl[i].GetComponent<Humanoid>().raceId == 0)
    51.             {
    52.                 g.transform.GetChild(0).GetComponent<Image>().sprite = icons[0];
    53.             }
    54.             else
    55.             {
    56.                 g.transform.GetChild(0).GetComponent<Image>().sprite = icons[1];
    57.             }
    58.  
    59.             g.transform.GetChild(1).GetComponent<Text>().text = tgl[i].GetComponent<Humanoid>().firstname;
    60.             g.transform.GetChild(2).GetComponent<Text>().text = tgl[i].GetComponent<Humanoid>().lastname;
    61.  
    62.             g.GetComponent<Button>().AddEventListener(i, ItemClicked);
    63.         }
    64.  
    65.         Destroy(buttonTemplate);
    66.     }
    67.  
    68.     /*
    69.     void Start()
    70.     {
    71.         GameObject buttonTemplate = this.transform.GetChild(0).gameObject;
    72.         GameObject g;
    73.  
    74.         int N = allGirls.Length;
    75.         for (int i = 0; i < N; i++)
    76.         {
    77.             g = Instantiate(buttonTemplate, transform);
    78.             g.transform.GetChild(0).GetComponent<Image>().sprite = allGirls[i].icon;
    79.             g.transform.GetChild(1).GetComponent<Text>().text = allGirls[i].name;
    80.             g.transform.GetChild(2).GetComponent<Text>().text = allGirls[i].desc;
    81.  
    82.             g.GetComponent<Button>().AddEventListener(i, ItemClicked);
    83.         }
    84.  
    85.         Destroy(buttonTemplate);
    86.     }*/
    87.  
    88.  
    89.     void ItemClicked(int itemIndex)
    90.     {
    91.         Debug.Log("Item " + itemIndex + "clicked!");
    92.         //Debug.Log("Name: " + allGirls[itemIndex].name);
    93.         Debug.Log("Name: " + gh.girlList[itemIndex].name);
    94.     }
    95.  
    96. }
    97.  

    And it works - units are generated sucessfully, with attribute and names depending on race, added to the list.
    Every time I press the GENERATE bottun, the Generate and RefreshPanel are called.
    The thing is, I start getting duplicates in the list.

    In the image you can see I have 4 generated units, but the panel displays duplicates.
    It also return double return on clicking???



    Now I'm probably and idiot and doing things wrong (I'm sure there's a better way to get to the List from GenerateHomanoid)
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    I only see code that calls .Add() to the lists. Should the code perhaps instead use what is already in the list in certain circumstances?

    Also, to track stuff down like this, and since you're already clearly familiar with the console log, I recommend liberally sprinkling even more Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run?
    - what are the values of the variables involved? Are they initialized?

    Knowing this information will help you reason about the behavior you are seeing.
     
  3. ElMagnifico

    ElMagnifico

    Joined:
    Aug 27, 2018
    Posts:
    71
    I'm a moron. I'm calling Refersh Pannel every time I generate, but that means it calls THIS:
    1. int n = tgl.Count;
    2. for (int i = 0; i < n; i++)
    3. {
    4. g = Instantiate(buttonTemplate, transform);

    every time. This code was initally made to run on startup with a fixed list, but since I wanted a dynamic list, I missed that. OBVIOUSLY, I have to tell it to only generate bottuns for NEW monsters, not for the entire list.