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

Instantiated prefab has increasing number of children

Discussion in 'Prefabs' started by gdebojyoti, Jul 11, 2021.

  1. gdebojyoti

    gdebojyoti

    Joined:
    Mar 3, 2013
    Posts:
    28
    I have a ground prefab. That prefab has a script (that inherits from MonoBehaviour).
    The script has one variable (`groundPrefabVariable`) and it performs 2 functions inside `Start` method.
    The variable refers to the ground prefab itself.

    The 2 functions it does are as folllows:
    1. Create 2 sprites and add them as children to self.
    2. Instantiate a gameobject from the groundPrefabVariable, and place it as a sibling in the hierarchy.

    To get everything started, I have dragged and dropped the ground prefab into the scene once.


    The purpose of the above mechanism is to get a ground for an endless runner type game.


    The problem that I am running into is that the subsequent ground prefabs that get instantiated have an increasing number of child sprites (triggered by first function) - 2, 4, 6, 8 and so on...

    It's as if the 2nd function is instantiating the last instantiated ground game object, instead of instantiating the ground prefab.

    Can you please tell me why this is happening?


    P.S. This is the code that I am using to instantiate the ground prefab in the second function -
    Code (CSharp):
    1. Instantiate(
    2.     groundPrefab, // set to the actual ground prefab in Inspector
    3.     somePosition, // derived from transform.position
    4.     Quaternion.identity,
    5.     transform.parent // to make sibling in hierarchy
    6. )
     
  2. pietrodenicola

    pietrodenicola

    Unity Technologies

    Joined:
    Dec 8, 2020
    Posts:
    43
    As you say that the Start method is the one that creates sprites, I guess that it is called multiple times. And I assume that it is called each time the GameObject is instantiated. You have probably created a loop in there because the script is component of the GameObject being instantiated (and so it keeps on instantiating itself indefinitely). I'm not sure that this is the case as I don't see any code here. But if you still can't fix the problem, can you show some code please?
     
    Last edited: Jul 12, 2021
  3. gdebojyoti

    gdebojyoti

    Joined:
    Mar 3, 2013
    Posts:
    28
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class GroundController : MonoBehaviour {
    4.  
    5.   #region public members
    6.  
    7.     public float baseMovementSpeed = -2f;
    8.     public GameObject groundPrefab;
    9.     public GameObject zombiePrefab;
    10.     public float width = 10f; // width of ground block (i.e., self)
    11.  
    12.   #endregion
    13.  
    14.   #region private members
    15.  
    16.     private bool m_NextBlockInitialized = false;
    17.     private float m_cameraWidth; // width of camera, used to decide when to create & delete ground blocks
    18.     private string m_enemyName = "enemy";
    19.     private Vector2[] m_enemyPositions = new Vector2[]{
    20.       new Vector2(1,0),
    21.       new Vector2(3,1),
    22.       new Vector2(6,0),
    23.       new Vector2(8,-1),
    24.       new Vector2(9,1)
    25.     };
    26.  
    27.   #endregion
    28.  
    29.   #region MonoBehaviour methods
    30.  
    31.     private void Start () {
    32.       // calculate camera width (TODO: can be moved to GameService)
    33.       Camera m_camera = Camera.main;
    34.       m_cameraWidth = m_camera.aspect * 2f * m_camera.orthographicSize;
    35.  
    36.       _InitObstacles();
    37.     }
    38.  
    39.     private void FixedUpdate () {
    40.       _Move();
    41.       _IsGroundNeeded();
    42.       _DidLeaveViewport();
    43.     }
    44.  
    45.   #endregion
    46.  
    47.   #region private methods
    48.  
    49.     private void _Move() {
    50.       // speed to be applied in current frame
    51.       float speedPerFrame = baseMovementSpeed * GameService.GetWorldMovementMultiplier() * Time.fixedDeltaTime;
    52.  
    53.       // move self
    54.       transform.Translate(speedPerFrame, 0, 0);
    55.     }
    56.  
    57.     // check whether new ground block needs to be created
    58.     private void _IsGroundNeeded () {
    59.       if (m_NextBlockInitialized) {
    60.         return;
    61.       }
    62.       if ((transform.position.x + width) < m_cameraWidth) {
    63.         _CreateNextGround();
    64.       }
    65.     }
    66.  
    67.     // check whether current ground block has left camera viewport
    68.     private void _DidLeaveViewport () {
    69.       if ((transform.position.x + width) < -m_cameraWidth) {
    70.         Destroy(gameObject);
    71.       }
    72.     }
    73.  
    74.     // instantiate new ground block
    75.     private void _CreateNextGround () {
    76.       // instantiate new ground from self
    77.       GameObject newGround = Instantiate(
    78.         groundPrefab,
    79.         new Vector2(transform.position.x + width - .06f, transform.position.y),
    80.         Quaternion.identity,
    81.         transform.parent
    82.       );
    83.  
    84.       newGround.name = "Ground";
    85.  
    86.       // update flag
    87.       m_NextBlockInitialized = true;
    88.     }
    89.  
    90.     private void _InitObstacles () {
    91.       // generate obstacles only if block is outside camera view
    92.       if (transform.position.x < m_cameraWidth / 2) {
    93.         return;
    94.       }
    95.  
    96.       foreach(Vector2 position in m_enemyPositions) {
    97.         GameObject enemy = Instantiate(zombiePrefab, transform.position, Quaternion.identity, transform);
    98.         enemy.transform.localPosition = position;
    99.         enemy.name = m_enemyName;
    100.       }
    101.     }
    102.  
    103.   #endregion
    104. }
     
  4. gdebojyoti

    gdebojyoti

    Joined:
    Mar 3, 2013
    Posts:
    28
    @pietrodenicola In the above mentioned snippet,
    _CreateNextGround
    (line 75) is responsible for instantiating the "ground prefab".

    The above script is attached to the original ground prefab.

    _InitObstacles
    method (line 90) is used to instantiate some "enemies". For some reason, the number of enemies keeps increasing every time - that is my problem.
     
  5. pietrodenicola

    pietrodenicola

    Unity Technologies

    Joined:
    Dec 8, 2020
    Posts:
    43
    While the number of enemies is increasing, is the number of GameObjects "Ground" also increasing?
     
  6. gdebojyoti

    gdebojyoti

    Joined:
    Mar 3, 2013
    Posts:
    28
    The "enemy" game objects are children of "ground" gameobjects.
    Every time a new "ground" is created, the number of "enemies" (under new ground) =
    enemy count in previous ground + 2


    What is want instead is: number of "enemies" = 2.

    I don't understand why the enemy count from previous instance is persisting. I ensured that I am not instantiating "self" - I am instantiating the original prefab itself.
     
  7. gdebojyoti

    gdebojyoti

    Joined:
    Mar 3, 2013
    Posts:
    28
    Can someone please help me with this? :(
     
  8. I think your problem is inside the
    _isGroundNeeded()
    method. Particularly the
    Code (CSharp):
    1. if ((transform.position.x + width) < m_cameraWidth) {
    2.         _CreateNextGround();
    3. }
    part.

    I think what's happening is that the newly created grounds also run this method and since the camera not yet moved, they will also spawn their new grounds. You will need to find a way to not to spawn new ground only once until you moved away from this position. You can use a static variable or something like that.
     
  9. gdebojyoti

    gdebojyoti

    Joined:
    Mar 3, 2013
    Posts:
    28
    @Lurking-Ninja Thank you for your reply. I double-checked to be sure, but what you suggested is not the case.
    There are no extra grounds.
    There are only extra enemies. :-(