简体   繁体   English

Unity3D-销毁对象后无法重生

[英]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. 我创建了一个空的游戏对象,并将SpawnTargets.cs脚本附加到该对象。 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. BulletCollisionHandler.cs可以正常工作。 Thanks for any help. 谢谢你的帮助。 Code is below: 代码如下:

SpawnTargets.cs: 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: 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. 您不会在任何地方调用Instantiate(),因此很难在提供的代码中看到新对象的来源。

In any case, it might be better not to use Destroy. 无论如何,最好不要使用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 ); 您最好使用gameObject.SetActive(true / false); for activating / deactivating the gameObject instead of just using Destroy. 用于激活/停用游戏对象,而不仅仅是使用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. 然后,如果您使用的是“销毁”,那么您会想到3种选择,以便在播放器看到之前将其置于所需位置。

1) You enable the game object after disabling its Renderer component. 1)在禁用游戏对象的渲染器组件后,可以启用它。 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. 2)您实例化gameObject,但首先要确保默认情况下在其Prefab上禁用了Renderer组件,因此您可以重新分配其Transform值,然后-再次重新启用Renderer。

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. 3)创建一个不可见的gameObject(一个Empty游戏对象)并实例化所需的gameObject,然后使Empty成为新创建的gameObject的父对象。只要父Empty恰好位于您想要的位置,当您实例化并重置孩子的位置,它应该在Empty父对象的顶部跳出。

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. 正如theodox所说,“对象池化”是子弹之类的最好朋友,尽管它可能会应用于许多其他游戏对象,这些对象可能会在游戏逻辑上充当“对象的集合”。 It's totally worth learning. 完全值得学习。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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