using cfg.LevelCfg; using System.Collections.Generic; using AOT.PostProcess.BlackArea; using Code.Scripts.Gameplay.Utils; using CriWare; using Cysharp.Threading.Tasks; using Framework; using Gameplay.AI; using Gameplay.Area; using Gameplay.BT.Variables; using Gameplay.Buff; using Gameplay.Character; using Gameplay.Common; using Gameplay.Effect; using Gameplay.Emoji; using Gameplay.Fight.Capture; using Gameplay.Fight.Flag; using Gameplay.Level.Select; 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 Gameplay.Vehicle.Impl; using PhxhSDK; using SRF; 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 bool IsWar => _currLevelInfo.ChapterInfo.Cfg.Type == E_ChapterType.War; public Level(int leveId, object param = null) { _id = leveId; _param = param; Init(); } private Dictionary _configLevelDic = new Dictionary(); public Dictionary ConfigLevelDic => _configLevelDic; private void LoadConfigLevel() { LevelManager.Instance.TryGetLevelInfoByID(_id, out _currLevelInfo); } private async UniTask LoadScene() { await GameSceneManager.Instance.LoadSceneAsync(_currLevelInfo.Cfg.LevelScene); await AssetManager.Instance.LoadAndInstAsync(CmpAreaColorSettings.ASSET_PATH); } private async UniTask UnLoadScene() { await GameSceneManager.Instance.UnLoadSceneAsync(_currLevelInfo.Cfg.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(); // await _TempCreateBuild(); } } private async UniTask _TempCreateBuild(uint id, uint cellIndex) { DebugUtil.LogError("临时创建建筑"); var tempCellIndex = (int)cellIndex;//37; var tempBuildId = (int)id;//1005; var teamId = ETroopsId.Enemy1; var createUnit = await GameUnitManager.instance.PrepareBuild(tempBuildId, teamId); if (createUnit == null) { DebugUtil.LogError("创建建筑失败"); return null; } GameUnitManager.instance.MoveUnitToFight(createUnit.GetID(), tempCellIndex, 0); return createUnit; } 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 createUnit = await GameUnitManager.instance.PrepareNpc(npcInfo, teamId); if (createUnit == null) { DebugUtil.LogError("创建npc失败"); continue; } createUnit.unitLevelData = new UnitLevelData() { AttachAIName = npcInfo.attachAIType, AIName = npcInfo.aIType, BornPosition = npcInfo.position, NpcToward = npcInfo.npcToward, PatrolInfos = npcInfo.patrolInfos, GroupInfos = npcInfo.groups, }; createUnit.transData.bornCellIndex = cellIndex; GameUnitManager.instance.MoveUnitToFight(createUnit.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); 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; case Framework.Wrapper.Unit.UnitType.Building: var bInfo = pvpUnitData.fightBuildingData; unit = await _TempCreateBuild(bInfo.Uid, (uint)pvpUnitData.cellIndex); break; } if (unit == null) { DebugUtil.LogError("创建pvp unit失败"); continue; } unit.unitLevelData = new UnitLevelData() { AttachAIName = pvpUnitData.attachAIType, AIName = pvpUnitData.aiType, BornPosition = position, NpcToward = _levelData.pvpDefendToward, PatrolInfos = new(), GroupInfos = new (), }; 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); } selectView?.LogicUpdate(); } /// /// 这里是 level system的初始化,不是 level 场景的初始化 /// public void Init() { // 初始化速度 ELevelSpeed.Level_0 = TableManager.Instance.Tables.GlobalConfig.FightSpeedParams[0]; ELevelSpeed.Level_1 = TableManager.Instance.Tables.GlobalConfig.FightSpeedParams[1]; ELevelSpeed.Level_2 = TableManager.Instance.Tables.GlobalConfig.FightSpeedParams[2]; ELevelSpeed.Level_3 = TableManager.Instance.Tables.GlobalConfig.FightSpeedParams[3]; var defaultLevelSpeedIndex = TableManager.Instance.Tables.GlobalConfig.FightSpeedDefault; ELevelSpeed.DEFAULT_SPEED = TableManager.Instance.Tables.GlobalConfig.FightSpeedParams[defaultLevelSpeedIndex]; 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.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); AssetManager.Instance.Unload(SkillRotateCamera.PREFAB_PATH); AssetManager.Instance.Unload(BlackAreaManagerImpl.BLIT_MAT_PATH); AssetManager.Instance.Unload(Constants.MOVE_AREA_POINT_PATH); for (int i = 0; i < PathDefine.RoadLine.END_NOTICES.Length; i++) { var path = PathDefine.RoadLine.END_NOTICES[i]; AssetManager.Instance.Unload(path); } AssetManager.Instance.Unload(PathDefine.RoadLine.ROAD_LINE); AssetManager.Instance.Unload(PathDefine.RoadLine.ROAD_LINE_STRAIGHT); AssetManager.Instance.Unload(PathDefine.ReadyArea.READY_AREA_POINT); _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.Cfg.LevelWeather; var groundType = (int)_currLevelInfo.Environment; 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(); selectView = new SelectView(); selectView.Init(); await _LoadNpc(); _CreateCapturePoints(); _CreateFlags(); _SetShadows(); RegisterAllEvent(); InitRules(); _InitAudioListener(); _stateMachine.ChangeState(new PrepareState(this)); var enableBlackArea = _currLevelInfo.Cfg.LevelTime == DayNightType.Night; BlackAreaManager.instance.Init(enableBlackArea); _UpdateAllUnits(); InitAIStart(); } private void _InitAudioListener() { var cameraRoot = CameraManager.Instance.MainCamera.gameObject; cameraRoot.RemoveComponentIfExists(); var rayHits = new RaycastHit[10]; var ray = CameraManager.Instance.MainCamera.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0)); var layerMask = LayerMask.GetMask("Ground"); var rayHit = Physics.RaycastNonAlloc(ray, rayHits, 1000, layerMask); if (rayHit <= 0) return; var firstHit = rayHits[0]; var hitPoint = firstHit.point; var listenerRoot = new GameObject("Listener"); listenerRoot.transform.SetParent(cameraRoot.transform); listenerRoot.transform.position = hitPoint; listenerRoot.AddComponent(); } private void _UpdateAllUnits() { var units = GameUnitManager.instance.infightUnits.unitList; for (int i = 0; i < units.Count; i++) { var unit = units[i]; unit.ForceUpdateBlackArea(); } } private async void InitAIStart() { var units = GameUnitManager.instance.infightUnits.unitList; foreach (var unit in units) { if (unit is Character.Character unitCharacter) { await _HandleForCharacter(unitCharacter); } else if (unit is NormalVehicle unitVehicle) { await _HandleForVehicle(unitVehicle); } } } private async UniTask _HandleForVehicle(NormalVehicle vehicle) { if (vehicle == null) return; if (vehicle.commonData.troopId == ETroopsId.Self) { // 玩家默认激活 vehicle.statusData.isAttackActive = true; return; } // AI 默认非激活 vehicle.statusData.isAttackActive = false; var bt = await AIManager.Instance.RegisterAI(vehicle.Node.GameObject, AIBehavior); bt.SetVariable("battleInfo", new SharedBattleInfo() { Value = new BattleInfo() { ownerId = vehicle.GetID(), AIName = vehicle.unitLevelData.AIName, AttachAIName = vehicle.unitLevelData.AttachAIName, PatrolInfos = vehicle.unitLevelData.PatrolInfos, groupInfo = vehicle.unitLevelData.GroupInfos, } }); vehicle.statusData.isAIControll = true; } private async UniTask _HandleForCharacter(Character.Character character) { if (character == null) return; 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.unitLevelData.AIName, AttachAIName = character.unitLevelData.AttachAIName, PatrolInfos = character.unitLevelData.PatrolInfos, groupInfo = character.unitLevelData.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.Cfg.LevelWeather; var groundType = (int)_currLevelInfo.Environment; 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.Cfg.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.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); AssetManager.Instance.PostPreload(SkillRotateCamera.PREFAB_PATH); AssetManager.Instance.PostPreload(BlackAreaManagerImpl.BLIT_MAT_PATH); AssetManager.Instance.PostPreload(Constants.MOVE_AREA_POINT_PATH); for (int i = 0; i < PathDefine.RoadLine.END_NOTICES.Length; i++) { var path = PathDefine.RoadLine.END_NOTICES[i]; AssetManager.Instance.PostPreload(path); } AssetManager.Instance.PostPreload(PathDefine.RoadLine.ROAD_LINE); AssetManager.Instance.PostPreload(PathDefine.RoadLine.ROAD_LINE_STRAIGHT); AssetManager.Instance.PostPreload(PathDefine.ReadyArea.READY_AREA_POINT); await AssetManager.Instance.WaitAllPreloads(); } private async UniTask _InitAfterLoadMap() { var blackAreaInst = new BlackAreaManagerImpl(); BlackAreaManager.CreateInstance(blackAreaInst); _InitCameraParams(); // 加载后处理 await _LoadOutlinePost(); AreaManager.CreateInstance(); // 表情相关 // AssetManager.Instance.PostPreload(Constants.EMOJI_PREFAB_PATH); await AssetManager.Instance.WaitAllPreloads(); } private void _InitCameraParams() { var camera = CameraManager.Instance.MainCamera; var cullingMask = 1 << LayerDefine.Default | 1 << LayerDefine.GROUND | 1 << LayerDefine.UNIT | 1 << LayerDefine.Skill | 1 << LayerDefine.LightArea | 1 << LayerDefine.TeamSelf | 1 << LayerDefine.TeamEnemy; camera.cullingMask = cullingMask; } 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); OutlineManager.instance.mat1 = AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH1); OutlineManager.instance.mat1_1 = AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH1_1); OutlineManager.instance.mat2 = AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH2); OutlineManager.instance.mat3 = AssetManager.Instance.GetPreLoadResult(Constants.SHADER_OUTLINE_PATH3); // 全部instance之后再设置 OutlineManager.instance.mat1 = new Material(OutlineManager.instance.mat1); OutlineManager.instance.mat1_1 = new Material(OutlineManager.instance.mat1_1); OutlineManager.instance.mat2 = new Material(OutlineManager.instance.mat2); OutlineManager.instance.mat3 = new Material(OutlineManager.instance.mat3); OutlineManager.instance.targetCamera = CameraManager.Instance.MainCamera; OutlineManager.instance.m_EnableOutline = PerformanceManager.instance.data.enablePostOutline; var screenWidth = Screen.width; var sampleDistance = OutlineManager.instance.m_SampleDistance; var wrapDistance = sampleDistance / 1080 * screenWidth; var scaleProgress = CameraManager.Instance.GetOutlineScale(wrapDistance); OutlineManager.instance.scaleProgress = scaleProgress; } } 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(); selectView.Dispose(); await UnLoadScene(); await UniTask.NextFrame(); } public LevelData GetLevelData() { return _levelData; } public LevelInfo GetLevelInfo() { return _currLevelInfo; } } }