-
似乎你正试图在任何碰撞中摧毁流星体。如果你也能检查一下流星体与实际宇宙飞船的碰撞,那就太好了。这现在可能没有必要,但如果任何两个流星体相互碰撞,或者与您稍后可能添加的其他游戏对象碰撞,可能会适得其反。
假设你的飞船有标签
Player
:
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player")
{
Debug.Log("collision");
Destroy(gameObject); // I want to destroy all meteoroids when spaceship dies
}
}
-
我想你是在摧毁离开游戏区域的流星体,这样它们就不会浪费资源。
-
你们的流星体不会一次全部被摧毁,因为每一个都有自己的例子
Meteoroid
脚本,每个脚本将分别运行自己的
OnCollisionEnter2D()
因此,如果流星体击中玩家,它只检查自己和另一个对撞机之间的碰撞。
如果你想一次摧毁所有的流星体,你必须以某种方式存储它们,然后在任何流星体之间发生碰撞时,调用某种方法,可以访问所有存储的流星体并一次摧毁它们。
你的
MeteoroidSpawn
现在上课似乎是一个很好的地方:
public class MeteoroidSpawn : MonoBehaviour
{
private List<Meteoroid> meteoroids; // Stores all currently spawned Meteoroids.
[SerializeField]
private GameObject meteoroidPrefab;
private bool spawn = true;
private void Start()
{
meteoroids = new List<Meteoroid>(); // Create and initialize the list.
StartCoroutine(SpawnRoutine());
}
IEnumerator SpawnRoutine()
{
Vector2 spawnPos = Vector2.zero;
while (spawn == true)
{
yield return new WaitForSeconds(1f);
// Spawn meteoroid
spawnPos.x = Random.Range(-Screen.width/40, Screen.width/40);
spawnPos.y = -Screen.height/40;
var meteor = Instantiate(meteoroidPrefab, spawnPos, Quaternion.identity);
// Add new meteoroid to the list.
meteoroids.Add(meteor.GetComponent<Meteoroid>());
}
}
}
现在你已经参考了所有繁殖的流星体,你可以用任何你喜欢的方式摧毁它们,即在
MeteoroidSpawn.cs
它会摧毁流星体,并在碰撞时称之为Meteoroid.cs(记住,你也必须
使
List<Meteoroid>
静止的
).
这样的代码可能看起来像这样(
MeteoroidSpawn.cs
):
public static void DestroyAllMeteoroids()
{
foreach (var meteoroid in meteoroids)
Destroy(meteoroid.gameObject);
}
可以这样称呼(
Meteoroid.cs
):
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player")
{
Debug.Log("collision");
MeteoroidSpawn.DestroyAllMeoroids();
}
}
事件方法
另一种方法是使用事件。Unity提供了自己的事件系统(
UnityEvent
)但我个人更喜欢用普通的
C# events
对于像这样轻的工作:
Meteoroid.cs
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Meteoroid : MonoBehaviour
{
public event EventHandler OnSpaceshipHit;
[SerializeField]
private GameObject spaceship;
[SerializeField]
private float speed = 1.0f;
[SerializeField]
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb = this.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
transform.position = Vector2.MoveTowards(transform.position, spaceship.transform.position, speed * Time.deltaTime);
transform.up = spaceship.transform.position - transform.position;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player")
{
Debug.Log("collision");
OnSpaceshipHit?.Invoke(this, null); // Raise event.
}
}
}
在里面
MeteoroidSpawn.cs
:
private List<Meteoroid> meteoroids; // Stores all currently spawned Meteoroids.
private void Start()
{
meteoroids = new List<Meteoroid>(); // Create and initialize the list.
StartCoroutine(SpawnRoutine());
}
// Rest of the code.
IEnumerator SpawnRoutine()
{
Vector2 spawnPos = Vector2.zero;
while (spawn == true)
{
yield return new WaitForSeconds(1f);
// Spawn meteoroid
spawnPos.x = Random.Range(-Screen.width/40, Screen.width/40);
spawnPos.y = -Screen.height/40;
Meteoroid meteor = Instantiate(meteoroidPrefab, spawnPos, Quaternion.identity).GetComponent<Meteoroid>();
meteor.OnSpaceshipHit += DestroyAllMeteoroids; // Subscribe to the event.
// Add new meteoroid to the list.
meteoroids.Add(meteor);
}
}
private void DestroyAllMeteoroids(object sender, EventArgs e)
{
foreach (var meteoroid in meteoroids)
Destroy(meteoroid.gameObject);
}
使用此设置,您可以订阅
OnSpaceshipHit
每个新流星体的事件。现在,每个流星体都有办法让房主知道它击中了玩家。如果发生这种情况,将引发一个事件,并且
DestroyAllMeteoroids()
方法被称为,在这个过程中摧毁所有流星体。不需要静态方法或变量。也没有必要取消订阅该事件,因为你在碰撞发生的同一帧破坏游戏对象。
如果您需要进一步解释代码,请告诉我。