You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中设置DontDestroyOnLoad的玩家死亡后触发场景无限重载Bug

问题原因分析

玩家死亡后场景无限重复加载的核心问题有以下几点:

  • Update方法中每帧都会检查currentHealth <=0 && canDie,死亡协程启动后没有立即禁用canDie或标记死亡状态,导致每帧都重复触发死亡逻辑
  • 死亡后直接加载场景,但没有重置玩家生命值,场景加载完成后玩家生命值仍为0,再次触发死亡检查
  • 重生逻辑没有正确衔接,既没有调用GameManager的重生方法重置玩家位置,也没有在场景加载完成后恢复玩家状态
  • GameManager仅在初始启动时查找RespawnPoint,场景切换后无法获取新场景中的重生点
修复方案

1. 修正玩家死亡逻辑,防止重复触发

在死亡协程启动前立即禁用canDie,避免Update持续触发;场景加载完成后通过GameManager处理重生,而不是直接加载场景后无操作。

2. 调整场景加载后的重生流程

使用SceneManager.sceneLoaded监听场景加载完成事件,在场景加载后调用GameManager的重生方法,重置玩家位置和生命值。

3. 修复GameManager的重生点获取逻辑

在场景加载完成后重新查找当前场景的RespawnPoint,而不是仅在初始Awake中查找。

4. 完善重生状态重置

确保重生时不仅恢复生命值,还要重新启用canDie并清除死亡标记。

修改后的代码

玩家生命值与重生代码(BasicPlayerMovement)

public int maxHealth = 5;
public float timeInvincible = 2.0f;

public int health { get { return currentHealth; } }
int currentHealth;

bool isInvincible;
float invincibleTimer;

public int respawn;
public bool canDie = true;
private bool isDead = false;
UIManager uiManager;

public static BasicPlayerMovement Instance;

private void Awake()
{
    // 防止玩家对象重复创建
    if(Instance != null && Instance != this)
    {
        Destroy(gameObject);
    }
    else
    {
        Instance = this;
    }
    DontDestroyOnLoad(gameObject);
    // 监听场景加载完成事件
    SceneManager.sceneLoaded += OnSceneLoaded;
}

void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
    // 场景加载完成后,如果处于死亡状态,触发重生
    if(isDead)
    {
        GameManager.instance.RespawnPlayer();
    }
}

// Start is called before the first frame update
void Start()
{
    currentHealth = maxHealth;
}

void Update()
{
    if (isInvincible)
    {
        invincibleTimer -= Time.deltaTime;
        if (invincibleTimer < 0)
            isInvincible = false;
    }

    if ((currentHealth <= 0) && (canDie == true))
    {
        StartCoroutine(PlayerDeath());
    }
}

public void ChangeHealth(int amount)
{
    if (amount < 0)
    {
        if (isInvincible)
            return;

        isInvincible = true;
        invincibleTimer = timeInvincible;
    }
    currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
    Debug.Log(currentHealth + "/" + maxHealth);
}

private IEnumerator PlayerDeath()
{
    isDead = true;
    canDie = false; // 禁用死亡触发,防止重复调用
    Time.timeScale = 1f;
    
    // 加载重生场景
    yield return SceneManager.LoadSceneAsync(respawn);
    
    // 场景加载完成后OnSceneLoaded会触发重生
}

public void Respawned()
{
    isDead = false;
    canDie = true; // 重新启用死亡触发
    currentHealth = maxHealth;
}

游戏管理器代码(GameManager)

public class GameManager : MonoBehaviour
{
    public string transitionedFromScene;
    public Vector2 respawnPoint;
    public Vector2 platformingRespawnPoint;
    [SerializeField] RespawnPoint rP;

    public static GameManager instance { get; private set; }

    private void Awake()
    {
        if(instance != null && instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
        }
        DontDestroyOnLoad(gameObject);
        // 监听场景加载完成事件,重新获取当前场景的重生点
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // 场景切换后重新查找当前场景的重生点
        rP = FindObjectOfType<RespawnPoint>();
    }

    public void RespawnPlayer()
    {
        if(rP != null && rP.interacted)
        {
            respawnPoint = rP.transform.position;
        }
        else
        {
            respawnPoint = platformingRespawnPoint;
        }

        BasicPlayerMovement.Instance.transform.position = respawnPoint;
        BasicPlayerMovement.Instance.Respawned();
    }
}

重生点代码(RespawnPoint)

public class RespawnPoint : MonoBehaviour
{
    public bool interacted;

    private void OnTriggerStay2D(Collider2D collision)
    {
        if(collision.CompareTag("Player") && Input.GetKeyDown(KeyCode.Z))
        {
            interacted = true;
            // 可添加交互反馈,比如音效或提示
        }
    }
}
额外说明
  • 使用LoadSceneAsync代替同步加载,避免场景加载时卡顿,同时确保协程等待加载完成后再处理后续逻辑
  • 通过SceneManager.sceneLoaded统一处理场景切换后的重生和重生点查找逻辑,保证状态同步
  • 死亡时立即禁用canDie,从根源上避免Update循环触发死亡协程

内容的提问来源于stack exchange,提问作者Knackered7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:45:01