Beginner question about 'SetParent'; Why is it necessary to make the script work?

Hi!
—First of all there is no problems with the script and my game will run—

I’ve got some “past” experience in Unity and I’m quite familiar with the basics on coding in C#. Currently I’m learning to create an endless ball game (from a “beginner” book), where you control a ball which is rolling down a lane, where you need to avoid random generated obstacles.

I’ve understood almost everything in the provided code, except the last line of code in a method that is bugging me. The statement spawns an obstacle, but it also sets the obstacle as the parent to the ‘tile’ it’s spawned on. Why is this necessary, because without the component ‘SetParent’ the game won’t run. I understand what the ‘SetParent’ does, but anyone able to explain why the ‘SetParent’ is mandatory for my game to run and what does it do in this case?

The raw script below (from the book) covers spawning tiles and spawning obstacles, the line of code is located at the very bottom ( newObstacle.SetParent(spawnPoint.transform); ). Thanks a lot!

using UnityEngine;
using System.Collections.Generic; // List 

/// <summary> 
/// Controls the main gameplay 
/// </summary> 

public class GameController : MonoBehaviour
{
    [Tooltip("A reference to the tile we want to spawn")]
    public Transform tile;

    [Tooltip("A reference to the obstacle we want to spawn")]
    public Transform obstacle;

    [Tooltip("Where the first tile should be placed at")]
    public Vector3 startPoint = new Vector3(0, 0, -5);

    [Tooltip("How many tiles should we create in advance")]
    [Range(1, 15)]
    public int initSpawnNum = 10;

    [Tooltip("How many tiles to spawn initially with no obstacles")]
    public int initNoObstacles = 4;

    /// <summary> 
    /// Where the next tile should be spawned at. 
    /// </summary> 
    private Vector3 nextTileLocation;

    /// <summary> 
    /// How should the next tile be rotated? 
    /// </summary> 
    private Quaternion nextTileRotation;

    /// <summary> 
    /// Used for initialization 
    /// </summary> 
    void Start()
    {
        // Set our starting point 
        nextTileLocation = startPoint;
        nextTileRotation = Quaternion.identity;

        for (int i = 0; i < initSpawnNum; ++i)
        {
            SpawnNextTile(i >= initNoObstacles);
        }
    }

    /// <summary> 
    /// Will spawn a tile at a certain location and setup the next 
    position 
    /// </summary> 
    public void SpawnNextTile(bool spawnObstacles = true)
    {
        var newTile = Instantiate(tile, nextTileLocation, 
                                  nextTileRotation);

        // Figure out where and at what rotation we should spawn 
        // the next item 
        var nextTile = newTile.Find("Next Spawn Point");
        nextTileLocation = nextTile.position;
        nextTileRotation = nextTile.rotation;

        if (!spawnObstacles)
            return;

        // Now we need to get all of the possible places to spawn the 
        // obstacle 
        var obstacleSpawnPoints = new List<GameObject>();

        // Go through each of the child game objects in our tile 
        foreach (Transform child in newTile)
        {
            // If it has the ObstacleSpawn tag 
            if (child.CompareTag("ObstacleSpawn"))
            {
                // We add it as a possibilty 
                obstacleSpawnPoints.Add(child.gameObject);
            }
        }

        // Make sure there is at least one 
        if (obstacleSpawnPoints.Count > 0)
        {
            // Get a random object from the ones we have 
            var spawnPoint = obstacleSpawnPoints[Random.Range(0, 
                                          obstacleSpawnPoints.Count)];

            // Store its position for us to use 
            var spawnPos = spawnPoint.transform.position;

            // Create our obstacle 
            var newObstacle = Instantiate(obstacle, spawnPos, 
                                          Quaternion.identity);

            // Have it parented to the tile
            newObstacle.SetParent(spawnPoint.transform);
        }
    }
}

well we cant tell much with just one script because there are many possibilities and we don’t know how the Game is actually working(probably upload a video to let us know whats happening with and without setParent),
i am also confused what is spawnPoint here??
considering spawnpoint is active Gameobject in scene then,
according to me one of the main reason that can be is the obstacle is being parented to newObstacle and another script is trying to access the childs of spawnPoint to perform some task[for eg: GameObject.Destroy(spawnPoint.transform.getChild(0));]
Or,
as written by you the newObstacle is being parented to the Tile if thats true then look at the foreach statement near line 75

foreach (Transform child in newTile)
         {
             // If it has the ObstacleSpawn tag 
             if (child.CompareTag("ObstacleSpawn"))
             {
                 // We add it as a possibilty 
                 obstacleSpawnPoints.Add(child.gameObject);
             }
         }

this chunk of code is actually accessing the child of the Tile GameObject and is assigning those child to a list , so that makes clear that if we dont use setParent then this chunk of code wont work which may result in unexpected behaviour.

and also using too much of var is not really a not good programming Practice.
i hope this helps :slight_smile: