// BubbleData.cs using System; using System.Collections.Generic; using Logic.Action; using RuntimeData; using TH1_Logic.Core; using TH1Renderer; using UnityEngine; using System.Linq; using Logic; using TH1_Core.Managers; using Object = UnityEngine.Object; using Random = UnityEngine.Random; namespace TH1_Renderer { public enum BubbleType { None, Gather, Capture, HeroUpgrade, Upgrade, Examine } //TODO 做BubbleData序列化相关的工作 [Serializable] public struct BubbleData { public GridData Grid; public UnitData Unit; //public HintType HintType; public BubbleType BubbleType; public BubbleData(GridData grid , BubbleType bubbleType) { Grid = grid; Unit = grid.Unit(Main.MapData); BubbleType = bubbleType; } } [Serializable] public class InGameBubbleManager { //public HashSet HintSet = new(); //private Dictionary _idToHintDict = new(); private uint _bubbleRendererIdCounter; private GameObject _prefabROHint; private Transform _selfTransform; //private Dictionary _ROHintRendererDict = new(); //存储可用的bubbleRendererId private HashSet _availableRenderer; private Dictionary _dict; //gid -> rendererid private Dictionary _gridHasBubble; //每次开启一局游戏前,都要初始化的模块 public void Init(Transform selfTransform) { _bubbleRendererIdCounter = 0; _prefabROHint = Resources.Load("Prefab/bubblePrefab"); _selfTransform = selfTransform; _availableRenderer = new HashSet(); _dict = new Dictionary(); _gridHasBubble = new Dictionary(); } //每局游戏开始前都要更新的 public void OnGameStart() { _bubbleRendererIdCounter = 0; _availableRenderer = new HashSet(); _dict = new Dictionary(); _gridHasBubble = new Dictionary(); foreach (Transform child in _selfTransform.transform) { // 对每个子对象调用Destroy Object.Destroy(child.gameObject); } } public void OnGameClosed() { CloseAllBubble(); ClearAllRenderer(); } public void ClearAllRenderer() { foreach (var t in _dict) t.Value.Destroy(); _dict.Clear(); } public uint BubbleDataIdGenerator() { return _bubbleRendererIdCounter++; } //每帧调用所有hintRenderer的update,并且将已经结束的Renderer回收 public void Update() { if (!Main.MapData.CurPlayer?.IsSelfPlayer() ?? true) return; //遍历所有unit,查看哪些单位需要更新bubble显示 foreach (var unit in Main.MapData.UnitMap.UnitList) { //如果不是本机玩家 if (!unit.Player(Main.MapData, out var player)||!player.IsSelfPlayer()) continue; if(!unit.Grid(Main.MapData,out var grid)) continue; //准备升级行为的参数 var upgradeAction = ActionLogicFactory.GetActionLogic(new CommonActionId() { ActionType = CommonActionType.UnitAction, UnitActionType = UnitActionType.Upgrade }); var heroUpgradeAction = ActionLogicFactory.GetActionLogic(new CommonActionId() { ActionType = CommonActionType.UnitAction, UnitActionType = UnitActionType.HeroUpgrade }); var captureAction = ActionLogicFactory.GetActionLogic(new CommonActionId() { ActionType = CommonActionType.UnitAction, UnitActionType = UnitActionType.Capture }); var starfishAction = ActionLogicFactory.GetActionLogic(new CommonActionId() { ActionType = CommonActionType.UnitAction, UnitActionType = UnitActionType.Gather }); var treasureAction = ActionLogicFactory.GetActionLogic(new CommonActionId() { ActionType = CommonActionType.UnitAction, UnitActionType = UnitActionType.Examine }); var actionParam = new CommonActionParams() { PlayerData = Main.MapData.PlayerMap.SelfPlayerData, UnitData = unit, GridData = unit.Grid(Main.MapData), MapData = Main.MapData, }; //先判断是否已经有按钮,如果有 bool upgrade = upgradeAction.CheckCan(actionParam); bool heroUpgrade = heroUpgradeAction.CheckCan(actionParam); bool capture = captureAction.CheckCan(actionParam); bool treasure = treasureAction.CheckCan(actionParam); bool starfish = starfishAction.CheckCan(actionParam); bool showBubble = upgrade || heroUpgrade || capture || treasure || starfish; BubbleType bubbleType = BubbleType.Upgrade; if(heroUpgrade)bubbleType = BubbleType.HeroUpgrade; if(capture)bubbleType = BubbleType.Capture; if(treasure)bubbleType = BubbleType.Examine; if(starfish)bubbleType = BubbleType.Gather; //判断是否能执行升级行为,可以的话,播放bubble if (showBubble) { if (_gridHasBubble.ContainsKey(grid.Id)) continue; if(ShowBubble(new BubbleData(grid,bubbleType),out var rendererId)) _gridHasBubble.Add(grid.Id,rendererId); } //如果不应该播放bubble但是有个bubble,关掉他 if(!showBubble) { if (_gridHasBubble.ContainsKey(grid.Id)) { if (_dict.TryGetValue(_gridHasBubble[grid.Id], out var renderer)) renderer.ForceClose(); RecycleBubble(_gridHasBubble[grid.Id],grid.Id); } } } //遍历现在所有存在bubble的格子,如果格子上没有unit,让这个bubble自动关闭 var deleteList = new List(); foreach (var t in _gridHasBubble) { if (!Main.MapData.GridMap.GetGridDataByGid(t.Key, out var grid)) continue; if (!grid.Unit(Main.MapData, out var _)) { if (_dict.TryGetValue(t.Value, out var renderer)) renderer.ForceClose(); deleteList.Add(t.Key); } } //回收这些bubble foreach (var t in deleteList) if(_gridHasBubble.TryGetValue(t,out var v)) RecycleBubble(v,t); } public bool ShowBubble(BubbleData data,out uint rendererId) { //Step #1 获取一个可用的renderer var id = GetAvailableRenderer(); _availableRenderer.Remove(id); if (!_dict.TryGetValue(id, out var renderer)) { Debug.Log($"Fatal error Showbubble can't find dict key id = {id}"); rendererId = 0; return false; } rendererId = renderer.Id; //Step #2 设置对应的renderer return renderer.SetInfo(data,onClick:ClickBubble); } public uint GetAvailableRenderer() { //如果池子里没有可用对象,新创建一个 if (_availableRenderer.Count == 0) { var renderer = new BubbleRenderer(BubbleDataIdGenerator(),_prefabROHint,_selfTransform); _availableRenderer.Add(renderer.Id); _dict[renderer.Id] = renderer; return renderer.Id; } //否则随便给一个可以用的 return _availableRenderer.First(); } public void CloseAllBubble() { //遍历所有renderer,查询是否有不在available set里的,有的话就强制关闭 foreach (var t in _dict) if (!_availableRenderer.Contains(t.Key)) { t.Value.ForceClose(); _availableRenderer.Add(t.Key); } _gridHasBubble.Clear(); } //被动由逻辑触发 public void RecycleBubble(uint rendererId,uint gid) { _availableRenderer.Add(rendererId); _gridHasBubble.Remove(gid); } //由玩家主动触发 public void ClickBubble(uint rendererId,uint gid) { RecycleBubble(rendererId,gid); //UI收回 Main.Instance.MapInteractionLogic.CancelAllHighlight(); UIManager.Instance.BottomInfoUI.UIBottomInfoStatus = false; } public void TurnStartSetBubble(MapData mapData, PlayerData playerData) { } } }