【问题标题】:Instantiate creates multiple clones in Unity实例化在 Unity 中创建多个克隆
【发布时间】:2017-07-10 19:41:02
【问题描述】:

我有以下代码:

public Rigidbody2D ball;
Vector2 sp = new Vector2(0f, 2.1f);

void Update() {
    if (Input.GetKeyDown("w")) {
        SpawnBall();           
        DestroyBall();
    }
}
void SpawnBall()
{
    Instantiate(ball, sp, transform.rotation);
}

void DestroyBall()
{
    if (ball.transform.position.y >= -5.7f)
    {
        Destroy(ball);
    }
}

并且代码应该在每次按下“w”时生成一个新球,但由于某种原因它会创建多个克隆并且它会使引擎崩溃。如何只创建一个克隆?

destroy 方法也不做任何事情,尽管它应该在 y 轴上通过 -5.7 时删除克隆。

提前致谢

【问题讨论】:

    标签: c# unity3d game-physics


    【解决方案1】:

    创建一个名为“SpawnRigidbody”的新脚本并复制并粘贴以下代码。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SpawnRigidbody : MonoBehaviour 
    {
    
        public Rigidbody2D ball;
        Vector2 sp = new Vector2(0f, 2.1f);
    
        void Update() 
        {
            if (Input.GetKeyDown("w")) {
                SpawnBall();
            }
        }
    
        void SpawnBall()
        {
            Debug.Log ("spawn");
            GameObject go = Instantiate(ball, sp, transform.rotation).gameObject;
            go.AddComponent<DestroyAfterPosition> ();
        }
    }
    

    现在创建另一个名为“DestroyAfterPosition”的脚本并复制并粘贴以下代码。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class DestroyAfterPosition : MonoBehaviour 
    {
    
        void Update ()
        {
            if (transform.position.y <= -5.7f)
            {
                Destroy(gameObject);
            }
        }
    }
    

    创建一个空的游戏对象并附加 SpawnRigidbody,然后在检查器中分配您的球。

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      您的Destroy() 声明存在一些问题。首先,它正在破坏ball,即Rigidbody2D。相反,您会想要销毁附加到球上的游戏对象:
      Destroy(ball.gameObject);

      其次,您试图在创建球后立即将其销毁,但前提是y&gt;=-5.7f。相反,我认为您要做的是不断检查球是否高于该点,如果是则将其销毁。由于您要创建多个球,因此它们都需要自己检查,这意味着您需要为球预制件创建脚本并在 Update() 中检查其位置并根据需要进行 Destroy(gameObject)。

      我认为您可能还想在脚本的开头将球声明为 GameObject,因此您正在实例化一个游戏对象而不仅仅是一个 Rigidbody2D:
      public GameObject ball;

      【讨论】:

      • 我试过了,还是一样。我得到了无限数量的克隆,它们并没有被破坏。
      • 我已经更新了我的答案 - 请检查一下,以及 Joe Sewell 的答案,如果这能让你知道的话,请告诉我。
      【解决方案3】:

      Object.Instantiate 创建所提供对象的克隆,因此每次调用它时都会创建一个新对象。 MonoBehaviour.Update 每帧调用一次,这意味着每秒至少调用 30 次(通常在 PC 上调用 60 次或更多)。

      所以每秒 30 多次,您的代码会检查 w 键是否被按住,如果是的话:

      • 创建了ball 的克隆
      • 如果在 y 轴上超出 -5.7,则销毁原始 ball。

      因此,您每秒创建 30 多个球克隆,并且不会删除任何球(因为 DestroyBall 方法只查看原始球,而不是克隆)。

      如果您想使用克隆的对象,请将Instantiate 的结果分配给一个字段:

      ballClone = Instantiate(ball, sp, transform.rotation);
      

      然后您可以check if ballClone exists 并在克隆已经存在的情况下跳过SpawnBall 调用。您也可以在DestroyBall 方法中使用ballClone。

      ryemoss' answer 好像是 也很重要。这个答案只是基于查看您的代码和公共 Unity 文档;我对 Unity 没有太多经验。

      【讨论】:

        【解决方案4】:

        您的destroy 调用被调用一次,并且仅在创建对象后立即调用。

        所以它目前正在这样做......

        1. 用户点击按钮...
        2. 创建球...
        3. 检查球是否达到一定高度。不是,所以忽略...
        4. 球会根据重力或任何迫使它下落的力下落。

        ...并且永远不会被删除。

        如果你想让球在到达某个点时被摧毁,要么......

        1. 让 SpawnBall 返回游戏对象,您稍后在更新中存储并检查/删除它,

        ...或...

        1. 创建一个脚本,只检查对象的 transform.position 并在它需要的地方爆炸。将其附加到您正在创建副本的球的预制件上。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-20
          • 2011-04-12
          • 1970-01-01
          • 1970-01-01
          • 2021-07-23
          相关资源
          最近更新 更多