This is my GameController
GameObject in the Inspector (Ignore Suns
and Player
). Note that the GameController
script has GameSpawner
as a SerializeField
.
And my script for GameController below.
public class GameController : MonoBehaviour
{
public GameObject sunParent;
public GameObject playerPrefab;
[SerializeField]
GameObject sunSpawnerObject;
SunSpawner sunSpawner;
void Start()
{
sunSpawner = sunSpawnerObject.GetComponent<SunSpawner>();
}
// this is only for testing
void LateUpdate()
{
SpawnSunAtY(sunParent, -3.5f);
SpawnSunAtY(sunParent, 0f);
SpawnSunAtY(sunParent, 3.5f);
}
void SpawnSunAtY(GameObject parent, float y)
{
sunSpawner.SpawnSunAtY(parent, y);
}
}
When the Scene starts, it should get the SunSpawner
script from sunSpawnerObject
. Then what is SunSpawner
? See below.
This GameObject(prefab) has SunSpawner
script as a component.
And below the script for SunSpawner
. (where my question begins)
public class SunSpawner : MonoBehaviour
{
const float SUN_MIN_SIZE_FACTOR = 0.05f;
const float SUN_MAX_SIZE_FACTOR = 0.3f;
[SerializeField]
GameObject sunPrefab;
float playerRawRadius;
float sunRawRadius;
void Start()
{
// these lines work just fine
GameObject player = GameObject.FindGameObjectWithTag("Player");
playerRawRadius = player.GetComponent<Renderer>().bounds.size.x / 2f;
sunRawRadius = sunPrefab.GetComponent<Renderer>().bounds.size.x / 2f;
}
public void SpawnSunAtY(GameObject parent, float y)
{
float sizeFactor = Random.Range(SUN_MIN_SIZE_FACTOR, SUN_MAX_SIZE_FACTOR);
Vector3 position = new Vector3(GetRandomXPos(sizeFactor), y, 0);
GameObject sun = Instantiate(sunPrefab, position, Quaternion.identity);
sun.transform.localScale *= sizeFactor;
sun.transform.parent = parent.transform;
}
float GetRandomXPos(float sizeFactor)
{
float offset = Camera.main.WorldToScreenPoint(new Vector3(GetHorizontalOffsetFromScreen(sizeFactor), 0, 0)).x;
float screenRightBoundWorldPoint = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, 0, 0)).x;
float screenLeftBoundWorldPoint = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 0)).x;
return Camera.main.ScreenToWorldPoint(new Vector2(Random.Range(offset, screenRightBoundWorldPoint - offset), 0)).x;
}
float GetHorizontalOffsetFromScreen(float sizeFactor)
{
float horizontalMargin = 0.1f; //TODO temporary value
float playerRadius = playerRawRadius; // *look here (1)*
float distancePlayerToSun = 0.5f; //TODO temporary value
float randomRadius = GetRandomRadius(sizeFactor);
return horizontalMargin + (2f * playerRadius) + distancePlayerToSun + randomRadius;
}
float GetRandomRadius(float sizeFactor)
{
// *look here (2)*
print("sunRawRadius: " + sunRawRadius + ", sizeFactor: " + sizeFactor + ", scaledRadius: " + (sunRawRadius * sizeFactor));
return sunRawRadius * sizeFactor;
}
}
Call stack:
GameController.LateUpdate()
-> SunSpawner.SpawnSunAtY(parent, y)
-> SunSpawner.GetRandomXPos(sizeFactor)
-> GetRandomXPos(sizeFactor)
-> GetHorizontalOffsetFromScreen(float sizeFactor)
-> GetRandomRadius(sizeFactor)
Look here (1):
in SunSpawner.Start()
, all values are initialized properly, I can see values in the debugger or log. However, when I get to GetHorizontalOffsetFromScreen(..)
, I see playerRawRadius
is now zero.
Look here (2):
Same thing. sunRawRadius
is 0, but sizeFactor
argument is properly passed down the call stack.
Question: Why is it doing this?
Follow up: How do I properly instantiate prefabs through game object chains and use them?
Big thank you in advance.
Start()
method called - the prefab will still have its default values. \$\endgroup\$Instantiate()
? \$\endgroup\$