Search Unity

Can't access prefab childs from ScriptableObject

Discussion in 'Prefabs' started by pBlackmouthA, Sep 12, 2019 at 1:39 AM.

  1. pBlackmouthA

    pBlackmouthA

    Joined:
    Sep 11, 2014
    Posts:
    1
    Hi, I'm following a video to create a Space Ship 2D Shooter Game and in this video shows how to use ScriptableObjects to configure Enemy Space Ship Waves.

    I have the next components to achieve this behavior:

    1. EnemyPathing SCRIPT (MonoBehaviour): Moves the enemy spaceship following the waypoints specified in a path. See script 1.
    2. WaveConfig SCRIPT (ScriptableObject): Specifies the wave configuration like Enemy Prefab, Path Prefab, number of enemies, speed move, etc. See script 2
    3. Enemy PREFAB: This is an Enemy spaceship that needs to follow a path of waypoints and have an EnemyPathing script component. See image 1
    4. PATH (0) PREFAB: This is an empty GameObject as a parent of waypoints childs. See image 2.


    Script 1
    Code (CSharp):
    1. using System.Collections;
    2.     using System.Collections.Generic;
    3.     using UnityEngine;
    4.  
    5.     public class EnemyPathing : MonoBehaviour
    6.     {
    7.         [SerializeField] WaveConfig waveConfig;
    8.         List<Transform> waypoints;
    9.         [SerializeField] float moveSpeed = 2f;
    10.         int waypointIndex = 0;
    11.  
    12.         // Start is called before the first frame update
    13.         void Start()
    14.         {
    15.             waypoints = waveConfig.GetWaypoints();
    16.             transform.position = waypoints[waypointIndex].position;
    17.         }
    18.  
    19.         // Update is called once per frame
    20.         void Update()
    21.         {
    22.             if(waypointIndex <= waypoints.Count - 1)
    23.             {
    24.                 var targetPosition = waypoints[waypointIndex].transform.position;
    25.                 var movementThisFrame = moveSpeed * Time.deltaTime;
    26.  
    27.                 transform.position = Vector2.MoveTowards(transform.position, targetPosition, movementThisFrame);
    28.  
    29.                 if(transform.position == targetPosition)
    30.                 {
    31.                     waypointIndex++;
    32.                 }
    33.             }
    34.             else
    35.             {
    36.                 Destroy(gameObject);
    37.             }
    38.         }
    39.     }


    Script 2


    Code (CSharp):
    1. using System.Collections;
    2.     using System.Collections.Generic;
    3.     using UnityEngine;
    4.  
    5.     [CreateAssetMenu(menuName = "Enemy Wave Config")]
    6.     public class WaveConfig : ScriptableObject
    7.     {
    8.         [SerializeField] GameObject enemyPrefab;
    9.         [SerializeField] GameObject pathPrefab;
    10.         [SerializeField] float timeBetweenSpawns = 0.5f;
    11.         [SerializeField] float spawnRandomFactor = 0.3f;
    12.         [SerializeField] int numberOfEnemies = 5;
    13.         [SerializeField] float moveSpeed = 2f;
    14.  
    15.         public GameObject GetEnemyPrefab() { return enemyPrefab; }
    16.  
    17.         public List<Transform> GetWaypoints() {
    18.  
    19.             var waveWaypoints = new List<Transform>();
    20.             foreach (Transform child in enemyPrefab.transform)
    21.             {
    22.                 waveWaypoints.Add(child);
    23.             }
    24.             return waveWaypoints;
    25.         }
    26.  
    27.         public float GetTimeBetweenSpawns() { return timeBetweenSpawns; }
    28.  
    29.         public float GetSpawnRandomFactor() { return spawnRandomFactor; }
    30.  
    31.         public int GetnNmberOfEnemies() { return numberOfEnemies; }
    32.  
    33.         public float GetMoveSpeed() { return moveSpeed; }
    34.     }


    Image 1:


    Image 2:


    I have created an instance of the ScriptableObject (WaveConfig) to have the configuration of wave 1 and assigned the Path (0) Prefab for the enemy to follow those waypoints.



    As you see I'm setting the **Path (0) Prefab** into Wave 1 pathPrefab property in the inspector

    The problem is when I try to get the waypoints by code from WaveConfig script in method GetWaypoints() from Path (0) Prefab dynamically. According to [the Unity API ][4], You can iterate on the children of a transform and get their transform through the FOREACH statement, but in my case, this is not happening, Unity does not enter in the FOREACH statement.

    Knowing this, in the video the instructor gets all the prefab children in Star() method in EnemyPathing script calling the **GetWayPoints()** method in WaveConfig instance script and its spaceship is following the path.

    I notice that the instructor is using an older version of Unity (2018.2.3f1) and its Path (0) Prefab shows its children as part of it in the folder (See Image 3 below) but I using Unity 2019.2.0f1 and the new prefab workflow don't show its children into the folder. (See Image 4 below).

    I testing the Unity API functionality to validate if the loop is working, adding a new Script to Path (0) Prefab instance in the hierarchy and this works.


    Code (CSharp):
    1. using System.Collections;
    2.     using System.Collections.Generic;
    3.     using UnityEngine;
    4.  
    5.     public class LoopingChilds : MonoBehaviour
    6.     {
    7.         // Start is called before the first frame update
    8.         void Start()
    9.         {
    10.             foreach(Transform child in transform)
    11.             {
    12.                 Debug.Log(child.name);
    13.             }
    14.         }  
    15.     }
    I think the problem is because the ScriptableObject (Wave 1) have a reference to the Path (0) Prefab itself and not to a Prefab Instance, also I tried to get the transform of the children with GetComponentInChildren <Transform> by changing the GetWayPoints () method in WaveConfig with this code:


    Code (CSharp):
    1. public List<Transform> GetWaypoints() {
    2.      
    3.                 var waveWaypoints = new List<Transform>();
    4.                 Transform[] allChildren = enemyPrefab.GetComponentsInChildren<Transform>(true);
    5.                 foreach (Transform child in allChildren)
    6.                 {
    7.                     waveWaypoints.Add(child);
    8.                 }
    9.                 return waveWaypoints;
    10.             }


    Image 3:


    Image 4:


    Any suggestions to be able to dynamically get the children of the Path (0) Prefab transform from the ScriptableObject (WaveConfig) using the new Unity Prefabs workflow?