GameObject 算作已销毁但并未真正销毁
GameObject counted as destroyed but not really destroyed
我目前正在制作 Breakout 风格的游戏,当游戏中的球超过 5 或 6 个时,我会遇到破坏砖块的问题(没有可靠的数字可以重现此错误,它只会在有很多球时发生比赛中的球)。有双球和三球能量提升,因此球的数量可以在短时间内迅速增加。
在我的 GameManager 脚本中,我在场景开始时跟踪初始砖块数量,并在每次球与砖块接触时减去 1。积木数为零后,玩家获胜,游戏结束。该游戏适用于少量球,但是当涉及太多球时,该过程似乎会中断。
GameManager.cs的相关代码:
void Start()
{
livesText.text = "Lives: " + Lives;
numOfBalls = GameObject.FindGameObjectsWithTag("Ball").Length;
numOfBricks = GameObject.FindGameObjectsWithTag("Brick").Length;
//Debug.Log(numOfBalls);
}
public void UpdateBrickNumber()
{
numOfBricks--;
if(numOfBricks <= 0)
{
numOfBricks = 0;
GameOver();
}
}
void GameOver()
{
gameOver = true;
if(numOfBricks == 0)
{
WinPanel.SetActive(true);
}
else
{
GameOverPanel.SetActive(true);
}
}
...
处理碰撞的球代码:
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.transform.CompareTag("Brick"))
{
Debug.Log("Brick Hit");
//Chance of powerup to spawn
int rand = Random.Range(1, 101);
//Chance of each power up
int rand2 = Random.Range(1, 101);
if (rand < 7)
{
if (rand2 >=1 && rand2<=20) {
Instantiate(SpeedBall, collision.transform.position, collision.transform.rotation);
//Debug.Log(" Speed Power Up Created ");
}
...
Rest of power ups
...
}
Transform newExplosion = Instantiate(explosion, collision.transform.position, collision.transform.rotation);
Destroy(newExplosion.gameObject, 2f);
gm.UpdateBrickNumber();
Destroy(collision.gameObject);
}
}
调试日志确实显示了正确数量的砖块被击中,但我认为有些球在有机会被摧毁之前就击中了同一块砖块。我怎样才能确保在另一个球撞到砖块上的对撞机之前砖块被摧毁?
实际错误:
消除了你在一个框架中遇到多次碰撞的预感,导致砖块数量低于剩余砖块数量,这应该可以解决这个问题:
void OnCollisionEnter2D(Collision2D collision)
{ //Check if the brick has already been processed
if (collision.transform.CompareTag("Brick") && collision.collider.enabled)
{
Debug.Log("Brick Hit");
//Chance of powerup to spawn
int rand = Random.Range(1, 101);
//Chance of each power up
int rand2 = Random.Range(1, 101);
if (rand < 7)
{
if (rand2 >=1 && rand2<=20) {
Instantiate(SpeedBall, collision.transform.position, collision.transform.rotation);
//Debug.Log(" Speed Power Up Created ");
}
...
Rest of power ups
...
}
Transform newExplosion = Instantiate(explosion, collision.transform.position, collision.transform.rotation);
Destroy(newExplosion.gameObject, 2f);
gm.UpdateBrickNumber();
//Mark the brick as hit already so other balls can't hit it!
collision.collider.enabled = false;
Destroy(collision.gameObject);
}
}
说明
Actual object destruction is always delayed until after the current Update loop, but will always be done before rendering.
Destroy
不是即时的。它将在更新循环之后发生,这意味着如果两个球在同一帧中击中,您的计数将减少 2,但只会摧毁一块砖。
快速简短回答
在 C# 和 Java 中,对象不会被销毁 right-away,它们会放入要删除的进程中,有时会立即发生,有时不会。
有时,其他对象仍然引用它们。解决方案是删除之前的那些引用。
void OnCollisionEnter2D(Collision2D collision)
{
...
Transform newExplosion = Instantiate(explosion, collision.transform.position, collision.transform.rotation);
// notify other objects that reference "newExplosion.gameObject"
Destroy(newExplosion.gameObject, 2f);
newExplosion.gameObject = null;
gm.UpdateBrickNumber();
// notify other objects that reference "collision.gameObject"
Destroy(collision.gameObject);
collision.gameObject = null;
...
} // void OnCollisionEnter2D(...)
干杯。
我目前正在制作 Breakout 风格的游戏,当游戏中的球超过 5 或 6 个时,我会遇到破坏砖块的问题(没有可靠的数字可以重现此错误,它只会在有很多球时发生比赛中的球)。有双球和三球能量提升,因此球的数量可以在短时间内迅速增加。
在我的 GameManager 脚本中,我在场景开始时跟踪初始砖块数量,并在每次球与砖块接触时减去 1。积木数为零后,玩家获胜,游戏结束。该游戏适用于少量球,但是当涉及太多球时,该过程似乎会中断。
GameManager.cs的相关代码:
void Start()
{
livesText.text = "Lives: " + Lives;
numOfBalls = GameObject.FindGameObjectsWithTag("Ball").Length;
numOfBricks = GameObject.FindGameObjectsWithTag("Brick").Length;
//Debug.Log(numOfBalls);
}
public void UpdateBrickNumber()
{
numOfBricks--;
if(numOfBricks <= 0)
{
numOfBricks = 0;
GameOver();
}
}
void GameOver()
{
gameOver = true;
if(numOfBricks == 0)
{
WinPanel.SetActive(true);
}
else
{
GameOverPanel.SetActive(true);
}
}
...
处理碰撞的球代码:
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.transform.CompareTag("Brick"))
{
Debug.Log("Brick Hit");
//Chance of powerup to spawn
int rand = Random.Range(1, 101);
//Chance of each power up
int rand2 = Random.Range(1, 101);
if (rand < 7)
{
if (rand2 >=1 && rand2<=20) {
Instantiate(SpeedBall, collision.transform.position, collision.transform.rotation);
//Debug.Log(" Speed Power Up Created ");
}
...
Rest of power ups
...
}
Transform newExplosion = Instantiate(explosion, collision.transform.position, collision.transform.rotation);
Destroy(newExplosion.gameObject, 2f);
gm.UpdateBrickNumber();
Destroy(collision.gameObject);
}
}
调试日志确实显示了正确数量的砖块被击中,但我认为有些球在有机会被摧毁之前就击中了同一块砖块。我怎样才能确保在另一个球撞到砖块上的对撞机之前砖块被摧毁?
实际错误:
消除了你在一个框架中遇到多次碰撞的预感,导致砖块数量低于剩余砖块数量,这应该可以解决这个问题:
void OnCollisionEnter2D(Collision2D collision)
{ //Check if the brick has already been processed
if (collision.transform.CompareTag("Brick") && collision.collider.enabled)
{
Debug.Log("Brick Hit");
//Chance of powerup to spawn
int rand = Random.Range(1, 101);
//Chance of each power up
int rand2 = Random.Range(1, 101);
if (rand < 7)
{
if (rand2 >=1 && rand2<=20) {
Instantiate(SpeedBall, collision.transform.position, collision.transform.rotation);
//Debug.Log(" Speed Power Up Created ");
}
...
Rest of power ups
...
}
Transform newExplosion = Instantiate(explosion, collision.transform.position, collision.transform.rotation);
Destroy(newExplosion.gameObject, 2f);
gm.UpdateBrickNumber();
//Mark the brick as hit already so other balls can't hit it!
collision.collider.enabled = false;
Destroy(collision.gameObject);
}
}
说明
Actual object destruction is always delayed until after the current Update loop, but will always be done before rendering.
Destroy
不是即时的。它将在更新循环之后发生,这意味着如果两个球在同一帧中击中,您的计数将减少 2,但只会摧毁一块砖。
快速简短回答
在 C# 和 Java 中,对象不会被销毁 right-away,它们会放入要删除的进程中,有时会立即发生,有时不会。
有时,其他对象仍然引用它们。解决方案是删除之前的那些引用。
void OnCollisionEnter2D(Collision2D collision)
{
...
Transform newExplosion = Instantiate(explosion, collision.transform.position, collision.transform.rotation);
// notify other objects that reference "newExplosion.gameObject"
Destroy(newExplosion.gameObject, 2f);
newExplosion.gameObject = null;
gm.UpdateBrickNumber();
// notify other objects that reference "collision.gameObject"
Destroy(collision.gameObject);
collision.gameObject = null;
...
} // void OnCollisionEnter2D(...)
干杯。