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

How should I handle a array of GameObjects that might or might not be prefabs?

Discussion in 'Scripting' started by Dko, Apr 18, 2021.

  1. Dko

    Dko

    Joined:
    May 17, 2014
    Posts:
    2
    Hope someone can help. I'm mostly new to scripting in Unity (not C# though)

    My end goal is take a list of GameObjects that I have added to a serialized array field and have them added as children of the GameObject that the script is attached to. I want it to be smart enough to handle Prefabs and regular GameObjects.

    Right now regular GameObjects do work, but Prefabs don't. Which clearly is because I need to create a instance of the Prefab.

    What I don't know is, can I either detect if a GameObject is a Prefab (Googling seems contradictory on if this is possible.) and create a instance, or attempt to make a instance from a GameObject regardless if it is a Prefab or not?

    Or is there something else I should do?
     
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,916
    https://docs.unity3d.com/ScriptReference/GameObject-scene.html

    You can check if a game object is part of any scenes. If it is, it's a game object instance, if it isn't, it's a "prefab" (it's just a game object without instance, there are no prefabs in runtime).
     
  3. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    It seems like bad seperation to mix gameobjects with prefabs.
     
    Owen-Reynolds likes this.
  4. Dko

    Dko

    Joined:
    May 17, 2014
    Posts:
    2
    Well I was mixing because my serialized object is of the Game Object type. I wanted to be able to handle both since I can assign either. If I could just limit what was assigned to just prefabs I would. But I don't know how.
     
  5. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,923
    Think of it this way: suppose you have a pair of Z42's in the scene and the player selects Z-42 and J14/a for their robot. How do you know which Z42 to grab? Or how can they tell the game "even though I have some Z42's I want a new one spawned, just like the J14/a has to be"? What is the point of having parts laying around, waiting to say "no need to spawn one -- use me"?

    It makes more sense to have one action to grab an existing part from some other robot, and a different action to create a set of new parts.
     
  6. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Or in a pool. use my pool as an example.

    Code (CSharp):
    1.    public abstract class PollingPool<T> where T : Component
    2.     {
    3.         private readonly T prefab;
    4.  
    5.         private readonly Queue<T> pool = new Queue<T>();
    6.         private readonly LinkedList<T> inuse = new LinkedList<T>();
    7.         private readonly Queue<LinkedListNode<T>> nodePool = new Queue<LinkedListNode<T>>();
    8.  
    9.         private int lastCheckFrame = -1;
    10.  
    11.         protected PollingPool(T prefab)
    12.         {
    13.             this.prefab = prefab;
    14.         }
    15.  
    16.         private void CheckInUse()
    17.         {
    18.             var node = inuse.First;
    19.             while (node != null)
    20.             {
    21.                 var current = node;
    22.                 node = node.Next;
    23.  
    24.                 if (!IsActive(current.Value))
    25.                 {
    26.                     current.Value.gameObject.SetActive(false);
    27.                     pool.Enqueue(current.Value);
    28.                     inuse.Remove(current);
    29.                     nodePool.Enqueue(current);
    30.                 }
    31.             }
    32.         }
    33.  
    34.         protected T Get()
    35.         {
    36.             T item;
    37.  
    38.             if (lastCheckFrame != Time.frameCount)
    39.             {
    40.                 lastCheckFrame = Time.frameCount;
    41.                 CheckInUse();
    42.             }
    43.  
    44.             if (pool.Count == 0)
    45.                 item = GameObject.Instantiate(prefab);
    46.             else
    47.                 item = pool.Dequeue();
    48.  
    49.             if (nodePool.Count == 0)
    50.                 inuse.AddLast(item);
    51.             else
    52.             {
    53.                 var node = nodePool.Dequeue();
    54.                 node.Value = item;
    55.                 inuse.AddLast(node);
    56.             }
    57.          
    58.             item.gameObject.SetActive(true);
    59.  
    60.             return item;
    61.         }
    62.  
    63.         protected abstract bool IsActive(T component);
    64.     }
    It takes the prefab as argument to constructor. But internally it handels a collection of instances of that prefab