- Home /
Instantiate Pre-fab clone altered on Instantiate
Hey folks,
So i've been working on a 2D platformer, learning as I go, and i've gotten to a point where I want my level to essentially reset on death, but load the player at the last checkpoint they visited.
Due to mechanics reasons I don't want the entire level to reset, just the breaking platforms etc, so i've created a pre-fab containing all those objects in their starting state, and the idea is that when the player days it deletes the current version of that prefab and loads in a fresh one, effectively resetting everything.
The issue i've got though is that the prefab that gets loaded in is an exact clone of the previous one, and not the original, meaning that the platforms etc are still missing.
I'm sure it's an easy fix, but as someone new to coding i'm really not sure what to change.
Here the public GameObject gameObjects is my levels platforms etc, and the reload is occurring in the public void makeDead.
Any help would be great!
Thanks
public class playerHealth : MonoBehaviour {
public float fullHealth;
public GameObject deathFX;
public AudioClip playerHurt;
public AudioClip playerDeath;
public AudioClip playerWin;
public Vector3 respawnPoint;
public static Player player;
private float time = 5f;
private GameObject instantiatedObj;
public GameObject gameObjects;
public float healthAmount;
float currentHealth;
public RestartGame gameManager;
AudioSource playerAS;
//HUD Variables
public Slider healthSlider;
public Image damageScreen;
public Text gameOverScreen;
public Text winScreen;
private bool damaged = false;
Color damagedColour = new Color (0f,0f,0f,0.4f);
float smoothColour = 5f;
void Awake()
{
gameObjects = (GameObject) Instantiate (gameObjects);
}
// Use this for initialization
void Start () {
currentHealth = fullHealth;
//HUD Initialisation
healthSlider.maxValue = fullHealth;
healthSlider.value = fullHealth;
playerAS = GetComponent<AudioSource> ();
}
// Update is called once per frame
void Update () {
if (damaged) {
damageScreen.color = damagedColour;
} else {
damageScreen.color = Color.Lerp(damageScreen.color, Color.clear, smoothColour*Time.deltaTime);
}
damaged = false;
}
public void addDamage(float damage){
if (damage <= 0)
return;
currentHealth -= damage;
playerAS.clip = playerHurt;
playerAS.Play ();
//playerAS.PlayOneShot (playerHurt);
healthSlider.value = currentHealth;
damaged = true;
if (currentHealth <= 0) {
makeDead();
}
}
public void addHealth(float healthAmount){
currentHealth += healthAmount;
if (currentHealth > fullHealth)
currentHealth = fullHealth;
healthSlider.value = currentHealth;
}
public void makeDead(){
instantiatedObj = (GameObject) Instantiate (deathFX, transform.position, transform.rotation);
Destroy (instantiatedObj, time);
AudioSource.PlayClipAtPoint (playerDeath, transform.position);
damageScreen.color = damagedColour;
transform.position = respawnPoint;
currentHealth += healthAmount;
if (currentHealth > fullHealth)
currentHealth = fullHealth;
healthSlider.value = currentHealth;
Destroy(gameObjects);
Instantiate (gameObjects);
}
public void winGame(){
Destroy (gameObject);
AudioSource.PlayClipAtPoint (playerWin, transform.position);
Animator winGameAnimator = winScreen.GetComponent<Animator> ();
winGameAnimator.SetTrigger("gameOver");
gameManager.restartTheGame();
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "Checkpoint") {
respawnPoint = other.transform.position;
}
}
}
Answer by Daemonhahn · Jul 25, 2017 at 03:52 PM
Dont instantiate all of them at once like:
gameObjects = (GameObject) Instantiate (gameObjects);
Instead loop through each and Instantiate them, getting a reference to each. Then use this reference to get components and adjust the instantiated object. Like this:
foreach(GameObject g in gameObjects)
{
GameObject obj = Instantiate(g);
// use get component with references to get parts of the object and adjust
ExampleComponent example = obj.GetComponent<ExampleComponent>();
// you can then access properties of that component
example.someThing = anotherThing.
// finally set its position to where you want
obj.transform.position = new Vector3(0,0,0);
}
Answer by Bairne · Jul 25, 2017 at 04:37 PM
That's awesome and i'll definitely give that a go!
It would be great to know why in the version I was using the prefab selected from the folder is replaced by its clone when it gets instantiated though, as this is something i'll likely use down the line and that I've seen bought up a few times by others whilst I tried to find a solution.
Is there a way to lock the selected prefab to the original version, rather than it referencing itself over and over again, and thus never resetting?
Or alternatively have I done something wrong in my code that causes it to start referencing the clone instead of the original prefab?
Thanks again for the help!
Hi!
This is because when you instantiate you create a clone of the original object.
A prefab is just a template of an object used for creating clones of objects.
If you would like to load an object ins$$anonymous$$d of clone one, look at Resources.Load :) Although instantiating will always create a clone, so bare that in $$anonymous$$d.
Good luck and feel free to message me if you have any further issues.
Also when you do:
Destroy(gameObjects); Instantiate (gameObjects);
you have just destroyed gameObjects and then try to instantiate them which will ofcourse not work as you destroyed the object at the end of the reference.
Could you please select my answer as the correct one if your issue is resolved?
Done :D Thanks again! $$anonymous$$anaged to get it working with Resources.Load, but working on transferring it to original answer as well.
Glad i could help, feel free to message me if theres ever any issues in the future