英文:
Instantiating and destroying unity prefabs
问题
我正在尝试在Unity中创建一个平台游戏,并且有一个随机生成的平台。我能够生成平台对象,但无法销毁它。
关于创建/销毁预制体的任何帮助将不胜感激。
public GameObject platform;
private Vector2 screenBounds;
void Start()
{
// 生成平台
Vector2 spawnPosition = new Vector2();
for (int i = 0; i < platformCount; i++)
{
spawnPosition.y = Random.Range(1f, 10f);
spawnPosition.x = Random.Range(-2.0f, 2.0f);
instance = Instantiate(platform, spawnPosition, Quaternion.identity);
}
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
}
void FixedUpdate()
{
if (instance != null)
{
if (platform.transform.position.y < screenBounds.y * 5)
{
Destroy(instance);
}
}
}
英文:
I am trying to create a platformer in unity and have a platform that randomly generates. I am able to get the platform object to spawn but cannot get it to be destroyed.
Any help on creating / destroying prefabs would be highly appreciated.
public GameObject platform;
private Vector2 screenBounds;
void Start()
{ // Spawn the platforms
Vector2 spawnPosition = new Vector2();
for ( int i=0; i < platformCount; i++)
{
spawnPosition.y = Random.Range(1f , 10f);
spawnPosition.x = Random.Range(-2.0f, 2.0f);
instance = Instantiate(platform, spawnPosition, Quaternion.identity);
}
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
}
void FixedUpdate()
{
if (instance != null)
{
if (platform.transform.position.y < screenBounds.y * 5)
{
Destroy(instance);
}
}
}
答案1
得分: 1
以下是代码部分的中文翻译:
主要问题已经在评论中提到:
instance = Instantiate(platform, spawnPosition, Quaternion.identity);
这在循环中被重新分配,所以最终只会保留最后一次迭代的实例。
在检查中,您正在使用原始的预制体:
if (platform.transform.position.y < screenBounds.y * 5)
这是从您实例化的资源中的预制体,所以在场景中当然不会移动。
我建议将这分为自己的脚本,例如:
public class Spawner : MonoBehaviour
{
[SerializeField] private OffScreenDestroy platformPrefab;
void Start()
{
for (int i = 0; i < platformCount; i++)
{
var spawnPosition = new Vector2(Random.Range(1f, 10f), Random.Range(-2.0f, 2.0f));
Instantiate(platformPrefab, spawnPosition, Quaternion.identity);
}
}
}
和
// 将这个附加到您的平台预制体
public class OffScreenDestroy : MonoBehaviour
{
private static Vector2? screenBounds;
private void FixedUpdate()
{
if (screenBounds == null) screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
if (transform.position.y < screenBounds.Value.y * 5)
{
Destroy(gameObject);
}
}
}
或者将它们保留在一个集合中,例如:
public class Spawner : MonoBehaviour
{
[SerializeField] private GameObject platformPrefab;
private readonly List<GameObject> instances = new();
private Vector2 screenBounds;
private void Start()
{
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
for (int i = 0; i < platformCount; i++)
{
var spawnPosition = new Vector2(Random.Range(1f, 10f), Random.Range(-2.0f, 2.0f));
instances.Add(Instantiate(platformPrefab, spawnPosition, Quaternion.identity));
}
}
private void FixedUpdate()
{
for (var i = instances.Count - 1; i >= 0; i--)
{
var instance = instances[i];
if (instance.transform.position.y < screenBounds.Value.y * 5)
{
Destroy(instance);
}
}
}
}
英文:
The main issue was already mentioned in the comments:
instance = Instantiate(platform, spawnPosition, Quaternion.identity);
this is re-assigned in a loop so it will only end up with the very last iteration's instance.
Further in your check you are using the original prefab
if (platform.transform.position.y < screenBounds.y * 5)
this is the prefab from the assets you instantiate so of course it never moves in the scene at all.
I would either split this into its very own script and do e.g.
public class Spawner : MonoBehaviour
{
[SerialzieField] private OffScreenDestroy platformPrefab;
void Start()
{
for ( int i=0; i < platformCount; i++)
{
var spawnPosition = new Vector2(Random.Range(1f , 10f), Random.Range(-2.0f, 2.0f));
Instantiate(platformPrefab, spawnPosition, Quaternion.identity);
}
}
}
and
// Attach this to your platform prefab
public class OffScreenDestroy : MonoBehaviour
{
private static Vector2? screenBounds;
private void FixedUpdate()
{
if(screenBounds == null) screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
if(transform.position.y < screenBounds.Value.y * 5)
{
Destroy(gameObject);
}
}
}
Or alternatively keep them in a collection and do e.g.
public class Spawner : MonoBehaviour
{
[SerializeField] private GameObject platformPrefab;
private readonly List<GameObject> instances = new();
private Vector2 screenBounds;
private void Start()
{
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
for ( int i=0; i < platformCount; i++)
{
var spawnPosition = new Vector2(Random.Range(1f , 10f), Random.Range(-2.0f, 2.0f));
instances.Add(Instantiate(platformPrefab, spawnPosition, Quaternion.identity));
}
}
private void FixedUpdate()
{
for(var i = instances.Count -1; i >= 0; i--)
{
var instance = instances[i];
if(instance.tranform.position.y < screenBounds.Value.y * 5)
{
Destroy(instance);
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论