简体   繁体   中英

Unity3D - unable to respawn an object after it has been destroyed

I am having an issue respawning a prefab after it has been destroyed. I can't seem to get it to respawn back at its original start position after a second of being destroyed. I have created an empty game object and attached the SpawnTargets.cs script to it. I'm not sure of what the best methodology to approach this situation. Another object with a script attached to it does the actual destroy of the prefab. BulletCollisionHandler.cs works fine though. Thanks for any help. Code is below:

SpawnTargets.cs:

using UnityEngine;
using System.Collections;

public class SpawnTargets : MonoBehaviour 
{
    public GameObject targetCircle;
    public GameObject targetSquare;
    public GameObject targetStar;

    private Vector3 circleSpawnPosition = new Vector3(0.0f, 1.227389f, -7.5f);
    private Vector3 squareSpawnPosition = new Vector3(0.0f, 1.027975f, -7.993299f);
    private Vector3 starSpawnPosition = new Vector3(0.0f, 1.8f, -7f);

    // Use this for initialization
    void Start ()
    {

    }

    // Update is called once per frame
    void Update ()
    {
        SpawnTarget ();
    }

    void SpawnTarget()
    {

    }
}

BulletCollisionHandler.cs:

using UnityEngine;
using System.Collections;

public class BulletCollisionHandler : MonoBehaviour 
{
    public GameObject targetCircle;

    // Use this for initialization
    void Start () 
    {
        Destroy (gameObject, 2);
    }

    // Update is called once per frame
    void Update ()
    {

    }

    void OnCollisionEnter(Collision other)
    {
        if(other.gameObject.name == "TargetSquare")
        {
            other.gameObject.rigidbody.isKinematic = false;
            ((TargetMovementHorizontal)other.gameObject.GetComponent<TargetMovementHorizontal>()).enabled = false;

            Destroy (other.gameObject, 1);
            Debug.Log("Hit square");
        }
        else if(other.gameObject.name == "TargetCircle")
        {
            other.gameObject.rigidbody.isKinematic = false;
            ((TargetMovementHorizontal)other.gameObject.GetComponent<TargetMovementHorizontal>()).enabled = false;

            Destroy (other.gameObject, 1);

            Debug.Log("Hit circle");
        }
        else if(other.gameObject.name == "TargetStar")
        {
            other.gameObject.rigidbody.isKinematic = false;
            ((TargetMovementHorizontal)other.gameObject.GetComponent<TargetMovementHorizontal>()).enabled = false;
            ((TargetMovementVertical)other.gameObject.GetComponent<TargetMovementVertical>()).enabled = false;

            Destroy (other.gameObject, 1);
            Debug.Log("Hit star");
        }
    }
}

You're not calling Instantiate() anywhere, so it's hard to see where the new object would come from in the code you've supplied.

In any case, it might be better not to use Destroy. If you want to immediately reset the object, why not simply recycle it back to the start position? It's a good idea to avoid instantiating and destroying lots of objects, it's better to hide/disable the ones your don't need and unhide/re-enable them.

Here's a tutorial on the general idea. The tutorial is about groups of objects but the same trick would work for recycling single objects too.

You are better of using gameObject.SetActive( true/false ); for activating / deactivating the gameObject instead of just using Destroy.

Then if you are using Destroy you have 3 options that comes to mind for getting it into the desire position before the Player sees it.

1) You enable the game object after disabling its Renderer component. Then you equalize the transform's position / rotation the one you need. After this you re-enable the Renderer component. It should be placed where you want it.

2) You Instantiate the gameObject, but first making sure the Renderer component is disabled on its Prefab, by default, so you can re-assign its Transform values then - re-enable the Renderer again.

3) You make an invisible gameObject (an Empty gameObject) and Instantiate the wanted gameObject, you then make the Empty to be the parent of the newly created gameObject.. Provided that the parent Empty is exactly where you want it to be, when you instantiate and reset the child's position it should jump off right on top the the Empty parent.

I'm not giving code since you haven't and I don't have no idea of which method you might end up liking more. In terms of performance the Enable/Disable are the best option.

And as theodox says Object Pooling is your best friend for things like bullets, although it might be applied to many other gameObjects that might work as 'collections of objects' on your game's logic. It's totally worth learning.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM