Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Two Lists Synchronisation

Discussion in 'Scripting' started by Artpen, Jun 15, 2022.

  1. Artpen

    Artpen

    Joined:
    Jan 24, 2015
    Posts:
    291
    Hi guys,

    I have a list of Vector3s which I changed at run time. It is part of scriptable object so other scripts can get access.
    I have another script which has its own List of Vector3s these are just a copy of original list from Scriptable object.

    Question, What is the best way , pattern to use to keep both lists in sync?
    Currently, every time original List is changed, I:

    1.Clear the list
    2.Destroy all objects
    3.Copy a new list using for each
    4.Instantiate new objects

    It works, but I think it is not the best way.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,713
    Pattern, schmattern, code, schmode.

    Entirely depends on the data.

    Is it a list of 3 things or a list of 3,000,000,000,000 things?

    "If you don't understand the data, you don't understand the problem." - Mike Acton
     
    Bunny83 likes this.
  3. Artpen

    Artpen

    Joined:
    Jan 24, 2015
    Posts:
    291
    Currently it is about 1000 points. But will become much more.
    I think deleting them and making again is not a good way in any case. Well maybe if you only have 10 to 100.
    I think there should be a better way.
    Any pointers to information or advice would be helpful
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,524
    What kind of objects are they? Are they all the same? So are they created from the same prefab? Can you actually reuse them? Or does each instance has anything special? (Besides the Vector3 value which is probably used as a position for the object, right?).

    If the objects are the same and can be reused, all you have to do is make sure both lists have the same number of objects and adjust the position of each object.

    This is of course also not optimal but is relatively cheap. A better solution would be to perform the same action on both lists. This of course means you have to handle "a change" of the list in a controlled way. How complex things can get also depends on what kind of changes can be made to the list? can object be deleted arbitrarily? Can object be added? If so, can they added in between or just at the end? Does the order of the object has any meaning or is that irrelevant?

    So say listA is the master list with the Vector3 values and listB is the list that holds the Gameobject / Transforms (I would highly recommend to store Transforms if you're currently use a
    List<GameObject>
    ). You can sync them like this:
    Code (CSharp):
    1.  
    2. while (listA.Count > listB.Count)
    3.     listB.Add(Instantiate(yourPrefab).transform);
    4. while (listA.Count < listB.Count)
    5. {
    6.     Destroy(listB[listB.Count-1].gameObject);
    7.     listB.RemoveAt(listB.Count-1);
    8. }
    9. for(int i = 0; i < listA.Count; i++)
    10.     listB[i].position = listA[i];
    This would use the vector from listA as the worldspace position of listB. First it adds elements if necessary, then it deletes elements if there are too many, After the two while loops the two list have an equal amount of elements. Now we just iterate through them and apply the data from listA to the equivalent object in listB.
     
  5. Artpen

    Artpen

    Joined:
    Jan 24, 2015
    Posts:
    291
    Ok I have List <Polygon> polygons .
    Each Polygon has a List <points> basically Vector3s

    In a different script I am drawing lines using this information. To be able to draw lines (Vectrosity) I need a List <Vector3>

    So if I have 3 polygons I will draw line GameObjects using points from polygons points list.

    This is easy. The problem I have is when I change the number of polygons or points in original lists , how should I update sync points in Lines?

    For example I have a function to move points on the screen, I do not want to destroy and instantiate all lines and points every frame.
     
  6. Artpen

    Artpen

    Joined:
    Jan 24, 2015
    Posts:
    291
    This is one script where I changing Polygons and ask LineDrawer to update graphics:

    Code (CSharp):
    1. public class BoundaryManager : MonoBehaviour
    2. {
    3.     [SerializeField] private BoundaryRuntimeSetSO boundaries;
    4.     [SerializeField] private PolygonRuntimeSetSO polygons;
    5.  
    6.     // Components reference
    7.     private CreatePolygon createPolygon;
    8.     private EditPolygon editPolygon;
    9.     private LineDrawer lineDrawer;
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         ResetRuntimeSet();
    15.         createPolygon = GetComponent<CreatePolygon>();
    16.         editPolygon = GetComponent<EditPolygon>();
    17.         lineDrawer = GetComponent<LineDrawer>();
    18.     }
    19.  
    20.     // Create boundary
    21.     public void CreateBoundary()
    22.     {
    23.         // Only one boundary per project is allowed for alpha release
    24.         if(boundaries.Items.Count == 0)
    25.         {
    26.             //Debug.Log("Boundary was created");
    27.             //boundaries.Items.Add(new Site());
    28.             //createPolygon.AddPolygon();
    29.         }
    30.  
    31.         Debug.Log("Boundary was created");
    32.         boundaries.Items.Add(new Site());
    33.         createPolygon.AddPolygon();
    34.         lineDrawer.SetupVectorsity();
    35.     }
    36.  
    37.     // Select node by passing touch position
    38.     public void HandleTouchInput(Vector3 position)
    39.     {
    40.         editPolygon.SelectNode(position);
    41.     }
    42.  
    43.     // Select node by passing touch position
    44.     public void HandleTouchEndedInput()
    45.     {
    46.         editPolygon.DeselectNode();
    47.     }
    48.  
    49.     // Get input and create nodes and edges for the boundary polygon
    50.     public void HandleTapInput(Vector3 position)
    51.     {
    52.         createPolygon.CreatePolygonData(position);
    53.         lineDrawer.DrawGraphics();
    54.     }
    55.  
    56.     // Handle OnMoveIput. This has touch at start
    57.     public void HandleOnMoveInput(Vector3 position)
    58.     {
    59.         editPolygon.MoveNode(position);
    60.         //lineDrawer.UpdateGraphics();
    61.     }
    62.  
    63.     // Handle double tap to remove or add nodes
    64.     public void HandleOnDoubleTap(Vector3 position)
    65.     {
    66.         editPolygon.RemoveNode(position);
    67.         //editPolygon.AddNode(position);
    68.         //lineDrawer.DrawGraphics();
    69.     }
    70.  
    71.     // Clear runtime sets at start, to clear Scriptable Objects data
    72.     private void ResetRuntimeSet()
    73.     {
    74.         boundaries.Items.Clear();
    75.         polygons.Items.Clear();
    76.     }
    77. }
    And this one is actual LineDrawer where I am trying to use information from Polygons.

    Code (CSharp):
    1. public class LineDrawer : MonoBehaviour
    2. {
    3.     [SerializeField] private LineConfigurationSO lineConfig;
    4.     [SerializeField] private PolygonRuntimeSetSO polygons;
    5.  
    6.     private VectorLine vectorLine;
    7.     private VectorLine vectorPoint;
    8.  
    9.     private List<VectorLine> lines;
    10.     private List<VectorLine> points;
    11.  
    12.     private void Start()
    13.     {
    14.         lines = new List<VectorLine>();
    15.         points = new List<VectorLine>();
    16.     }
    17.  
    18.     // Setup Lines and points for Vectrosity.
    19.     public void SetupVectorsity()
    20.     {
    21.         if(lines.Count < polygons.Items.Count)
    22.         {
    23.             for (int i = 0; i < polygons.Items.Count - lines.Count; i++)
    24.             {
    25.                 CreateLines();
    26.                 CreatePoints();
    27.             }
    28.         }
    29.     }
    30.  
    31.     // Setup Vectro Lines
    32.     private void CreateLines()
    33.     {
    34.         // Setup Vector Line
    35.         vectorLine = new VectorLine(lineConfig.lineName, new List<Vector3>(), lineConfig.lineWidth, LineType.Continuous);
    36.         vectorLine.color = lineConfig.lineColor;
    37.         vectorLine.texture = lineConfig.lineTexture;
    38.         vectorLine.textureScale = 1.0f;
    39.         lines.Add(vectorLine);
    40.     }
    41.  
    42.     // Setup Vectro Points
    43.     private void CreatePoints()
    44.     {
    45.         // Setup Vector Point
    46.         vectorPoint = new VectorLine(lineConfig.lineName + " point", new List<Vector3>(), lineConfig.pointWidth, LineType.Points);
    47.         vectorPoint.color = lineConfig.pointColor;
    48.         vectorPoint.texture = lineConfig.pointTexture;
    49.         vectorPoint.textureScale = 1.0f;
    50.         points.Add(vectorPoint);
    51.     }
    52.  
    53.     // Draw graphics
    54.     public void DrawGraphics()
    55.     {
    56.         for (int i = 0; i < polygons.Items.Count; i++)
    57.         {
    58.             DrawLines(polygons.Items[i].Nodes, i);
    59.             DrawPoints(polygons.Items[i].Nodes, i);
    60.         }
    61.     }
    62.  
    63.     // Draw lines
    64.     private void DrawLines(List<Node> nodes, int polygonIndex)
    65.     {
    66.         lines[polygonIndex].points3.Add(nodes[nodes.Count-1].Position);
    67.         lines[polygonIndex].Draw3DAuto();
    68.  
    69.         if (!lineConfig.isLineOpen && lines[polygonIndex].points3.Count > 2)
    70.         {
    71.             //lines[polygonIndex].points3.Add(nodes[0].Position);
    72.         }
    73.     }
    74.  
    75.     // Draw points
    76.     private void DrawPoints(List<Node> nodes, int polygonIndex)
    77.     {
    78.         if (lineConfig.displayPoints)
    79.         {
    80.             points[polygonIndex].points3.Add(nodes[nodes.Count - 1].Position);
    81.             points[polygonIndex].Draw3DAuto();
    82.         }
    83.     }
    84. }
     
  7. Artpen

    Artpen

    Joined:
    Jan 24, 2015
    Posts:
    291
    Hi @Bunny83

    The answer your questions is yes :)
    “can object be deleted arbitrarily? Can object be added? If so, can they added in between or just at the end?”

    Thank you for the code.I am doing something similar. So I assume it is fine to destroy objects.
    But what good about your example I can see how I can change only position while dragging without constantly deleting all from the list B