From some reason my code doesn’t instantiate my prefab. However, if I don’t use the instance = Instantiate(…) rather instantiate directly Instantiate (…), then it works, but then I’m not able to destroy the gameobjects that I create.
using UnityEngine;
using System.Collections;
public class Driving : MonoBehaviour {
public GameObject RightBlast;
public GameObject LeftBlast;
public GameObject instance;
void FixedUpdate ()
{
if (Input.GetKeyDown(KeyCode.D)) {
instance = Instantiate (RightBlast, transform.position, RightBlast.transform.rotation) as GameObject;
Destroy(instance);
}
if (Input.GetKeyDown(KeyCode.A)) {
instance = Instantiate (LeftBlast, transform.position, LeftBlast.transform.rotation) as GameObject;
Destroy(instance);
}
}
}
GameObject.Instantiate is redundant - the method is defined in Object, which is a class you’re inside. So GameObject.Instantiate gives you exactly the same method as just “instantiate”.
The correct invocation would be:
instance = (GameObject) Instantiate(...
Or if you’re using Unity 5:
instance = Instantiate(...
As there’s a generic version of Instantiate now that makes casting redundant as long as you’re instantiating a GameObject.
What do you get in the debugger when you run the game?
edit:
Also why do you do “RightBlast.transform.rotation”? As far as I know a prefab is Always instantiated with it’s own rotation added to the rotation you give to the Instantiate call, meaning that you can just use “transform.rotation” or “Quaternion.identity”.
You’re right, I destroyed it as soon as I created it.
OK, so now I’m trying to time the destroy object with a coroutine but from some reason it creates waaaay more objects than it destroys!
If I use GetKeyDown instead of GetKey I lose continuous motion (in addition to instantiating a gameobject the key is supposed to make the object move) and it still generally creates more objects than it destroys, depends on how frequency I press the key.
using UnityEngine;
using System.Collections;
public class Driving : MonoBehaviour {
public GameObject RightBlast;
public GameObject LeftBlast;
public GameObject instance;
public float speed = 0.1f; //player's moving speed
// Update is called once per frame
void FixedUpdate ()
{
if (Input.GetKey(KeyCode.D)) {
GetComponent<Rigidbody>().AddForce (transform.right * speed);
StartCoroutine(RocketFireLeft());
}
if (Input.GetKey(KeyCode.A)) {
GetComponent<Rigidbody>().AddForce (-transform.right * speed);
StartCoroutine(RocketFireRight());
}
}
IEnumerator RocketFireRight()
{
instance = (GameObject) Instantiate (RightBlast, transform.position, RightBlast.transform.rotation);
yield return new WaitForSeconds(0.5f);
Destroy(instance);
}
IEnumerator RocketFireLeft()
{
instance = (GameObject) Instantiate (LeftBlast, transform.position, LeftBlast.transform.rotation);
yield return new WaitForSeconds(0.5f);
Destroy (instance);
}
}
Because instance is a field, so each subsequent coroutine overrides that field.
Say you’re running on 60 fps. Then between you call Instantiate in the coroutine, and WaitForSeconds(.5f), 30 new right/left blasts has been instantiated. When you get to the Destroy statement, only the very last of those are destroyed.
So the first ((fps - 1) * 0.5) RightBlasts that are created when you hold down the D button are going to never be destroyed, while each of the next ones will be destroyed after one frame, when the coroutine started .5 seconds before it gets to the Destroy statement.
Just declare instance locally, and the coroutine will delete the instantiated object:
var instance = (GameObject) Instantiate(...
yield return new WaitForSeconds(0.5f);
Destroy(instance)
Note that you don’t need a coroutine here - Destroy has an optional second parameter that’s a timeout. So you could replace this:
if (Input.GetKey(KeyCode.D)) {
GetComponent<Rigidbody>().AddForce (transform.right * speed);
StartCoroutine(RocketFireLeft());
}
...
IEnumerator RocketFireLeft()
{
var instance = (GameObject) Instantiate (LeftBlast, transform.position, LeftBlast.transform.rotation);
yield return new WaitForSeconds(0.5f);
Destroy (instance);
}
If ‘var’ is new to you, it’s just short for "figure out what type’s supposed to be here. You can use GameObject in all the instances I’ve used var if that’s more to your liking.
That’s not his code, it’s yours. You haven’t changed the return type to “void” like he did, to stop it from being a coroutine.
Coroutine or not, if a function has a return type then you HAVE to return something. IEnumerator happens to be the return type of coroutines, so if you specify that it has to return an IEnumerator, then you have to return an IEnumerator. Changing it to “void” means you don’t have to return anything- it’ll just end automatically when it hits the end of the function.
I think this is another example of how programming shortcuts tend to confuse new people. If C# required “return null;” in their void functions this wouldn’t happen.