Instantiate在Unity中创建多个克隆
Instantiate creates multiple clones in Unity
我有以下代码:
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 时删除克隆。
提前致谢
您的 Destroy()
声明有几个问题。首先,它正在破坏 ball
,即 Rigidbody2D
。相反,您想要销毁附在球上的游戏对象:
Destroy(ball.gameObject);
其次,您试图在创建球后立即将其销毁,但前提是 y>=-5.7f
。我认为相反,您要做的是不断检查球是否高于该点,如果高于则将其摧毁。由于您正在创建多个球,因此它们都需要自己检查,这意味着您需要为球预制件创建一个脚本,并在 Update()
中检查其位置并根据需要销毁(游戏对象)。
我认为您可能还想在脚本开头将 ball 声明为游戏对象,因此您正在实例化游戏对象而不仅仅是 Rigidbody2D:
public GameObject ball;
Object.Instantiate
creates a clone of the provided object, so each time it is called a new object is created. MonoBehaviour.Update
每帧调用一次,这意味着它每秒至少调用 30 次(在 PC 上通常为 60 次或更多)。
所以每秒 30 次以上,您的代码会检查 w
键是否被按下,如果是:
- 创建了
ball
的克隆
- 破坏原来的
ball
如果y轴超过-5.7
因此,您每秒创建 30 多个球克隆,并且 none 将被删除(因为 DestroyBall
方法只查看原始球,而不查看克隆)。
如果要使用克隆的对象,请将 Instantiate
的结果分配给一个字段:
ballClone = Instantiate(ball, sp, transform.rotation);
然后您可以 check if ballClone
exists 并跳过 SpawnBall
调用(如果克隆已存在)。您也可以在 DestroyBall
方法中使用 ballClone
。
好像是
也很重要。这个答案只是基于查看您的代码和 public Unity 文档;我没有很多 Unity 经验。
创建一个名为 "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,然后在检查器中分配你的球。
希望对您有所帮助。
您的销毁调用仅在创建对象后立即被调用一次。
所以它目前正在这样做...
- 用户点击按钮...
- 创建球...
- 检查球是否达到一定高度。不是,所以忽略...
- 球会根据重力或任何迫使它下落的力下落。
...并且永远不会被删除。
如果你想让球在到达某个点时被摧毁,要么...
- 拥有 SpawnBall return 游戏对象,稍后您可以在更新中存储和检查/删除它,
...或...
- 创建一个脚本,只检查对象的 transform.position 并在需要的地方爆炸。将其附加到您正在创建副本的球的预制件上。
我有以下代码:
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 时删除克隆。
提前致谢
您的 Destroy()
声明有几个问题。首先,它正在破坏 ball
,即 Rigidbody2D
。相反,您想要销毁附在球上的游戏对象:
Destroy(ball.gameObject);
其次,您试图在创建球后立即将其销毁,但前提是 y>=-5.7f
。我认为相反,您要做的是不断检查球是否高于该点,如果高于则将其摧毁。由于您正在创建多个球,因此它们都需要自己检查,这意味着您需要为球预制件创建一个脚本,并在 Update()
中检查其位置并根据需要销毁(游戏对象)。
我认为您可能还想在脚本开头将 ball 声明为游戏对象,因此您正在实例化游戏对象而不仅仅是 Rigidbody2D:
public GameObject ball;
Object.Instantiate
creates a clone of the provided object, so each time it is called a new object is created. MonoBehaviour.Update
每帧调用一次,这意味着它每秒至少调用 30 次(在 PC 上通常为 60 次或更多)。
所以每秒 30 次以上,您的代码会检查 w
键是否被按下,如果是:
- 创建了
ball
的克隆 - 破坏原来的
ball
如果y轴超过-5.7
因此,您每秒创建 30 多个球克隆,并且 none 将被删除(因为 DestroyBall
方法只查看原始球,而不查看克隆)。
如果要使用克隆的对象,请将 Instantiate
的结果分配给一个字段:
ballClone = Instantiate(ball, sp, transform.rotation);
然后您可以 check if ballClone
exists 并跳过 SpawnBall
调用(如果克隆已存在)。您也可以在 DestroyBall
方法中使用 ballClone
。
创建一个名为 "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,然后在检查器中分配你的球。
希望对您有所帮助。
您的销毁调用仅在创建对象后立即被调用一次。
所以它目前正在这样做...
- 用户点击按钮...
- 创建球...
- 检查球是否达到一定高度。不是,所以忽略...
- 球会根据重力或任何迫使它下落的力下落。
...并且永远不会被删除。
如果你想让球在到达某个点时被摧毁,要么...
- 拥有 SpawnBall return 游戏对象,稍后您可以在更新中存储和检查/删除它,
...或...
- 创建一个脚本,只检查对象的 transform.position 并在需要的地方爆炸。将其附加到您正在创建副本的球的预制件上。