How can I respawn pickups in an array and through a coroutine?
I'm having difficulty getting my gold pickups to respawn after they've been destroyed on death. The idea is, if the player fails to pick up the 5 gold bars, activates a checkpoint, and dies, the current gold is destroyed and it resets once the screen has faded from black.
I currently have a Coroutine in my Health Manager that runs correctly if the player dies and resets them. I have a Gold Pickup script that destroys the gold if they haven't been picked up. I just can't seem to get them to re-instantiate. I've tried adding the instantiate code within the Health Manager's coroutine and within the Gold Pickup script. Nothing seems to work. If I'm not getting errors saying 'Array index is out of range' it's 'object reference not set to an instance of an object' etc.
public class GoldPickup : MonoBehaviour{
public int value;
public GameObject pickupEffect;
public GameObject goldBarArray;
public HealthManager healthManager;
public Checkpoint checkpoint;
private Vector3 goldRespawnPoint;
private Quaternion goldStartPosition;
void Start()
{
//To destroy multiple objects at once, use FindGameObjectsWithTag.
//GetComponent is considered more efficient than FindObjectOfType, but the latter avoids any errors saying an object reference hasn't been set.
goldBarArray = GameObject.FindGameObjectsWithTag("Gold");
healthManager = FindObjectOfType<HealthManager>();
//FindObjectOfType<Checkpoint>();
checkpoint = FindObjectOfType<Checkpoint>();
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
}
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
FindObjectOfType<GameManager>().AddGold(value);
Instantiate(pickupEffect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
public void DestroyGold()
{
//For Statics, an object reference isn't necessary. Use the FindObjectOfType to find the appropriate script and reference the Type, such as HealthManager.
if (checkpoint.checkpoint1On == false)
{
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
}
}
/*public void GoldReset()
{
if (healthManager.isRespawning == true)
{
if (checkpoint.checkpoint1On == false)
{
StartCoroutine("GoldRespawnCo");
}
}
else if (_respawnCoroutine != null)
{
StopCoroutine(_respawnCoroutine);
_respawnCoroutine = StartCoroutine("GoldRespawnCo");
}*/
/*public IEnumerator GoldRespawnCo()
{
if (checkpoint.checkpoint1On == false)
{
Instantiate(goldPrefab, goldRespawnPoint, goldStartPosition);
transform.position = goldRespawnPoint;
transform.rotation = goldStartPosition;
}
else
{
yield return null;
}
}*/
/*if (thePlayer.gameObject.activeInHierarchy == false)
{
Destroy(gameObject);
Instantiate(goldBar, transform.position, transform.rotation);
}
else
{
if (thePlayer.gameObject.activeInHierarchy == true)
{
transform.position = respawnPoint;
transform.rotation = startPosition;
}
}*/
}
public class HealthManager : MonoBehaviour
//The counters will count down and will keep counting down based on the length variables
public int maxHealth;
public int currentHealth;
public PlayerController thePlayer;
//public GoldPickup goldPickup;
//public GoldPickup goldPickup;
public float invincibilityLength;
public Renderer playerRenderer;
public float flashLength;
public float respawnLength;
public GameObject deathEffect;
public Image blackScreen;
public float fadeSpeed;
public float waitForFade;
public bool isRespawning;
//public GameObject goldBar;
//To reference another script's function, such as in the DeathTrigger script, make a public DeathTrigger, give it a reference name, and put it into the Start function. Use the reference name and assign it using GetComponent. Call another script's method by using the reference name, followed by a dot and the name of the method. Eg: deathTrigger.DestroyGold().
private Quaternion startPosition;
//private Quaternion goldPosition;
private float flashCounter;
private float invincibilityCounter;
private Vector3 respawnPoint;
//private Vector3 goldRespawnPoint;
private bool isFadetoBlack;
private bool isFadefromBlack;
//private Coroutine _respawnCoroutine;
//private Vector3 goldRespawnPoint;
//private Quaternion goldStartPosition;
void Start()
{
currentHealth = maxHealth;
respawnPoint = thePlayer.transform.position;
startPosition = thePlayer.transform.rotation;
//goldPickup = GetComponent<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
//goldRespawnPoint = transform.position;
//goldStartPosition = transform.rotation;
//goldPickup = FindObjectOfType<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldPosition = goldBar.transform.rotation;
}
void Update()
{
//These functions are checked every frame until the player takes damage
if (invincibilityCounter > 0)
{
invincibilityCounter -= Time.deltaTime;
flashCounter -= Time.deltaTime;
if (flashCounter <= 0)
//The Flash Counter is currently set at 0.1 and will be within the 0 region as it counts down. During this period, the playerRenderer will alternate between on and off
{
playerRenderer.enabled = !playerRenderer.enabled;
//The Flash Counter will keep counting down and reloop depending on the Flash Length time
flashCounter = flashLength;
}
//This makes sure after the flashing and invincibility has worn off that the player renderer is always turned back on so you can see the player
if (invincibilityCounter <= 0)
{
playerRenderer.enabled = true;
}
}
if (isFadetoBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 1f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 1f)
{
isFadetoBlack = false;
}
}
if (isFadefromBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 0f)
{
isFadefromBlack = false;
}
}
}
public void HurtPlayer(int damage, Vector3 direction)
{
//If the invincibility countdown reaches zero it stops, making you no longer invincible and prone to taking damage again
if (invincibilityCounter <= 0)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Respawn();
}
else
{
thePlayer.Knockback(direction);
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
}
public void Respawn()
{
//A StartCoroutine must be set up before the IEnumerator can begin
if (!isRespawning)
{
StartCoroutine("RespawnCo");
}
}
//IEnumerators or Coroutines will execute the code separately at specified times while the rest of the code in a codeblock will carry on executing as normal.
//To prevent an error appearing below the name of the Coroutine, be sure to place a yield return somewhere within the code block. Either yield return null or a new WaitForSeconds.
public IEnumerator RespawnCo()
{
if (GameManager.currentGold < 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
//To reference another script's function quickly and just the once, use the FindObjectOfType function. This is considered to be slow however.
FindObjectOfType<GoldPickup>().DestroyGold();
//GetComponent<GoldPickup>().DestroyGold();
//Instantiate(goldBar, goldRespawnPoint, Quaternion.identity);
isFadefromBlack = true;
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
GameManager.currentGold = 0;
GetComponent<GameManager>().SetCountText();
StopCoroutine("RespawnCo");
/*isRespawning = true;
thePlayer.gameObject.SetActive(false);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
SceneManager.LoadScene("Level 1");
GameManager.currentGold = 0;*/
}
else if(GameManager.currentGold >= 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
/*public void HealPlayer(int healAmount)
{
currentHealth += healAmount;
if(currentHealth > maxHealth)
{
currentHealth = maxHealth;
}
}*/
public void SetSpawnPoint(Vector3 newPosition)
{
respawnPoint = newPosition;
}
public class Checkpoint : MonoBehaviour
public HealthManager theHealthManager;
public Renderer cpRenderer;
public Renderer postRenderer;
public SpriteRenderer pcRenderer;
public Material cpOff;
public Material cpOn;
public Material postOff;
public Material postOn;
public GameObject infoPanels;
public bool checkpoint1On;
//Make sure to assign a value to a bool with '=' and in an 'if' statement somewhere in the code to prevent warnings.
//private bool checkpoint1IsActivated;
private bool infoPanel1Activated;
void Start()
{
theHealthManager = FindObjectOfType<HealthManager>();
}
void Update()
//Key presses are better handled in the Update function and will recognise keys being pressed once every frame.
{
if (checkpoint1On == true)
{
if (infoPanel1Activated == false)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(true);
infoPanel1Activated = true;
}
}
else
{
if (infoPanel1Activated == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(false);
infoPanel1Activated = false;
}
}
}
}
}
public void Checkpoint1On()
{
cpRenderer.material = cpOn;
postRenderer.material = postOn;
pcRenderer.color = new Color(1f, 1f, 1f, 1f);
checkpoint1On = true;
}
// makes a variable an Array (a list). The 'foreach' loop will check through all the Checkpoint objects
//Checkpoint checkpoints = FindObjectsOfType<Checkpoint>();
//For each Checkpoint Array called 'checkpoints', look for 'cp' and turn the others in the list off
/*foreach (Checkpoint cp in checkpoints)
{
cp.CheckpointOff();
}
theRenderer.material = cpOn;*/
public void Checkpoint1Off()
{
cpRenderer.material = cpOff;
postRenderer.material = postOff;
pcRenderer.color = new Color(1f, 1f, 1f, 5f);
checkpoint1On = false;
}
public void OnTriggerStay(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if (GameManager.currentGold >= 5)
{
if (Input.GetKeyDown(KeyCode.Return))
{
theHealthManager.SetSpawnPoint(transform.position);
Checkpoint1On();
checkpoint1On = true;
}
}
else if (GameManager.currentGold <= 5)
{
checkpoint1On = false;
}
}
}
c# unity3d
add a comment |
I'm having difficulty getting my gold pickups to respawn after they've been destroyed on death. The idea is, if the player fails to pick up the 5 gold bars, activates a checkpoint, and dies, the current gold is destroyed and it resets once the screen has faded from black.
I currently have a Coroutine in my Health Manager that runs correctly if the player dies and resets them. I have a Gold Pickup script that destroys the gold if they haven't been picked up. I just can't seem to get them to re-instantiate. I've tried adding the instantiate code within the Health Manager's coroutine and within the Gold Pickup script. Nothing seems to work. If I'm not getting errors saying 'Array index is out of range' it's 'object reference not set to an instance of an object' etc.
public class GoldPickup : MonoBehaviour{
public int value;
public GameObject pickupEffect;
public GameObject goldBarArray;
public HealthManager healthManager;
public Checkpoint checkpoint;
private Vector3 goldRespawnPoint;
private Quaternion goldStartPosition;
void Start()
{
//To destroy multiple objects at once, use FindGameObjectsWithTag.
//GetComponent is considered more efficient than FindObjectOfType, but the latter avoids any errors saying an object reference hasn't been set.
goldBarArray = GameObject.FindGameObjectsWithTag("Gold");
healthManager = FindObjectOfType<HealthManager>();
//FindObjectOfType<Checkpoint>();
checkpoint = FindObjectOfType<Checkpoint>();
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
}
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
FindObjectOfType<GameManager>().AddGold(value);
Instantiate(pickupEffect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
public void DestroyGold()
{
//For Statics, an object reference isn't necessary. Use the FindObjectOfType to find the appropriate script and reference the Type, such as HealthManager.
if (checkpoint.checkpoint1On == false)
{
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
}
}
/*public void GoldReset()
{
if (healthManager.isRespawning == true)
{
if (checkpoint.checkpoint1On == false)
{
StartCoroutine("GoldRespawnCo");
}
}
else if (_respawnCoroutine != null)
{
StopCoroutine(_respawnCoroutine);
_respawnCoroutine = StartCoroutine("GoldRespawnCo");
}*/
/*public IEnumerator GoldRespawnCo()
{
if (checkpoint.checkpoint1On == false)
{
Instantiate(goldPrefab, goldRespawnPoint, goldStartPosition);
transform.position = goldRespawnPoint;
transform.rotation = goldStartPosition;
}
else
{
yield return null;
}
}*/
/*if (thePlayer.gameObject.activeInHierarchy == false)
{
Destroy(gameObject);
Instantiate(goldBar, transform.position, transform.rotation);
}
else
{
if (thePlayer.gameObject.activeInHierarchy == true)
{
transform.position = respawnPoint;
transform.rotation = startPosition;
}
}*/
}
public class HealthManager : MonoBehaviour
//The counters will count down and will keep counting down based on the length variables
public int maxHealth;
public int currentHealth;
public PlayerController thePlayer;
//public GoldPickup goldPickup;
//public GoldPickup goldPickup;
public float invincibilityLength;
public Renderer playerRenderer;
public float flashLength;
public float respawnLength;
public GameObject deathEffect;
public Image blackScreen;
public float fadeSpeed;
public float waitForFade;
public bool isRespawning;
//public GameObject goldBar;
//To reference another script's function, such as in the DeathTrigger script, make a public DeathTrigger, give it a reference name, and put it into the Start function. Use the reference name and assign it using GetComponent. Call another script's method by using the reference name, followed by a dot and the name of the method. Eg: deathTrigger.DestroyGold().
private Quaternion startPosition;
//private Quaternion goldPosition;
private float flashCounter;
private float invincibilityCounter;
private Vector3 respawnPoint;
//private Vector3 goldRespawnPoint;
private bool isFadetoBlack;
private bool isFadefromBlack;
//private Coroutine _respawnCoroutine;
//private Vector3 goldRespawnPoint;
//private Quaternion goldStartPosition;
void Start()
{
currentHealth = maxHealth;
respawnPoint = thePlayer.transform.position;
startPosition = thePlayer.transform.rotation;
//goldPickup = GetComponent<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
//goldRespawnPoint = transform.position;
//goldStartPosition = transform.rotation;
//goldPickup = FindObjectOfType<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldPosition = goldBar.transform.rotation;
}
void Update()
{
//These functions are checked every frame until the player takes damage
if (invincibilityCounter > 0)
{
invincibilityCounter -= Time.deltaTime;
flashCounter -= Time.deltaTime;
if (flashCounter <= 0)
//The Flash Counter is currently set at 0.1 and will be within the 0 region as it counts down. During this period, the playerRenderer will alternate between on and off
{
playerRenderer.enabled = !playerRenderer.enabled;
//The Flash Counter will keep counting down and reloop depending on the Flash Length time
flashCounter = flashLength;
}
//This makes sure after the flashing and invincibility has worn off that the player renderer is always turned back on so you can see the player
if (invincibilityCounter <= 0)
{
playerRenderer.enabled = true;
}
}
if (isFadetoBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 1f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 1f)
{
isFadetoBlack = false;
}
}
if (isFadefromBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 0f)
{
isFadefromBlack = false;
}
}
}
public void HurtPlayer(int damage, Vector3 direction)
{
//If the invincibility countdown reaches zero it stops, making you no longer invincible and prone to taking damage again
if (invincibilityCounter <= 0)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Respawn();
}
else
{
thePlayer.Knockback(direction);
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
}
public void Respawn()
{
//A StartCoroutine must be set up before the IEnumerator can begin
if (!isRespawning)
{
StartCoroutine("RespawnCo");
}
}
//IEnumerators or Coroutines will execute the code separately at specified times while the rest of the code in a codeblock will carry on executing as normal.
//To prevent an error appearing below the name of the Coroutine, be sure to place a yield return somewhere within the code block. Either yield return null or a new WaitForSeconds.
public IEnumerator RespawnCo()
{
if (GameManager.currentGold < 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
//To reference another script's function quickly and just the once, use the FindObjectOfType function. This is considered to be slow however.
FindObjectOfType<GoldPickup>().DestroyGold();
//GetComponent<GoldPickup>().DestroyGold();
//Instantiate(goldBar, goldRespawnPoint, Quaternion.identity);
isFadefromBlack = true;
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
GameManager.currentGold = 0;
GetComponent<GameManager>().SetCountText();
StopCoroutine("RespawnCo");
/*isRespawning = true;
thePlayer.gameObject.SetActive(false);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
SceneManager.LoadScene("Level 1");
GameManager.currentGold = 0;*/
}
else if(GameManager.currentGold >= 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
/*public void HealPlayer(int healAmount)
{
currentHealth += healAmount;
if(currentHealth > maxHealth)
{
currentHealth = maxHealth;
}
}*/
public void SetSpawnPoint(Vector3 newPosition)
{
respawnPoint = newPosition;
}
public class Checkpoint : MonoBehaviour
public HealthManager theHealthManager;
public Renderer cpRenderer;
public Renderer postRenderer;
public SpriteRenderer pcRenderer;
public Material cpOff;
public Material cpOn;
public Material postOff;
public Material postOn;
public GameObject infoPanels;
public bool checkpoint1On;
//Make sure to assign a value to a bool with '=' and in an 'if' statement somewhere in the code to prevent warnings.
//private bool checkpoint1IsActivated;
private bool infoPanel1Activated;
void Start()
{
theHealthManager = FindObjectOfType<HealthManager>();
}
void Update()
//Key presses are better handled in the Update function and will recognise keys being pressed once every frame.
{
if (checkpoint1On == true)
{
if (infoPanel1Activated == false)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(true);
infoPanel1Activated = true;
}
}
else
{
if (infoPanel1Activated == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(false);
infoPanel1Activated = false;
}
}
}
}
}
public void Checkpoint1On()
{
cpRenderer.material = cpOn;
postRenderer.material = postOn;
pcRenderer.color = new Color(1f, 1f, 1f, 1f);
checkpoint1On = true;
}
// makes a variable an Array (a list). The 'foreach' loop will check through all the Checkpoint objects
//Checkpoint checkpoints = FindObjectsOfType<Checkpoint>();
//For each Checkpoint Array called 'checkpoints', look for 'cp' and turn the others in the list off
/*foreach (Checkpoint cp in checkpoints)
{
cp.CheckpointOff();
}
theRenderer.material = cpOn;*/
public void Checkpoint1Off()
{
cpRenderer.material = cpOff;
postRenderer.material = postOff;
pcRenderer.color = new Color(1f, 1f, 1f, 5f);
checkpoint1On = false;
}
public void OnTriggerStay(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if (GameManager.currentGold >= 5)
{
if (Input.GetKeyDown(KeyCode.Return))
{
theHealthManager.SetSpawnPoint(transform.position);
Checkpoint1On();
checkpoint1On = true;
}
}
else if (GameManager.currentGold <= 5)
{
checkpoint1On = false;
}
}
}
c# unity3d
add a comment |
I'm having difficulty getting my gold pickups to respawn after they've been destroyed on death. The idea is, if the player fails to pick up the 5 gold bars, activates a checkpoint, and dies, the current gold is destroyed and it resets once the screen has faded from black.
I currently have a Coroutine in my Health Manager that runs correctly if the player dies and resets them. I have a Gold Pickup script that destroys the gold if they haven't been picked up. I just can't seem to get them to re-instantiate. I've tried adding the instantiate code within the Health Manager's coroutine and within the Gold Pickup script. Nothing seems to work. If I'm not getting errors saying 'Array index is out of range' it's 'object reference not set to an instance of an object' etc.
public class GoldPickup : MonoBehaviour{
public int value;
public GameObject pickupEffect;
public GameObject goldBarArray;
public HealthManager healthManager;
public Checkpoint checkpoint;
private Vector3 goldRespawnPoint;
private Quaternion goldStartPosition;
void Start()
{
//To destroy multiple objects at once, use FindGameObjectsWithTag.
//GetComponent is considered more efficient than FindObjectOfType, but the latter avoids any errors saying an object reference hasn't been set.
goldBarArray = GameObject.FindGameObjectsWithTag("Gold");
healthManager = FindObjectOfType<HealthManager>();
//FindObjectOfType<Checkpoint>();
checkpoint = FindObjectOfType<Checkpoint>();
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
}
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
FindObjectOfType<GameManager>().AddGold(value);
Instantiate(pickupEffect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
public void DestroyGold()
{
//For Statics, an object reference isn't necessary. Use the FindObjectOfType to find the appropriate script and reference the Type, such as HealthManager.
if (checkpoint.checkpoint1On == false)
{
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
}
}
/*public void GoldReset()
{
if (healthManager.isRespawning == true)
{
if (checkpoint.checkpoint1On == false)
{
StartCoroutine("GoldRespawnCo");
}
}
else if (_respawnCoroutine != null)
{
StopCoroutine(_respawnCoroutine);
_respawnCoroutine = StartCoroutine("GoldRespawnCo");
}*/
/*public IEnumerator GoldRespawnCo()
{
if (checkpoint.checkpoint1On == false)
{
Instantiate(goldPrefab, goldRespawnPoint, goldStartPosition);
transform.position = goldRespawnPoint;
transform.rotation = goldStartPosition;
}
else
{
yield return null;
}
}*/
/*if (thePlayer.gameObject.activeInHierarchy == false)
{
Destroy(gameObject);
Instantiate(goldBar, transform.position, transform.rotation);
}
else
{
if (thePlayer.gameObject.activeInHierarchy == true)
{
transform.position = respawnPoint;
transform.rotation = startPosition;
}
}*/
}
public class HealthManager : MonoBehaviour
//The counters will count down and will keep counting down based on the length variables
public int maxHealth;
public int currentHealth;
public PlayerController thePlayer;
//public GoldPickup goldPickup;
//public GoldPickup goldPickup;
public float invincibilityLength;
public Renderer playerRenderer;
public float flashLength;
public float respawnLength;
public GameObject deathEffect;
public Image blackScreen;
public float fadeSpeed;
public float waitForFade;
public bool isRespawning;
//public GameObject goldBar;
//To reference another script's function, such as in the DeathTrigger script, make a public DeathTrigger, give it a reference name, and put it into the Start function. Use the reference name and assign it using GetComponent. Call another script's method by using the reference name, followed by a dot and the name of the method. Eg: deathTrigger.DestroyGold().
private Quaternion startPosition;
//private Quaternion goldPosition;
private float flashCounter;
private float invincibilityCounter;
private Vector3 respawnPoint;
//private Vector3 goldRespawnPoint;
private bool isFadetoBlack;
private bool isFadefromBlack;
//private Coroutine _respawnCoroutine;
//private Vector3 goldRespawnPoint;
//private Quaternion goldStartPosition;
void Start()
{
currentHealth = maxHealth;
respawnPoint = thePlayer.transform.position;
startPosition = thePlayer.transform.rotation;
//goldPickup = GetComponent<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
//goldRespawnPoint = transform.position;
//goldStartPosition = transform.rotation;
//goldPickup = FindObjectOfType<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldPosition = goldBar.transform.rotation;
}
void Update()
{
//These functions are checked every frame until the player takes damage
if (invincibilityCounter > 0)
{
invincibilityCounter -= Time.deltaTime;
flashCounter -= Time.deltaTime;
if (flashCounter <= 0)
//The Flash Counter is currently set at 0.1 and will be within the 0 region as it counts down. During this period, the playerRenderer will alternate between on and off
{
playerRenderer.enabled = !playerRenderer.enabled;
//The Flash Counter will keep counting down and reloop depending on the Flash Length time
flashCounter = flashLength;
}
//This makes sure after the flashing and invincibility has worn off that the player renderer is always turned back on so you can see the player
if (invincibilityCounter <= 0)
{
playerRenderer.enabled = true;
}
}
if (isFadetoBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 1f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 1f)
{
isFadetoBlack = false;
}
}
if (isFadefromBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 0f)
{
isFadefromBlack = false;
}
}
}
public void HurtPlayer(int damage, Vector3 direction)
{
//If the invincibility countdown reaches zero it stops, making you no longer invincible and prone to taking damage again
if (invincibilityCounter <= 0)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Respawn();
}
else
{
thePlayer.Knockback(direction);
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
}
public void Respawn()
{
//A StartCoroutine must be set up before the IEnumerator can begin
if (!isRespawning)
{
StartCoroutine("RespawnCo");
}
}
//IEnumerators or Coroutines will execute the code separately at specified times while the rest of the code in a codeblock will carry on executing as normal.
//To prevent an error appearing below the name of the Coroutine, be sure to place a yield return somewhere within the code block. Either yield return null or a new WaitForSeconds.
public IEnumerator RespawnCo()
{
if (GameManager.currentGold < 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
//To reference another script's function quickly and just the once, use the FindObjectOfType function. This is considered to be slow however.
FindObjectOfType<GoldPickup>().DestroyGold();
//GetComponent<GoldPickup>().DestroyGold();
//Instantiate(goldBar, goldRespawnPoint, Quaternion.identity);
isFadefromBlack = true;
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
GameManager.currentGold = 0;
GetComponent<GameManager>().SetCountText();
StopCoroutine("RespawnCo");
/*isRespawning = true;
thePlayer.gameObject.SetActive(false);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
SceneManager.LoadScene("Level 1");
GameManager.currentGold = 0;*/
}
else if(GameManager.currentGold >= 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
/*public void HealPlayer(int healAmount)
{
currentHealth += healAmount;
if(currentHealth > maxHealth)
{
currentHealth = maxHealth;
}
}*/
public void SetSpawnPoint(Vector3 newPosition)
{
respawnPoint = newPosition;
}
public class Checkpoint : MonoBehaviour
public HealthManager theHealthManager;
public Renderer cpRenderer;
public Renderer postRenderer;
public SpriteRenderer pcRenderer;
public Material cpOff;
public Material cpOn;
public Material postOff;
public Material postOn;
public GameObject infoPanels;
public bool checkpoint1On;
//Make sure to assign a value to a bool with '=' and in an 'if' statement somewhere in the code to prevent warnings.
//private bool checkpoint1IsActivated;
private bool infoPanel1Activated;
void Start()
{
theHealthManager = FindObjectOfType<HealthManager>();
}
void Update()
//Key presses are better handled in the Update function and will recognise keys being pressed once every frame.
{
if (checkpoint1On == true)
{
if (infoPanel1Activated == false)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(true);
infoPanel1Activated = true;
}
}
else
{
if (infoPanel1Activated == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(false);
infoPanel1Activated = false;
}
}
}
}
}
public void Checkpoint1On()
{
cpRenderer.material = cpOn;
postRenderer.material = postOn;
pcRenderer.color = new Color(1f, 1f, 1f, 1f);
checkpoint1On = true;
}
// makes a variable an Array (a list). The 'foreach' loop will check through all the Checkpoint objects
//Checkpoint checkpoints = FindObjectsOfType<Checkpoint>();
//For each Checkpoint Array called 'checkpoints', look for 'cp' and turn the others in the list off
/*foreach (Checkpoint cp in checkpoints)
{
cp.CheckpointOff();
}
theRenderer.material = cpOn;*/
public void Checkpoint1Off()
{
cpRenderer.material = cpOff;
postRenderer.material = postOff;
pcRenderer.color = new Color(1f, 1f, 1f, 5f);
checkpoint1On = false;
}
public void OnTriggerStay(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if (GameManager.currentGold >= 5)
{
if (Input.GetKeyDown(KeyCode.Return))
{
theHealthManager.SetSpawnPoint(transform.position);
Checkpoint1On();
checkpoint1On = true;
}
}
else if (GameManager.currentGold <= 5)
{
checkpoint1On = false;
}
}
}
c# unity3d
I'm having difficulty getting my gold pickups to respawn after they've been destroyed on death. The idea is, if the player fails to pick up the 5 gold bars, activates a checkpoint, and dies, the current gold is destroyed and it resets once the screen has faded from black.
I currently have a Coroutine in my Health Manager that runs correctly if the player dies and resets them. I have a Gold Pickup script that destroys the gold if they haven't been picked up. I just can't seem to get them to re-instantiate. I've tried adding the instantiate code within the Health Manager's coroutine and within the Gold Pickup script. Nothing seems to work. If I'm not getting errors saying 'Array index is out of range' it's 'object reference not set to an instance of an object' etc.
public class GoldPickup : MonoBehaviour{
public int value;
public GameObject pickupEffect;
public GameObject goldBarArray;
public HealthManager healthManager;
public Checkpoint checkpoint;
private Vector3 goldRespawnPoint;
private Quaternion goldStartPosition;
void Start()
{
//To destroy multiple objects at once, use FindGameObjectsWithTag.
//GetComponent is considered more efficient than FindObjectOfType, but the latter avoids any errors saying an object reference hasn't been set.
goldBarArray = GameObject.FindGameObjectsWithTag("Gold");
healthManager = FindObjectOfType<HealthManager>();
//FindObjectOfType<Checkpoint>();
checkpoint = FindObjectOfType<Checkpoint>();
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
}
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
FindObjectOfType<GameManager>().AddGold(value);
Instantiate(pickupEffect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
public void DestroyGold()
{
//For Statics, an object reference isn't necessary. Use the FindObjectOfType to find the appropriate script and reference the Type, such as HealthManager.
if (checkpoint.checkpoint1On == false)
{
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
}
}
/*public void GoldReset()
{
if (healthManager.isRespawning == true)
{
if (checkpoint.checkpoint1On == false)
{
StartCoroutine("GoldRespawnCo");
}
}
else if (_respawnCoroutine != null)
{
StopCoroutine(_respawnCoroutine);
_respawnCoroutine = StartCoroutine("GoldRespawnCo");
}*/
/*public IEnumerator GoldRespawnCo()
{
if (checkpoint.checkpoint1On == false)
{
Instantiate(goldPrefab, goldRespawnPoint, goldStartPosition);
transform.position = goldRespawnPoint;
transform.rotation = goldStartPosition;
}
else
{
yield return null;
}
}*/
/*if (thePlayer.gameObject.activeInHierarchy == false)
{
Destroy(gameObject);
Instantiate(goldBar, transform.position, transform.rotation);
}
else
{
if (thePlayer.gameObject.activeInHierarchy == true)
{
transform.position = respawnPoint;
transform.rotation = startPosition;
}
}*/
}
public class HealthManager : MonoBehaviour
//The counters will count down and will keep counting down based on the length variables
public int maxHealth;
public int currentHealth;
public PlayerController thePlayer;
//public GoldPickup goldPickup;
//public GoldPickup goldPickup;
public float invincibilityLength;
public Renderer playerRenderer;
public float flashLength;
public float respawnLength;
public GameObject deathEffect;
public Image blackScreen;
public float fadeSpeed;
public float waitForFade;
public bool isRespawning;
//public GameObject goldBar;
//To reference another script's function, such as in the DeathTrigger script, make a public DeathTrigger, give it a reference name, and put it into the Start function. Use the reference name and assign it using GetComponent. Call another script's method by using the reference name, followed by a dot and the name of the method. Eg: deathTrigger.DestroyGold().
private Quaternion startPosition;
//private Quaternion goldPosition;
private float flashCounter;
private float invincibilityCounter;
private Vector3 respawnPoint;
//private Vector3 goldRespawnPoint;
private bool isFadetoBlack;
private bool isFadefromBlack;
//private Coroutine _respawnCoroutine;
//private Vector3 goldRespawnPoint;
//private Quaternion goldStartPosition;
void Start()
{
currentHealth = maxHealth;
respawnPoint = thePlayer.transform.position;
startPosition = thePlayer.transform.rotation;
//goldPickup = GetComponent<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
//goldRespawnPoint = transform.position;
//goldStartPosition = transform.rotation;
//goldPickup = FindObjectOfType<GoldPickup>();
//goldRespawnPoint = goldBar.transform.position;
//goldPosition = goldBar.transform.rotation;
}
void Update()
{
//These functions are checked every frame until the player takes damage
if (invincibilityCounter > 0)
{
invincibilityCounter -= Time.deltaTime;
flashCounter -= Time.deltaTime;
if (flashCounter <= 0)
//The Flash Counter is currently set at 0.1 and will be within the 0 region as it counts down. During this period, the playerRenderer will alternate between on and off
{
playerRenderer.enabled = !playerRenderer.enabled;
//The Flash Counter will keep counting down and reloop depending on the Flash Length time
flashCounter = flashLength;
}
//This makes sure after the flashing and invincibility has worn off that the player renderer is always turned back on so you can see the player
if (invincibilityCounter <= 0)
{
playerRenderer.enabled = true;
}
}
if (isFadetoBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 1f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 1f)
{
isFadetoBlack = false;
}
}
if (isFadefromBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 0f)
{
isFadefromBlack = false;
}
}
}
public void HurtPlayer(int damage, Vector3 direction)
{
//If the invincibility countdown reaches zero it stops, making you no longer invincible and prone to taking damage again
if (invincibilityCounter <= 0)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Respawn();
}
else
{
thePlayer.Knockback(direction);
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
}
public void Respawn()
{
//A StartCoroutine must be set up before the IEnumerator can begin
if (!isRespawning)
{
StartCoroutine("RespawnCo");
}
}
//IEnumerators or Coroutines will execute the code separately at specified times while the rest of the code in a codeblock will carry on executing as normal.
//To prevent an error appearing below the name of the Coroutine, be sure to place a yield return somewhere within the code block. Either yield return null or a new WaitForSeconds.
public IEnumerator RespawnCo()
{
if (GameManager.currentGold < 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
//To reference another script's function quickly and just the once, use the FindObjectOfType function. This is considered to be slow however.
FindObjectOfType<GoldPickup>().DestroyGold();
//GetComponent<GoldPickup>().DestroyGold();
//Instantiate(goldBar, goldRespawnPoint, Quaternion.identity);
isFadefromBlack = true;
//goldRespawnPoint = goldBar.transform.position;
//goldStartPosition = goldBar.transform.rotation;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
GameManager.currentGold = 0;
GetComponent<GameManager>().SetCountText();
StopCoroutine("RespawnCo");
/*isRespawning = true;
thePlayer.gameObject.SetActive(false);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
SceneManager.LoadScene("Level 1");
GameManager.currentGold = 0;*/
}
else if(GameManager.currentGold >= 5)
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, respawnPoint, startPosition);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
thePlayer.transform.rotation = startPosition;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
/*public void HealPlayer(int healAmount)
{
currentHealth += healAmount;
if(currentHealth > maxHealth)
{
currentHealth = maxHealth;
}
}*/
public void SetSpawnPoint(Vector3 newPosition)
{
respawnPoint = newPosition;
}
public class Checkpoint : MonoBehaviour
public HealthManager theHealthManager;
public Renderer cpRenderer;
public Renderer postRenderer;
public SpriteRenderer pcRenderer;
public Material cpOff;
public Material cpOn;
public Material postOff;
public Material postOn;
public GameObject infoPanels;
public bool checkpoint1On;
//Make sure to assign a value to a bool with '=' and in an 'if' statement somewhere in the code to prevent warnings.
//private bool checkpoint1IsActivated;
private bool infoPanel1Activated;
void Start()
{
theHealthManager = FindObjectOfType<HealthManager>();
}
void Update()
//Key presses are better handled in the Update function and will recognise keys being pressed once every frame.
{
if (checkpoint1On == true)
{
if (infoPanel1Activated == false)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(true);
infoPanel1Activated = true;
}
}
else
{
if (infoPanel1Activated == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(false);
infoPanel1Activated = false;
}
}
}
}
}
public void Checkpoint1On()
{
cpRenderer.material = cpOn;
postRenderer.material = postOn;
pcRenderer.color = new Color(1f, 1f, 1f, 1f);
checkpoint1On = true;
}
// makes a variable an Array (a list). The 'foreach' loop will check through all the Checkpoint objects
//Checkpoint checkpoints = FindObjectsOfType<Checkpoint>();
//For each Checkpoint Array called 'checkpoints', look for 'cp' and turn the others in the list off
/*foreach (Checkpoint cp in checkpoints)
{
cp.CheckpointOff();
}
theRenderer.material = cpOn;*/
public void Checkpoint1Off()
{
cpRenderer.material = cpOff;
postRenderer.material = postOff;
pcRenderer.color = new Color(1f, 1f, 1f, 5f);
checkpoint1On = false;
}
public void OnTriggerStay(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if (GameManager.currentGold >= 5)
{
if (Input.GetKeyDown(KeyCode.Return))
{
theHealthManager.SetSpawnPoint(transform.position);
Checkpoint1On();
checkpoint1On = true;
}
}
else if (GameManager.currentGold <= 5)
{
checkpoint1On = false;
}
}
}
c# unity3d
c# unity3d
edited Jan 1 at 0:25
Alexei Levenkov
84.7k891136
84.7k891136
asked Dec 31 '18 at 12:52
DustyShinigamiDustyShinigami
61
61
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
In your DestroyGold()
function, you instantiate the gold like this:
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
But transform.position
and transform.rotation
only get the position and rotation of the current object (i.e. whatever your script is attached to). So not only are you spawning all the gold in the same spot, it's spawning the gold at the location of the object that holds your script, not where you actually want it to go!
Without knowing much about the objects in your scene, here's what I can tell you: try creating a Transform
to store the locations where you want to respawn the gold. Also, make sure you assign the goldRespawnPoint
and goldStartPosition
BEFORE you call Instantiate()
in your foreach loop. Finally, just a general tip: you should never use variable == true
or variable == false
in an if
statement. You can just use if(variable)
or if(!variable)
, respectively. It will work just the same while being more readable and reducing the amount of code you need to write.
EDIT 1: In response to comments, I've added specific code examples for implementing these suggestions.
To start, you're probably getting the out of range error because of goldBarArray[5]
. Since arrays start at index 0, you can only access up to element n-1
in a size n
array. More on how to fix this in the next step.
Now for the Transform
array. In the area where you declare your public variables (at the top of the script), add the line
public Transform spawnPoints;
Then, back in Unity you will be able to assign those spawn points in the Inspector.
EDIT 2: Additionally, in the foreach
loop you're trying to instantiate one of the gold bars from the scene, but those are getting deleted with the Destroy(Gold);
statement. Instead, you should be instantiating from the prefab which won't get destroyed. To do this, add
public GameObject goldPrefab;
up with the rest of your public variables. Then, in the Editor create a prefab by dragging one of the gold bars from the Hierarchy into your Assets folder. Finally, set that prefab to be the value of goldPrefab
in the Inspector.
Now, you actually can clean up your foreach
loop a little bit. You can get rid of the goldRespawnPoint
and goldStartPosition
lines because the respawn locations will be contained in the Transform
array we just created. Again, without knowing how your scene is structured I've needed to just make an educated guess about what will work. Give this loop a try:
int spawnPointCounter = 0;
foreach(GameObject Gold in goldBarArray){
Destroy(Gold);
Transform currentSP = spawnPoints[spawnPointCounter];
Instantiate(goldPrefab, currentSP.position, currentSP.rotation);
spawnPointCounter++;
}
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
|
show 4 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53987753%2fhow-can-i-respawn-pickups-in-an-array-and-through-a-coroutine%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
In your DestroyGold()
function, you instantiate the gold like this:
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
But transform.position
and transform.rotation
only get the position and rotation of the current object (i.e. whatever your script is attached to). So not only are you spawning all the gold in the same spot, it's spawning the gold at the location of the object that holds your script, not where you actually want it to go!
Without knowing much about the objects in your scene, here's what I can tell you: try creating a Transform
to store the locations where you want to respawn the gold. Also, make sure you assign the goldRespawnPoint
and goldStartPosition
BEFORE you call Instantiate()
in your foreach loop. Finally, just a general tip: you should never use variable == true
or variable == false
in an if
statement. You can just use if(variable)
or if(!variable)
, respectively. It will work just the same while being more readable and reducing the amount of code you need to write.
EDIT 1: In response to comments, I've added specific code examples for implementing these suggestions.
To start, you're probably getting the out of range error because of goldBarArray[5]
. Since arrays start at index 0, you can only access up to element n-1
in a size n
array. More on how to fix this in the next step.
Now for the Transform
array. In the area where you declare your public variables (at the top of the script), add the line
public Transform spawnPoints;
Then, back in Unity you will be able to assign those spawn points in the Inspector.
EDIT 2: Additionally, in the foreach
loop you're trying to instantiate one of the gold bars from the scene, but those are getting deleted with the Destroy(Gold);
statement. Instead, you should be instantiating from the prefab which won't get destroyed. To do this, add
public GameObject goldPrefab;
up with the rest of your public variables. Then, in the Editor create a prefab by dragging one of the gold bars from the Hierarchy into your Assets folder. Finally, set that prefab to be the value of goldPrefab
in the Inspector.
Now, you actually can clean up your foreach
loop a little bit. You can get rid of the goldRespawnPoint
and goldStartPosition
lines because the respawn locations will be contained in the Transform
array we just created. Again, without knowing how your scene is structured I've needed to just make an educated guess about what will work. Give this loop a try:
int spawnPointCounter = 0;
foreach(GameObject Gold in goldBarArray){
Destroy(Gold);
Transform currentSP = spawnPoints[spawnPointCounter];
Instantiate(goldPrefab, currentSP.position, currentSP.rotation);
spawnPointCounter++;
}
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
|
show 4 more comments
In your DestroyGold()
function, you instantiate the gold like this:
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
But transform.position
and transform.rotation
only get the position and rotation of the current object (i.e. whatever your script is attached to). So not only are you spawning all the gold in the same spot, it's spawning the gold at the location of the object that holds your script, not where you actually want it to go!
Without knowing much about the objects in your scene, here's what I can tell you: try creating a Transform
to store the locations where you want to respawn the gold. Also, make sure you assign the goldRespawnPoint
and goldStartPosition
BEFORE you call Instantiate()
in your foreach loop. Finally, just a general tip: you should never use variable == true
or variable == false
in an if
statement. You can just use if(variable)
or if(!variable)
, respectively. It will work just the same while being more readable and reducing the amount of code you need to write.
EDIT 1: In response to comments, I've added specific code examples for implementing these suggestions.
To start, you're probably getting the out of range error because of goldBarArray[5]
. Since arrays start at index 0, you can only access up to element n-1
in a size n
array. More on how to fix this in the next step.
Now for the Transform
array. In the area where you declare your public variables (at the top of the script), add the line
public Transform spawnPoints;
Then, back in Unity you will be able to assign those spawn points in the Inspector.
EDIT 2: Additionally, in the foreach
loop you're trying to instantiate one of the gold bars from the scene, but those are getting deleted with the Destroy(Gold);
statement. Instead, you should be instantiating from the prefab which won't get destroyed. To do this, add
public GameObject goldPrefab;
up with the rest of your public variables. Then, in the Editor create a prefab by dragging one of the gold bars from the Hierarchy into your Assets folder. Finally, set that prefab to be the value of goldPrefab
in the Inspector.
Now, you actually can clean up your foreach
loop a little bit. You can get rid of the goldRespawnPoint
and goldStartPosition
lines because the respawn locations will be contained in the Transform
array we just created. Again, without knowing how your scene is structured I've needed to just make an educated guess about what will work. Give this loop a try:
int spawnPointCounter = 0;
foreach(GameObject Gold in goldBarArray){
Destroy(Gold);
Transform currentSP = spawnPoints[spawnPointCounter];
Instantiate(goldPrefab, currentSP.position, currentSP.rotation);
spawnPointCounter++;
}
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
|
show 4 more comments
In your DestroyGold()
function, you instantiate the gold like this:
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
But transform.position
and transform.rotation
only get the position and rotation of the current object (i.e. whatever your script is attached to). So not only are you spawning all the gold in the same spot, it's spawning the gold at the location of the object that holds your script, not where you actually want it to go!
Without knowing much about the objects in your scene, here's what I can tell you: try creating a Transform
to store the locations where you want to respawn the gold. Also, make sure you assign the goldRespawnPoint
and goldStartPosition
BEFORE you call Instantiate()
in your foreach loop. Finally, just a general tip: you should never use variable == true
or variable == false
in an if
statement. You can just use if(variable)
or if(!variable)
, respectively. It will work just the same while being more readable and reducing the amount of code you need to write.
EDIT 1: In response to comments, I've added specific code examples for implementing these suggestions.
To start, you're probably getting the out of range error because of goldBarArray[5]
. Since arrays start at index 0, you can only access up to element n-1
in a size n
array. More on how to fix this in the next step.
Now for the Transform
array. In the area where you declare your public variables (at the top of the script), add the line
public Transform spawnPoints;
Then, back in Unity you will be able to assign those spawn points in the Inspector.
EDIT 2: Additionally, in the foreach
loop you're trying to instantiate one of the gold bars from the scene, but those are getting deleted with the Destroy(Gold);
statement. Instead, you should be instantiating from the prefab which won't get destroyed. To do this, add
public GameObject goldPrefab;
up with the rest of your public variables. Then, in the Editor create a prefab by dragging one of the gold bars from the Hierarchy into your Assets folder. Finally, set that prefab to be the value of goldPrefab
in the Inspector.
Now, you actually can clean up your foreach
loop a little bit. You can get rid of the goldRespawnPoint
and goldStartPosition
lines because the respawn locations will be contained in the Transform
array we just created. Again, without knowing how your scene is structured I've needed to just make an educated guess about what will work. Give this loop a try:
int spawnPointCounter = 0;
foreach(GameObject Gold in goldBarArray){
Destroy(Gold);
Transform currentSP = spawnPoints[spawnPointCounter];
Instantiate(goldPrefab, currentSP.position, currentSP.rotation);
spawnPointCounter++;
}
In your DestroyGold()
function, you instantiate the gold like this:
foreach (GameObject Gold in goldBarArray)
{
Destroy(Gold);
Instantiate(goldBarArray[5], goldRespawnPoint, goldStartPosition);
goldRespawnPoint = transform.position;
goldStartPosition = transform.rotation;
//healthManager.RespawnCo();
}
But transform.position
and transform.rotation
only get the position and rotation of the current object (i.e. whatever your script is attached to). So not only are you spawning all the gold in the same spot, it's spawning the gold at the location of the object that holds your script, not where you actually want it to go!
Without knowing much about the objects in your scene, here's what I can tell you: try creating a Transform
to store the locations where you want to respawn the gold. Also, make sure you assign the goldRespawnPoint
and goldStartPosition
BEFORE you call Instantiate()
in your foreach loop. Finally, just a general tip: you should never use variable == true
or variable == false
in an if
statement. You can just use if(variable)
or if(!variable)
, respectively. It will work just the same while being more readable and reducing the amount of code you need to write.
EDIT 1: In response to comments, I've added specific code examples for implementing these suggestions.
To start, you're probably getting the out of range error because of goldBarArray[5]
. Since arrays start at index 0, you can only access up to element n-1
in a size n
array. More on how to fix this in the next step.
Now for the Transform
array. In the area where you declare your public variables (at the top of the script), add the line
public Transform spawnPoints;
Then, back in Unity you will be able to assign those spawn points in the Inspector.
EDIT 2: Additionally, in the foreach
loop you're trying to instantiate one of the gold bars from the scene, but those are getting deleted with the Destroy(Gold);
statement. Instead, you should be instantiating from the prefab which won't get destroyed. To do this, add
public GameObject goldPrefab;
up with the rest of your public variables. Then, in the Editor create a prefab by dragging one of the gold bars from the Hierarchy into your Assets folder. Finally, set that prefab to be the value of goldPrefab
in the Inspector.
Now, you actually can clean up your foreach
loop a little bit. You can get rid of the goldRespawnPoint
and goldStartPosition
lines because the respawn locations will be contained in the Transform
array we just created. Again, without knowing how your scene is structured I've needed to just make an educated guess about what will work. Give this loop a try:
int spawnPointCounter = 0;
foreach(GameObject Gold in goldBarArray){
Destroy(Gold);
Transform currentSP = spawnPoints[spawnPointCounter];
Instantiate(goldPrefab, currentSP.position, currentSP.rotation);
spawnPointCounter++;
}
edited Jan 1 at 0:50
answered Dec 31 '18 at 19:45
jbinvntjbinvnt
6127
6127
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
|
show 4 more comments
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Thanks for the explanation. I'll give that a try and see. Apart from the Start function, where should I assign the goldRespawnPoint and goldStartPosition before calling Instantiate? Also, thanks for the tip about the if statements. That's quite useful to know. :)
– DustyShinigami
Dec 31 '18 at 20:24
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
Also, if I instantiate the gold like in that function, I get an error saying Array index is out of range.
– DustyShinigami
Dec 31 '18 at 20:40
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
No, I'm not even sure how I'd go about setting up a Transform array to get the gold's position. :-
– DustyShinigami
Dec 31 '18 at 21:12
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
I've added more to my answer that will hopefully address your questions. Please don't forget to upvote my answer if it was helpful and mark it as accepted if it solved your problem.
– jbinvnt
Dec 31 '18 at 21:59
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
We're almost there by the looks of it. :D Though when it gets to Instantiate, it gives me an error saying 'The object of type 'Transform' has been destroyed but you are still trying to access it.'
– DustyShinigami
Dec 31 '18 at 23:41
|
show 4 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53987753%2fhow-can-i-respawn-pickups-in-an-array-and-through-a-coroutine%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown