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

如何通过ProjectContext重启场景并保留英雄状态(Zenject)

解决方案

1. 拆分绑定:全局状态与视图分离

把需要持久化的状态类(PlayerModel)和全局服务(PlayerInput)放在ProjectContext中绑定,确保状态跨场景保留;PlayerView如果需要跨场景存在,也要在ProjectContext中做单例绑定,避免重复实例化:

// 在ProjectContext的Install方法中实现
private void SetupPlayerGlobally()
{
    // 绑定全局状态模型,永久单例
    Container.Bind<PlayerModel>().AsSingle();
    // 全局输入服务
    Container.Bind<PlayerInput>().AsSingle();

    // 检查是否已有PlayerView实例,防止重复创建
    var existingPlayer = GameObject.FindObjectOfType<PlayerView>();
    if (existingPlayer == null)
    {
        var playerPrefab = Container.Resolve<ScriptableObjectService>().PlayerConfig.GetHeroValue().Player;
        existingPlayer = Container.InstantiatePrefabForComponent<PlayerView>(playerPrefab);
        // 标记为跨场景保留
        GameObject.DontDestroyOnLoad(existingPlayer.gameObject);
    }
    // 将PlayerView绑定为全局单例
    Container.Bind<PlayerView>().FromInstance(existingPlayer).AsSingle();

    // 绑定控制器,依赖全局的View、Model、Input
    Container.BindInterfacesAndSelfTo<PlayerController>().AsSingle();
}

2. 清理SceneContext中的重复绑定

彻底移除SceneContext中原有的PlayerBindings方法,所有需要访问Player相关对象的场景脚本,直接从ProjectContext的容器中引用:

// 在SceneContext的Install方法中
private void LinkGlobalPlayer()
{
    // 直接引用全局实例,无需重新绑定
    var playerModel = ProjectContext.Instance.Container.Resolve<PlayerModel>();
    // 示例:如果场景UI需要依赖PlayerModel,直接绑定全局实例
    Container.Bind<PlayerModel>().FromInstance(playerModel);
}

3. 场景重启时的状态重置逻辑

在PlayerModel中拆分全局状态和场景临时状态,重启场景时只重置临时状态,保留等级等全局数据:

// PlayerModel类
public class PlayerModel
{
    // 全局保留的状态
    public int Level { get; private set; }
    // 场景临时状态
    public int CurrentHealth { get; private set; }
    public int MaxHealth { get; private set; }

    // 重置场景相关状态的方法
    public void ResetSceneState()
    {
        CurrentHealth = MaxHealth;
        // 其他需要重置的临时状态(比如位置、buff等)
    }
}

// 在场景加载完成后调用(可放在SceneContext的PostInstall或场景初始化脚本中)
ProjectContext.Instance.Container.Resolve<PlayerModel>().ResetSceneState();

4. 避免冻结的核心注意事项

  • 禁止重复绑定:SceneContext中绝对不能再绑定ProjectContext已声明的Player相关类型,否则Zenject会抛出依赖冲突异常导致游戏冻结。
  • 清理场景关联:如果PlayerView绑定了场景内的触发器、UI事件,在场景卸载时要手动解绑事件,场景加载完成后重新关联,防止空引用或重复监听引发逻辑死循环。
  • 检查实例唯一性:确保PlayerView只会被实例化一次,通过FindObjectOfType或容器的HasBinding方法做前置检查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:50:03