using cfg.LevelCfg; using System.Collections.Generic; using Code.Scripts.Gameplay.Utils; using Cysharp.Threading.Tasks; using Framework; using Gameplay.AI; using Gameplay.Area; using Gameplay.BT.Variables; using Gameplay.Buff; using Gameplay.Character; using Gameplay.Effect; using Gameplay.Emoji; using Gameplay.Fight.Capture; using Gameplay.Fight.Flag; using Gameplay.Pause; using Gameplay.Performance; using Gameplay.Pool; using Gameplay.PostProcess.BlackArea; using Gameplay.Skill; using Gameplay.SubSystems; using Gameplay.Unit; using Gameplay.Unit.Data; using Gameplay.Vehicle; using PhxhSDK; using UnityEngine; using Constants = Framework.Constants; namespace Gameplay.Level { public partial class Level : IUpdatable, ILoadable { private const string AIBehavior = "AIBehavior"; private int _id; private LevelData _levelData; private LevelInfo _currLevelInfo; private Map _map; private StateMachine _stateMachine = new StateMachine(); public bool isInBattle = false; private object _param; public int ID => _id; public Map Map => _map; public float LevelTime { set; get; } public bool IsPvPLevel => _id == TableManager.Instance.Tables.GlobalConfig.PVPLevelID; public Level(int leveId, object param = null) { _id = leveId; _param = param; Init(); } private Dictionary _configLevelDic = new Dictionary(); public Dictionary ConfigLevelDic => _configLevelDic; private void LoadConfigLevel() { _currLevelInfo = LevelManager.Instance.GetLevelInfoByID(_id); } private async UniTask LoadScene() { await GameSceneManager.Instance.LoadSceneAsync(_currLevelInfo.LevelScene); await AssetManager.Instance.LoadAndInstAsync(CmpAreaColorSettings.ASSET_PATH); } private async UniTask UnLoadScene() { await GameSceneManager.Instance.UnLoadSceneAsync(_currLevelInfo.LevelScene); AssetManager.Instance.Unload(CmpAreaColorSettings.ASSET_PATH); } private void LoadData() { _levelData = _currLevelInfo.LevelData; } private async UniTask LoadMap() { // if (_levelData != null) // { // if (_map != null) // { // MapUtils.RemoveCameraController(CameraManager.Instance.MainCamera); // MapUtils.UnLoadMap(_map); // } _map = await MapUtils.LoadMap(_currLevelInfo.MapData); //NLDSceneManager.Instance.SceneCamera.gameObject.SetActive(false); var sceneCamera = NLDSceneManager.Instance.SceneCamera; // Debug.LogError(sceneCamera.scene + " " + sceneCamera.name); CameraManager.Instance.SwitchMainCamera(sceneCamera); MapUtils.BindCameraController(NLDSceneManager.Instance.SceneCamera, _map); //MapUtils.BindCameraController(CameraManager.Instance.MainCamera, _map); //} } private async UniTask _LoadNpc() { if (!IsPvPLevel) { await _LoadEnemyFromLevelData(); await _LoadBeProtectFromLevelData(); } else { await _LoadNPCFromPVPData(); } } private async UniTask _LoadBeProtectFromLevelData() { if (_levelData == null) return; var infos = _levelData.protectUnitInfos; for (int i = 0; i < infos.Count; i++) { var info = infos[i]; var createUnit = await GameUnitManager.instance.PrepareBeProtectUnit(info.id); if (createUnit == null) { DebugUtil.LogError("创建护送对象失败"); return; } createUnit.transData.bornCellIndex = info.protectStartPoint; GameUnitManager.instance.MoveUnitToFight(createUnit.GetID(), info.protectStartPoint, 0); createUnit.CreateTargetPoint(info.protectTargetPoint); } } private async UniTask _LoadEnemyFromLevelData() { if (_levelData == null) return; if (_map == null) return; for (var i = 0; i < _levelData.npcInfos.Count; i++) { var npcInfo = _levelData.npcInfos[i]; // TODO: LT:临时处理,后续需要根据配置来 var teamId = ETroopsId.Enemy1; var cellIndex = _map.BlockPosition2TGSCellIndex(npcInfo.position); var yaw = LevelUtils.SetCharaterToward(npcInfo.npcToward); var npcCharacter = await GameUnitManager.instance.PrepareNpc(npcInfo, teamId); if (npcCharacter == null) { DebugUtil.LogError("创建npc失败"); continue; } npcCharacter.runtimeData.characterLevelData = new CharacterLevelData() { AttachAIName = npcInfo.attachAIType, AIName = npcInfo.aIType, BornPosition = npcInfo.position, NpcToward = npcInfo.npcToward, PatrolInfos = npcInfo.patrolInfos, GroupInfos = npcInfo.groups, }; npcCharacter.transData.bornCellIndex = cellIndex; GameUnitManager.instance.MoveUnitToFight(npcCharacter.GetID(), cellIndex, yaw); } } private async UniTask _LoadNPCFromPVPData() { var pvpDefenderData = _param as PVPDefenderData; if (pvpDefenderData == null) { DebugUtil.LogError("pvp参数不合法!"); return; } for (var i = 0; i < pvpDefenderData.pvpRuntimeUnitInfos.Count; i++) { var pvpUnitData = pvpDefenderData.pvpRuntimeUnitInfos[i]; //var id = (uint)pvpUnitData.unitID; var position = _map.TGSCellIndex2BlockPosition(pvpUnitData.cellIndex); var teamId = ETroopsId.Enemy1; GameUnit unit = null; switch (pvpUnitData.type) { case Framework.Wrapper.Unit.UnitType.Charactor: var cInfo = new CharacterDataInfo(); cInfo.Refresh(pvpUnitData.characterInfo); unit = await GameUnitManager.instance.PrepareCharacter(cInfo, teamId); var character = (Character.Character)unit; character.runtimeData.characterLevelData = new CharacterLevelData() { AttachAIName = pvpUnitData.attachAIType, AIName = pvpUnitData.aiType, BornPosition = position, NpcToward = _levelData.pvpDefendToward, PatrolInfos = new(), GroupInfos = new (), }; break; case Framework.Wrapper.Unit.UnitType.Vehicle: //todo VehicleCultivateData第二个参数 var vInfo = new VehicleCultivateData(); vInfo.Refresh(pvpUnitData.vehicleInfo); unit = await GameUnitManager.instance.PrepareVehicle(vInfo, teamId); break; default: break; } if (unit == null) { DebugUtil.LogError("创建pvp unit失败"); continue; } var yaw = LevelUtils.SetCharaterToward(_levelData.pvpDefendToward); GameUnitManager.instance.MoveUnitToFight(unit.GetID(), pvpUnitData.cellIndex, yaw); } } // public void BindMap(Map map) // { // if (map != null) // { // _map = map; // } // // if (_map.MapData.name.Equals(_levelData.mapName)) // { // DebugUtil.LogError("{0}.{1} Error:map name not match", GetType(), // System.Reflection.MethodBase.GetCurrentMethod()?.Name); // } // } public void Update(float deltaTime) { if (!_isPause) { _stateMachine.Update(deltaTime * _speed); // GameUnitManager.instance.LogicUpdate(deltaTime * _speed); AIManager.Instance.Update(deltaTime * _speed); SelecterView.Instance.Update(deltaTime * _speed); } } /// /// 这里是 level system的初始化,不是 level 场景的初始化 /// public void Init() { AIManager.Instance.Init(); GameUnitManager.CreateInstance(); SkillManager.CreateInstance(); BuffManager.CreateInstance(); EmojiManager.CreateInstance(); } public void Release() { AreaManager.instance.Dispose(); EmojiManager.inst.Dispose(); SkillManager.instance.Dispose(); BuffManager.instance.Dispose(); _stateMachine?.ChangeState(null); AIManager.Instance.Release(); CaptureManager.instance.Dispose(); FlagManager.instance.Dispose(); // 在这里释放所有单位 GameUnitManager.instance.Dispose(); if (PauseManager.instance != null) { PauseManager.instance.Dispose(); } EffectManager.instance.ClearPool(); ObjPoolManager.instance.Clear(); BlackAreaManager.instance.Dispose(); AssetManager.Instance.Unload(Constants.TIREMARK_UNIT_PATH); AssetManager.Instance.Unload(Constants.TIREMARK_MAT_PATH); AssetManager.Instance.Unload(Constants.CHARACTER_SELECT_GROUND_GFX); AssetManager.Instance.Unload(Constants.EMOJI_HEAD_MAT); AssetManager.Instance.Unload(Constants.SUMMON_BOTTOM_PATH_SELF); AssetManager.Instance.Unload(Constants.SUMMON_BOTTOM_PATH_ENEMY); AssetManager.Instance.Unload(Constants.SKILL_GORUND_HIGH_LIGHT); AssetManager.Instance.Unload(Constants.CHARACTER_TARGET_GFX); AssetManager.Instance.Unload(Constants.ROAD_LINE_PATH); AssetManager.Instance.Unload(Constants.CAPTURE_POINT_PATH); AssetManager.Instance.Unload(Constants.CAPTURE_FINISHED_POINT_PATH); AssetManager.Instance.Unload(Constants.FLAG_GROUND_PATH); AssetManager.Instance.Unload(Constants.FLAG_PICK_PATH); AssetManager.Instance.Unload(Constants.FLAG_RETURN_PATH); AssetManager.Instance.Unload(Constants.PROTECT_TARGET_POINT_PATH); AssetManager.Instance.Unload(Constants.FIGHT_LIGHT_AREA_PATH); AssetManager.Instance.Unload(Constants.FIGHT_CELL_COLLIDER_PATH); _UnloadOutlinePost(); _UnLoadWeather(); // 卸载关卡时强制隐藏技能相机 CameraManager.Instance.SkillCamera.gameObject.SetActive(false); } private void _UnloadOutlinePost() { AssetManager.Instance.Unload(Constants.SHADER_OUTLINE_PATH1); AssetManager.Instance.Unload(Constants.SHADER_OUTLINE_PATH1_1); AssetManager.Instance.Unload(Constants.SHADER_OUTLINE_PATH2); AssetManager.Instance.Unload(Constants.SHADER_OUTLINE_PATH3); AssetManager.Instance.Unload(Constants.OUTLINE_POSTPROCESS_PATH); } private void _UnLoadWeather() { var weatherType = (int)_currLevelInfo.WeatherType; var groundType = (int)_currLevelInfo.EnvironmentType; var weatherEffectConfig = TableManager.Instance.Tables.WeatherEffectConfig.Get(weatherType, groundType); if (weatherEffectConfig == null) { return; } var cameraPrefab = weatherEffectConfig.CameraPrefab; if (string.IsNullOrEmpty(cameraPrefab)) { return; } AssetManager.Instance.Unload(cameraPrefab); } public async UniTask Load() { LoadConfigLevel(); // GameUnitManager.instance.PrepareUnits(); //UIManager.Instance.CloseAllNormalExcept(UINameConst.UI_Loading); // 打开加载界面时已经移除 await LoadScene(); LoadData(); await LoadMap(); await _LoadWeather(); await _InitAfterLoadMap(); await _LoadOthers(); await _LoadNpc(); _CreateCapturePoints(); _CreateFlags(); _SetShadows(); RegisterAllEvent(); InitRules(); _stateMachine.ChangeState(new PrepareState(this)); SelecterView.Instance.Init(); BlackAreaManager.instance.Init(_currLevelInfo.DayNightType == LevelData.DayNightType.Night); InitAIStart(); } private async void InitAIStart() { var units = GameUnitManager.instance.infightUnits.unitList; foreach (var unit in units) { var character = unit as Character.Character; if (character == null) continue; if (character.troopId == ETroopsId.Self) { // 玩家默认激活 character.statusData.isAttackActive = true; return; } // AI 默认非激活 character.statusData.isAttackActive = false; var bt = await AIManager.Instance.RegisterAI(character.Node.GameObject, AIBehavior); bt.SetVariable("battleInfo", new SharedBattleInfo() { Value = new BattleInfo() { ownerId = character.GetID(), AIName = character.runtimeData.characterLevelData.AIName, AttachAIName = character.runtimeData.characterLevelData.AttachAIName, PatrolInfos = character.runtimeData.characterLevelData.PatrolInfos, groupInfo = character.runtimeData.characterLevelData.GroupInfos, } }); character.statusData.isAIControll = true; } } private void _CreateCapturePoints() { CaptureManager.CreateInstance(); CaptureManager.instance.Init(); } private void _CreateFlags() { FlagManager.CreateInstance(); FlagManager.instance.Init(); } private async UniTask _LoadWeather() { var weatherType = (int)_currLevelInfo.WeatherType; var groundType = (int)_currLevelInfo.EnvironmentType; var weatherEffectConfig = TableManager.Instance.Tables.WeatherEffectConfig.Get(weatherType, groundType); if (weatherEffectConfig == null) { return; } var cameraPrefab = weatherEffectConfig.CameraPrefab; if (string.IsNullOrEmpty(cameraPrefab)) { return; } var loadObj = await AssetManager.Instance.LoadAssetAsync(cameraPrefab); if (loadObj == null) { DebugUtil.LogError("加载天气特效失败:{0}", cameraPrefab); return; } var cameraObj = CameraManager.Instance.MainCamera.gameObject; var weatherCamera = Object.Instantiate(loadObj, cameraObj.transform); weatherCamera.transform.localPosition = Vector3.zero; weatherCamera.transform.localRotation = Quaternion.identity; } private void _SetShadows() { var setDistance = _currLevelInfo.ShadowDistance; ShadowEx.SetShadowDistance(setDistance); } private async UniTask _LoadOthers() { AssetManager.Instance.PostPreload(Constants.TIREMARK_UNIT_PATH); AssetManager.Instance.PostPreload(Constants.TIREMARK_MAT_PATH); AssetManager.Instance.PostPreload(Constants.CHARACTER_SELECT_GROUND_GFX); AssetManager.Instance.PostPreload(Constants.EMOJI_HEAD_MAT); AssetManager.Instance.PostPreload(Constants.SUMMON_BOTTOM_PATH_SELF); AssetManager.Instance.PostPreload(Constants.SUMMON_BOTTOM_PATH_ENEMY); AssetManager.Instance.PostPreload(Constants.SKILL_GORUND_HIGH_LIGHT); AssetManager.Instance.PostPreload(Constants.CHARACTER_TARGET_GFX); AssetManager.Instance.PostPreload(Constants.ROAD_LINE_PATH); AssetManager.Instance.PostPreload(Constants.CAPTURE_POINT_PATH); AssetManager.Instance.PostPreload(Constants.CAPTURE_FINISHED_POINT_PATH); AssetManager.Instance.PostPreload(Constants.FLAG_GROUND_PATH); AssetManager.Instance.PostPreload(Constants.FLAG_PICK_PATH); AssetManager.Instance.PostPreload(Constants.FLAG_RETURN_PATH); AssetManager.Instance.PostPreload(Constants.PROTECT_TARGET_POINT_PATH); AssetManager.Instance.PostPreload(Constants.FIGHT_LIGHT_AREA_PATH); AssetManager.Instance.PostPreload(Constants.FIGHT_CELL_COLLIDER_PATH); await AssetManager.Instance.WaitAllPreloads(); } private async UniTask _InitAfterLoadMap() { // 加载后处理 await _LoadOutlinePost(); AreaManager.CreateInstance(); // 表情相关 // AssetManager.Instance.PostPreload(Constants.EMOJI_PREFAB_PATH); await AssetManager.Instance.WaitAllPreloads(); } private async UniTask _LoadOutlinePost() { // todo: 因为逻辑上有使用outlinemanager.instance 所以这里需要先加载 // if (!PerformanceManager.instance.data.enablePostOutline) return; // 加载shader AssetManager.Instance.PostPreload(Constants.SHADER_OUTLINE_PATH1); AssetManager.Instance.PostPreload(Constants.SHADER_OUTLINE_PATH1_1); AssetManager.Instance.PostPreload(Constants.SHADER_OUTLINE_PATH2); AssetManager.Instance.PostPreload(Constants.SHADER_OUTLINE_PATH3); await AssetManager.Instance.WaitAllPreloads(); var loadObj = await AssetManager.Instance.LoadAssetAsync(Constants.OUTLINE_POSTPROCESS_PATH); if (loadObj != null) { Object.Instantiate(loadObj); } } public void BeginBattle() { _stateMachine.ChangeState(new BattleState(this)); } public bool IsPreparing() { return _stateMachine.GetCurrentState() is PrepareState; } public bool IsInBattle() { return isInBattle; } public bool IsEnd() { return _stateMachine.GetCurrentState() is EndState; } public async UniTask Unload() { //MapUtils.RemoveCameraController(CameraManager.Instance.MainCamera); CameraManager.Instance.RevertMainCamera(); MapUtils.UnLoadMap(_map); UnRegisterAllEvent(); ReleaseRules(); SelecterView.Instance.Release(); await UnLoadScene(); await UniTask.NextFrame(); } public LevelData GetLevelData() { return _levelData; } public LevelInfo GetLevelInfo() { return _currLevelInfo; } private const string DescKey = "LevelDesc{0}"; private const string NameKey = "LevelName{0}"; public string GetLevelName() { return StringManager.Instance.GetLocalizeTextByKey(string.Format(NameKey, _id)); } public string GetLevelDesc(LevelData levelData) { return StringManager.Instance.GetLocalizeTextByKey(string.Format(DescKey, _id)); } } }