Search Unity

How to Make Delete Buttons Work For Records On A List Loaded From A Text File

Discussion in 'Scripting' started by bullettea, Jan 16, 2022.

  1. bullettea

    bullettea

    Joined:
    Oct 24, 2019
    Posts:
    29
    Novice here. My game has a HISTORY button that shows you data for all the sessions (aka streaks) you've played.

    Info is displayed 4 sessions per page. All info is loaded from a simple save text file (one session per line) that is parsed to and from the game when needed.

    The way this is done is by:
    * loading a list of 4 streaks called streakGroup, calculated by the page number
    * instantiating a historyUIElementPrefab for each streak in streakGroup. This prefab shows the data for each streak.

    Screenshot 2022-01-15 203431.jpg

    The problem is that I want each each streak on the page to have a Delete button, to allow the user to remove a record. I have added this delete button to the Prefab. As intended, it displays one per streak record.

    When pushed, it should delete that particular streak from the save file. But I can't figure out how to do this.

    So far I understand part of the solution is by loading the save file into a list, removing the record at that index, and saving the list back into the file.

    The issue is: h ow do I get the index of the streak that the button is attached to? I don't know how to tell any specific delete button to delete THAT particular record, or how to get the index number of the streak it is sitting next to.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5.  
    6. public static class HistoryHandler
    7. {
    8.  
    9.     static int recordsPerPage = 4;
    10.     static int numberOfTotalPages;
    11.  
    12.     static public List<Record> listOfSessions = new List<Record>();
    13.  
    14.     static public List<Record> LoadGroupOfStreaks(int pageNumber)
    15.     {
    16.         listOfSessions = SaveManager.Load();
    17.         listOfSessions.Reverse();
    18.         return listOfSessions.Skip((pageNumber - 1) * recordsPerPage).Take(recordsPerPage).ToList();
    19.  
    20.     }
    21.  
    22.     static public int GetNumberOfTotalPages()
    23.     {
    24.         if (listOfSessions.Count%recordsPerPage == 0)
    25.         {
    26.             numberOfTotalPages = listOfSessions.Count / recordsPerPage;
    27.         }
    28.         else
    29.         {
    30.             numberOfTotalPages = listOfSessions.Count / recordsPerPage + 1;
    31.         }
    32.  
    33.         return numberOfTotalPages;
    34.     }
    35.  
    36.     static public void RemoveRecordFromHistory(int recordIndex)
    37.     {
    38.         List<Record> allRecords = new List<Record>();
    39.         allRecords = SaveManager.Load();
    40.         allRecords.RemoveAt(recordIndex);
    41.         SaveManager.SaveAllRecords(allRecords);
    42.     }
    43.  
    44. }
    45.  
    46. using System.Collections;
    47. using System.Collections.Generic;
    48. using UnityEngine;
    49. using TMPro;
    50. using UnityEngine.UI;
    51.  
    52. public class HistoryWindow : MonoBehaviour
    53. {
    54.     [SerializeField] GameObject panel;
    55.     [SerializeField] GameObject historyUIElementPrefab;
    56.     [SerializeField] Transform elementWrapper;
    57.     [SerializeField] Button previousButton;
    58.     [SerializeField] Button nextButton;
    59.  
    60.     List<GameObject> uiElements = new List<GameObject>();
    61.  
    62.     List<Record> streakGroup;
    63.  
    64.     int pageNumber;
    65.     int pageTotal;
    66.  
    67.  
    68.     private void Start()
    69.     {
    70.         panel.SetActive(false);
    71.         pageNumber = 1;
    72.     }
    73.     public void ShowPanel()
    74.     {
    75.         this.gameObject.SetActive(true);
    76.         panel.SetActive(true);
    77.  
    78.         pageTotal = HistoryHandler.GetNumberOfTotalPages();
    79.  
    80.         if (pageNumber == 1)
    81.         {
    82.             previousButton.gameObject.SetActive(false);
    83.             nextButton.gameObject.SetActive(true);
    84.         }
    85.         else if (pageNumber == pageTotal)
    86.         {
    87.             previousButton.gameObject.SetActive(true);
    88.             nextButton.gameObject.SetActive(false);
    89.         }
    90.         else
    91.         {
    92.             previousButton.gameObject.SetActive(true);
    93.             nextButton.gameObject.SetActive(true);
    94.         }
    95.  
    96.         UpdateUI(pageNumber);
    97.     }
    98.  
    99.     public void ClosePanel()
    100.     {
    101.         panel.SetActive(false);
    102.         uiElements.Clear();
    103.         foreach (Transform child in elementWrapper)
    104.         { GameObject.Destroy(child.gameObject); }
    105.         pageNumber = 1;
    106.  
    107.     }
    108.  
    109.     public void NextPage()
    110.     {
    111.         pageNumber++;
    112.         ShowPanel();
    113.     }
    114.  
    115.     public void PreviousPage()
    116.     {
    117.         pageNumber--;
    118.         ShowPanel();
    119.     }
    120.  
    121.     private void ClearRecordsOnPage()
    122.     {
    123.         uiElements.Clear();
    124.         foreach (Transform child in elementWrapper)
    125.         { GameObject.Destroy(child.gameObject); }
    126.     }
    127.  
    128.     private void UpdateUI(int pageNumber)
    129.     {
    130.         ClearRecordsOnPage();
    131.         streakGroup = HistoryHandler.LoadGroupOfStreaks(pageNumber);
    132.  
    133.         int i = 0;
    134.  
    135.         foreach (var streak in streakGroup)
    136.         {
    137.             Debug.Log(i + " length record: " + streak.streakLength);
    138.  
    139.             var inst = Instantiate(historyUIElementPrefab, new Vector3(0, 0, 0), Quaternion.identity, elementWrapper);
    140.  
    141.             uiElements.Add(inst);
    142.  
    143.             var texts = uiElements[i].GetComponentsInChildren<TextMeshProUGUI>();
    144.  
    145.  
    146.             texts[0].text = "Started on " + streak.startTime.ToString(@"MMM/dd/yy h:mm tt");
    147.             texts[1].text = "Ended on " +  streak.endTime.ToString(@"MMM/dd/yy h:mm tt");
    148.             texts[2].text = DateTimeDisplay.ToReadableString(streak.streakLength);
    149.             texts[3].text = streak.comment.ToString();
    150.  
    151.             i++;
    152.  
    153.         }
    154.     }
    155.  
    156.     public void DeleteRecord()
    157.     {
    158.         /// how do I get the record index????
    159.         HistoryHandler.RemoveRecordFromHistory(recordIndex);
    160.     }
    161.  
    162. }
     
  2. bullettea

    bullettea

    Joined:
    Oct 24, 2019
    Posts:
    29
    Ok, in case anyone ever stumbles across the same issue, this is how I fixed it:

    1. Add a delete button to the session prefab
    2. Add a script to the prefab delete button

    Code (CSharp):
    1. public class DeleteButton : MonoBehaviour
    2. {
    3.     public int indexNumber;
    4.  
    5.     public void DeleteIndexNumber()
    6.     {
    7.         var scriptINeed = GameObject.FindObjectOfType(typeof(HistoryWindow)) as HistoryWindow;
    8.         scriptINeed.DeleteRecord(indexNumber);
    9.     }
    10. }
    In the script that manages the instantiation of the prefabs, add this method:

    Code (CSharp):
    1.     public void DeleteRecord(int recordIndex)
    2.     {
    3.         List<Record> allRecords = new List<Record>();
    4.         allRecords = SaveManager.Load();
    5.         allRecords.RemoveAt(recordIndex);
    6.         SaveManager.SaveAllRecords(allRecords);
    7.         ShowPanel();
    8.     }
    And under the instantiation loop in the same script, which for me is under UpdateUI, set the variable indexNumber to the number it would match in the save file method, by calculating backwards from the page number (third to last in this function)

    Code (CSharp):
    1.  private void UpdateUI(int pageNumber)
    2.     {
    3.         ClearRecordsOnPage();
    4.         streakGroup = HistoryHandler.LoadGroupOfStreaks(pageNumber);
    5.  
    6.         int i = 0;
    7.  
    8.         foreach (var streak in streakGroup)
    9.         {
    10.             Debug.Log(i + " length record: " + streak.streakLength);
    11.  
    12.             var inst = Instantiate(historyUIElementPrefab, new Vector3(0, 0, 0), Quaternion.identity, elementWrapper);
    13.  
    14.             uiElements.Add(inst);
    15.  
    16.             var texts = uiElements[i].GetComponentsInChildren<TextMeshProUGUI>();
    17.  
    18.  
    19.             texts[0].text = "Started on " + streak.startTime.ToString(@"MMM/dd/yy h:mm tt");
    20.             texts[1].text = "Ended on " +  streak.endTime.ToString(@"MMM/dd/yy h:mm tt");
    21.             texts[2].text = DateTimeDisplay.ToReadableString(streak.streakLength);
    22.             texts[3].text = streak.comment.ToString();
    23.  
    24.             uiElements[i].GetComponentInChildren<DeleteButton>().indexNumber = (pageNumber - 1) * HistoryHandler.recordsPerPage + i;
    25.  
    26.             Debug.Log("This is the button's index number " + uiElements[i].GetComponentInChildren<DeleteButton>().indexNumber);
    27.  
    28.             i++;
    29.  
    30.         }
    Not sure if this is the most efficient approach, but it seems to work.