Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Detecting change in a list

Discussion in 'Scripting' started by TheNuttyGamer, Feb 10, 2019.

  1. TheNuttyGamer

    TheNuttyGamer

    Joined:
    Oct 15, 2017
    Posts:
    3
    Hello, this is something I've been struggling with for a while. In my game, a UI Element should be updating every time its corresponding list gets updated. I've tried getters and setters but they just straight up don't work.

    Code (CSharp):
    1. public List<CrewMember> Crew
    2.     {
    3.         get { return crew; }
    4.         set { crew = value; UpdateCrewUI();}
    5.     }
    I am directly interacting with the 'Crew' list and elements do get added/ removed successfuly however the method just does not get called. I've tried putting in print statements as well to test it and those don't get executed either.

    From my research it appears that getters and setters don't actually work with lists in which case I would need a workaround, I haven't been able to find any however, any advice is appreciated.
     
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Simplest solution is to encapsulate the actual list (make it private / protected). If you need it to be serialized for inspector - use [SerializeField] attribute on it. Alternatively, if you don't, mark it as readonly.
    Code (CSharp):
    1. [SerializeField] private List<CrewMember> _members = new List<CrewMember>();
    2. // Or
    3. private readonly List<CrewMember> _members = new List<CrewMember>();
    Then add a AddCrewMember() / RemoveCrewMember() methods to the class, alter list in there, call your method UpdateCrewUI in there as well.

    In C# it's best to not allow external objects to modify internal collections directly, unless you want that by design.
    (Avoid public modifiers on fields)
     
    Last edited: Feb 10, 2019
    Kiwasi and TheNuttyGamer like this.
  3. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,083
    meechan007 likes this.
  4. I have this piece of code I use, maybe it's useful, maybe it's not, it's up to you (under construction, so things will change as I go forward and optimize things, I more likely will make the list public to speed up the reads and those kind of things):
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace LurkingNinja.KujiKiri.Sets
    6. {
    7.     [Serializable]
    8.     public class AbstractSet<T> : ScriptableObject
    9.     {
    10.         public event Action<T> OnAddElement = delegate { };
    11.         public event Action<T> OnRemoveElement = delegate { };
    12.         public event Action<T> OnChangeElement = delegate { };
    13.         public event Action OnClear = delegate { };
    14.  
    15.         [SerializeField]
    16.         private List<T> Items = new List<T>();
    17.  
    18.         public int Count => Items.Count;
    19.  
    20.         public bool HasItems => Items.Count > 0;
    21.  
    22.         public bool Contains(T value) => Items.Contains(value);
    23.  
    24.         public T this[int index]
    25.         {
    26.             get => Items[index];
    27.             set
    28.             {
    29.                 Items[index] = value;
    30.                 OnChangeElement?.Invoke(value);
    31.             }
    32.         }
    33.  
    34.         public void Add(T item)
    35.         {
    36.             if(Items.Contains(item))
    37.                 return;
    38.             Items.Add(item);
    39.             OnAddElement?.Invoke(item);
    40.         }
    41.  
    42.         public void Remove(T item)
    43.         {
    44.             if(!Items.Contains(item))
    45.                 return;
    46.             Items.Remove(item);
    47.             OnRemoveElement?.Invoke(item);
    48.         }
    49.  
    50.         public void Clear()
    51.         {
    52.             if(!HasItems)
    53.                 return;
    54.             Items.Clear();
    55.             OnClear?.Invoke();
    56.         }
    57.  
    58.         public static bool IsNullOrEmpty(AbstractSet<T> set)
    59.         {
    60.             return set == null || !set.HasItems;
    61.         }
    62.     }
    63. }
    64.  
    It is part of a bigger framework I'm working on (to support future projects as well), this is, among other things, for support tag replacements. You can build any Sets (eg: GameObjectSet : AbstractSet<GameObject>) and then search (will be implemented and optimized later, depends on the use cases I'll have) or check if an element is in the Set or so on.
     
    Hozgen90, pry_bar and pepperopigeon like this.