当 Unity 中的生命被移除时,游戏会冻结 [重复]
Posted
技术标签:
【中文标题】当 Unity 中的生命被移除时,游戏会冻结 [重复]【英文标题】:Game Freezes When Ever Lives Get Removed In Unity [duplicate] 【发布时间】:2021-11-15 04:06:25 【问题描述】:每当我的游戏中的敌人在团结中夺走生命时,游戏就会暂时冻结。我认为这与“Thread.Sleep(3000);”行有关但我不确定是否有一个不会暂时冻结整个游戏的替代等待。 如果您能帮助我,我将不胜感激!
谢谢。
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading;
using UnityEngine;
public class Enemy : MonoBehaviour
public Transform attackPoint;
public float attackrange = 0.5f;
public LayerMask playerlayers;
public float speed = 3f;
private Transform target;
bool hitID = false;
private void Update()
if (target != null)
float step = speed * Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, target.position, step);
Collider2D[] hitplayers = Physics2D.OverlapCircleAll(attackPoint.position, attackrange, playerlayers);
foreach (Collider2D player in hitplayers)
if (hitID == false)
hitID = true;
player.GetComponent<HeartSystem>().TakeDamage(1);
Thread.Sleep(3000);
hitID = false;
private void OnTriggerEnter2D(Collider2D other)
if (other.gameObject.tag == "Player")
target = other.transform;
private void OnTriggerExit2D(Collider2D other)
if (other.gameObject.tag == "Player")
target = null;
void OnDrawGizmosSelected()
if (attackPoint == null)
return;
Gizmos.DrawWireSphere(attackPoint.position, attackrange);
【问题讨论】:
【参考方案1】:Enemy.cs
using System.Collections;
using UnityEngine;
public class Enemy : MonoBehaviour
public Transform attackPoint;
public float attackrange = 0.5f;
public LayerMask playerlayers;
public float speed = 3f;
private Transform _target;
private bool _hitID;
private void Update()
if (_target != null)
var step = speed * Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, _target.position, step);
var hitPlayers = new Collider2D[10];
Physics2D.OverlapCircleNonAlloc(attackPoint.position, attackrange, hitPlayers, playerlayers);
foreach (var player in hitPlayers)
if (_hitID == false)
StartCoroutine(HitCoroutine(player));
private IEnumerator HitCoroutine(Collider2D player)
_hitID = true;
player.GetComponent<HeartSystem>().TakeDamage(1);
yield return new WaitForSeconds(3);
_hitID = false;
private void OnTriggerEnter2D(Collider2D other)
if (other.gameObject.CompareTag("Player"))
_target = other.transform;
private void OnTriggerExit2D(Collider2D other)
if (other.gameObject.CompareTag("Player"))
_target = null;
private void OnDrawGizmosSelected()
if (attackPoint == null)
return;
Gizmos.DrawWireSphere(attackPoint.position, attackrange);
试试这个。
在这种情况下,您想使用协程。
您可以在此处阅读有关协程的信息: https://docs.unity3d.com/Manual/Coroutines.html
【讨论】:
【参考方案2】:Unity 是单线程的,因此您实际上是在暂停运行游戏的整个线程。由于帧是在这个线程上更新的,你甚至会冻结视觉帧更新。
您有几种方法可以管理游戏中的“等待”。
协程:
可以暂停的进程,直到满足以后的条件(包括时间)
void Update()
//Your other code goes here
if (hitID == false)
hitID = true;
player.GetComponent<HeartSystem>().TakeDamage(1);
StartCoroutine(ResetHitIDAfterSeconds(3))
IEnumerator ResetHitIDAfterSeconds(float seconds)
yield return new WaitForSeconds(seconds);
hitID = false;
上面的代码允许你有同样的逻辑,并且会启动一个协程,等待 3 秒再将 hitID 设置回 false。
时间.deltaTime:
您还可以在 Update 方法中跟踪经过的时间,并根据经过的时间主动管理变量。 Time.deltaTime 返回自上一帧以来经过的时间量。
public class ConstantRotation : MonoBehaviour
public float timeElapsed = 0f;
void Update()
//Your other code goes here
if (hitID == false)
hitID = true;
player.GetComponent<HeartSystem>().TakeDamage(1);
timeElapsed = 0f;
else
timeElapsed += Time.deltaTime
if(timeElapsed >= 3.0f)
hitId = false;
您可能希望稍微修改上述代码以避免在每一帧上运行逻辑,并且只在命中时运行它。
【讨论】:
以上是关于当 Unity 中的生命被移除时,游戏会冻结 [重复]的主要内容,如果未能解决你的问题,请参考以下文章