using System; using System.Collections.Generic; using UnityEngine; using RuntimeData; using Animancer; using Logic; using Logic.Action; using Logic.AI; using Logic.CrashSight; using TH1_Logic.Config; using TH1_Logic.Core; using TH1Resource; using Unity.IO.LowLevel.Unsafe; using Object = UnityEngine.Object; using Random = UnityEngine.Random; using TMPro; using Unity.VisualScripting; using UnityEngine.UI; namespace TH1Renderer { public class GridRenderer { private static readonly CommonActionId GainFishActionId = new CommonActionId { ActionType = CommonActionType.Gain, ResourceType = ResourceType.Fish, }; private MapData _mapData; private GameObject _ROGrid; private uint _gridId; private bool _cityWallMark = false; private Color terriColor = new Color(0.9f, 0.9f, 1f); //-------- 表现层数据Rdata --------// public bool IsSelectHighlight = false; public bool IsMoveHighlight = false; public bool IsAttackHighlight = false; public MoveHighlightType MoveHighlightTypes { get; private set; } = MoveHighlightType.None; //--------- 瞬间更新的动画 -------- public int NowCityBuildlingLevel; public CivEnum NowCityCiv; public CivEnum UpdateCityCiv; public int UpdateCityBuildingLevel; public bool UpdateGrid; public float RandomWait; //-------- Update缓存数据 --------// private GridData _gridData; private bool _freeland; private CityData _cityData; private PlayerData _playerData; private GameObject _land, _gridSp, _mountain, _forest, _road, _resource, _cityBuilding, _cityWall, _fog, _borderUpLeft, _borderUpRight, _borderDownLeft, _borderDownRight, _cityBorderUpLeft, _cityBorderUpRight, _cityBorderDownLeft, _cityBorderDownRight, _selectHighlight, _moveHighlight, _moveHighlightTypeGroup, _attackHighlight, _effect, _RODebugText; private TextMeshPro _debugText; private readonly GameObject[] _moveHighlightTypeSlots = new GameObject[4]; private readonly SpriteRenderer[] _moveHighlightTypeRenderers = new SpriteRenderer[4]; private SpriteRenderer _moveHighlightRenderer; private Sprite _defaultMoveHighlightSprite; private Color _defaultMoveHighlightColor = Color.white; private static readonly MoveHighlightType[] MoveHighlightDisplayOrder = { MoveHighlightType.Slow, MoveHighlightType.Road, MoveHighlightType.Boat, MoveHighlightType.Ashore, MoveHighlightType.Sanae, MoveHighlightType.Teleport, MoveHighlightType.Momiji, MoveHighlightType.Yuugi, }; public int x, y; string forcesName, civName; bool needBounce = false, isBounceDown = true,levelupBounce = false; Vector3 bounceUpPos, bounceDownPos; private float _bounceWaitTime = 0f; float bounceTime = 0f; float bounceDownFullTime = 0.13f; float bounceUpFullTime = 0.07f; float levelupBounceDownFullTime = 0.33f; float levelupBounceUpFullTime = 0.07f; //-------- VFX管理器 -------- public GridVFXManager GridVFXManager; private Sprite _dieHint; private Sprite _counterDieHint; bool renderVeteran = false; public GridRenderer(GameObject prefab,Transform father, uint gridId, MapData mapData, Main main) { _mapData = mapData; _gridId = gridId; mapData.GridMap.GetGridDataByGid(_gridId,out _gridData); _freeland = !_mapData.GetCityDataByTerritoryGid(_gridId,out _cityData); if(!_freeland) _mapData.GetPlayerDataByCityId(_cityData.Id,out _playerData); if (!(_cityData == null) && !(_playerData == null)) { _mapData.GridMap.GetGridDataByGid(gridId, out var g1); } Vector3 tpos = Table.Instance.GridToWorld(_gridData); _ROGrid = GameObject.Instantiate(prefab,tpos, Quaternion.identity, father); Init(_gridData); } public GameObject GetROGrid() { return _ROGrid; } public GridData Grid() { return _gridData; } public void InstantUpdateGrid(bool v = true) { UpdateGrid = v; } public void InstantUpdateCityBuilding(int v,CivEnum civ) { UpdateCityBuildingLevel = v; UpdateCityCiv = civ; } public bool IsBelongSelfPlayer() { return _gridData.Player(Main.MapData).IsSelfPlayer(); } private void ClearHistoryRenderMark() { GridVFXManager.Clear(); } //判断各自是否要bounce 并处理bounce动画 private void UpdateBounceAnim() { var downFullTime = levelupBounce? levelupBounceDownFullTime : bounceUpFullTime; var upFullTime = levelupBounce ? levelupBounceUpFullTime : bounceUpFullTime; if (needBounce) { if (_bounceWaitTime > 0) _bounceWaitTime -= Time.deltaTime; else { if (isBounceDown) { bounceTime += Time.deltaTime / downFullTime; if (levelupBounce) { float easedT = 1f - Mathf.Pow(1f - bounceTime, 3); _ROGrid.transform.position = Vector3.Lerp(bounceUpPos, bounceDownPos, bounceTime); } else _ROGrid.transform.position = Vector3.Lerp(bounceUpPos, bounceDownPos, bounceTime); if (bounceTime >= 1f) { isBounceDown = false; bounceTime = 0f; } } else { bounceTime += Time.deltaTime / upFullTime; _ROGrid.transform.position = Vector3.Lerp(bounceDownPos, bounceUpPos, bounceTime); if (bounceTime >= 1f) needBounce = false; } } } } //处理VFXManagerDict下每个Effect的Update public void Update() { //step #1 每帧更新每个grid相关的player city的缓存数据 _mapData.GridMap.GetGridDataByGid(_gridId, out _gridData); _freeland = !_mapData.GetCityDataByTerritoryGid(_gridId, out _cityData); if (!_freeland) _mapData.GetPlayerDataByCityId(_cityData.Id, out _playerData); //step #2 处理需要瞬间更新gridData视觉的情况 if (UpdateGrid) { UpdateGrid = false; RenderUpdateGridWithoutCityBuilding(); } if (UpdateCityBuildingLevel != NowCityBuildlingLevel) { NowCityBuildlingLevel = UpdateCityBuildingLevel; RenderUpdateCityBuilding(_cityData.Id); } if (NowCityCiv != UpdateCityCiv) { NowCityCiv = UpdateCityCiv; RenderUpdateCityBuilding(_cityData.Id); } //step #3 查看城市边界的更新情况,这个没有视野也会显示的,目前都是瞬间更新 UpdateCityBorder(); //step #4 判断各自是否要bounce UpdateBounceAnim(); //step #5 驱动VFXManager的所有VFX对象的update GridVFXManager.Update(); } public void FirstShowGrid() { //Step #1 播放雾气消失动画 PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); //Step #2 呈现格子画面 RenderUpdateGridWithoutCityBuilding(); //Step #3 如果有city,更新city情况 var city = _gridData.CityOnGrid(Main.MapData); if (city != null) { RenderUpdateCityBuilding(_cityData.Id); _cityData.CityInfoRenderer(Main.MapData)?.InstantUpdateCityInfo(); } //Step #4 如果有unit,更新unit的表现,更新unit的位置 if (_gridData.MainSelfPlayerVisibleUnit(out var unit)) { //unit.RenderMark = true; unit.Renderer(Main.MapData)?.InstantUpdateUnit(true); unit.Renderer(Main.MapData)?.InstantUpdateUnitPos(); //更新该单位周围其他单位的高亮状态 MapRenderer.Instance.UpdateAroundHighlight(Main.MapData,_gridData); } } public void PlayVFXInSight(GridVFXParams param, GridVFXPlayType playType = GridVFXPlayType.PlayOnce) { //当前玩家有该格子的视野,才播放该动画 if (Main.MapData?.PlayerMap?.SelfPlayerData?.Sight?.SightGidSet == null || _gridData == null || GridVFXManager == null) return; if(Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id)) GridVFXManager.PlayVFX(param,playType); } public void PlayVFXForce(GridVFXParams param, GridVFXPlayType playType = GridVFXPlayType.PlayOnce) { GridVFXManager.PlayVFX(param,playType); } private void RenderUpdateDebug() { if (DebugCenter.Instance.DebugMode) { if(!_RODebugText.activeSelf) _RODebugText.SetActive(true); } else { _RODebugText.SetActive(false); return; } _debugText.text = ""; _debugText.text += $"ID={_gridId}"; _debugText.text += $" pos={_gridData.Pos.X} {_gridData.Pos.Y}\n"; if(_gridData.buildingLevel > 0) _debugText.text += $"lv = {_gridData.buildingLevel}\n"; if(_gridData.Feature == TerrainFeature.Road) _debugText.text += $"road\n"; } private void Init(GridData t) { x = (int)t.Pos.X; y = (int)t.Pos.Y; //Vector3 pos = transform.position; //pos.z = GridData.pos.x + GridData.pos.y; //transform.position = pos; _land = _ROGrid.transform.Find("Land").gameObject; _gridSp = _ROGrid.transform.Find("GridSp")?.gameObject; _road = _ROGrid.transform.Find("Road").gameObject; _mountain = _ROGrid.transform.Find("Mountain").gameObject; _forest = _ROGrid.transform.Find("Forest").gameObject; _resource = _ROGrid.transform.Find("Resource").gameObject; _cityBuilding = _ROGrid.transform.Find("cityBuilding").gameObject; _cityWall = _ROGrid.transform.Find("cityWall").gameObject; _fog = _ROGrid.transform.Find("Fog").gameObject; _borderUpLeft = _ROGrid.transform.Find("BorderUpLeft").gameObject; _borderUpRight = _ROGrid.transform.Find("BorderUpRight").gameObject; _borderDownLeft = _ROGrid.transform.Find("BorderDownLeft").gameObject; _borderDownRight = _ROGrid.transform.Find("BorderDownRight").gameObject; _cityBorderUpLeft = _ROGrid.transform.Find("CityBorderUpLeft").gameObject; _cityBorderUpRight = _ROGrid.transform.Find("CityBorderUpRight").gameObject; _cityBorderDownLeft = _ROGrid.transform.Find("CityBorderDownLeft").gameObject; _cityBorderDownRight = _ROGrid.transform.Find("CityBorderDownRight").gameObject; _selectHighlight = _ROGrid.transform.Find("SelectHighlight").gameObject; _moveHighlight = _ROGrid.transform.Find("MoveHighlight").gameObject; _moveHighlightRenderer = _moveHighlight.GetComponent(); if (_moveHighlightRenderer != null) { _defaultMoveHighlightSprite = _moveHighlightRenderer.sprite; _defaultMoveHighlightColor = _moveHighlightRenderer.color; } InitMoveHighlightTypeGroup(); _attackHighlight = _ROGrid.transform.Find("AttackHighlight").gameObject; _effect = _ROGrid.transform.Find("Effect").gameObject; _RODebugText = _ROGrid.transform.Find("DebugText").gameObject; _debugText = _RODebugText?.GetComponent(); foreach(Transform child in _effect.transform) child.gameObject.SetActive(false); //创建特效管理器Dict GridVFXManager = new GridVFXManager(_effect); RenderUpdateGridWithoutCityBuilding(); //UpdateBorder();fog自带updateborder } private void RenderUpdateGridWithoutCityBuilding() { UpdateLand(); UpdateGridSp(); UpdateRoad(); UpdateMountain(); UpdateForest(); UpdateResource(); UpdateCityWall(); UpdateCityBorder(); UpdateFog(); UpdateGridVFX(); RenderUpdateDebug(); //UpdateBorder();fog自带updateborder } public void RenderUpdateCityBuilding(uint cityId) { if (_mapData?.CityMap == null || _cityBuilding == null || Table.Instance == null) return; _mapData.CityMap.GetCityById(cityId,out CityData cityData); _mapData.GetPlayerDataByCityId(cityId, out PlayerData playerData); if (cityData == null || playerData == null) return; int citylevel = cityData.Level; if (citylevel < 0 || citylevel >= Table.Instance.cityLevel2HouseEdge.Length || citylevel >= Table.Instance.cityLevel2HouseNumber.Length || citylevel >= Table.Instance.cityLevel2HouseHeight.Length || citylevel >= Table.Instance.cityLevel2HouseType.Length) return; int houseEdge = Table.Instance.cityLevel2HouseEdge[citylevel]; int houseSize = houseEdge * houseEdge; int houseCount = Table.Instance.cityLevel2HouseNumber[citylevel]; int houseHeight = Table.Instance.cityLevel2HouseHeight[citylevel]; int houseTypeCount = Table.Instance.cityLevel2HouseType[citylevel]; if (houseEdge <= 0 || houseSize <= 0 || houseCount <= 0 || houseHeight <= 0 || houseTypeCount <= 0) return; if (houseCount < houseSize) houseCount = houseSize; int[] housePosHeight = new int[houseSize]; int[,] textureType = new int[houseHeight, houseCount]; for (int k = 0; k < houseSize; k++) { for (int l = 0; l < houseHeight; l++) textureType[l, k] = 0; //初始化 housePosHeight[k] = 1; textureType[0, k] = Random.Range(0, houseTypeCount); } for (int k = houseSize; k < houseCount; k++) { int randPos = Random.Range(0, houseSize); if (housePosHeight[randPos] >= houseHeight) { for (randPos = houseSize - 1; randPos >= 0; randPos--) if (housePosHeight[randPos] < houseHeight) break; if (randPos < 0) break; } textureType[housePosHeight[randPos]++, randPos] = Random.Range(0, houseTypeCount); } //清空原来的城市图像 foreach (UnityEngine.Transform child in _cityBuilding.transform) Object.Destroy(child.gameObject); //开始设置城市图像 for (int x = 0; x < houseEdge; x++) for (int y = 0; y < houseEdge; y++) for (int z = 0; z < housePosHeight[x * houseEdge + y]; z++) { int textureIndex = textureType[z, x * houseEdge + y]; GameObject house = new GameObject($"house{x}_{y}_{z}"); SpriteRenderer sr = house.AddComponent(); //string forcesName = Table.Instance.QueryForcesName(playerData.PlayerForceId); //string civName = Table.Instance.QueryCivsName(playerData.PlayerCivId); //sr.sprite = TH1Resource.ResourceLoader.Load( // $"ArtResources/TH1Buildings/TH1Buildings{forcesName}/{civName}/{forcesName}_{civName}_House_{textureType[z,x*houseEdge +y] + 1}"); if (Table.Instance.CivDataAssets != null && Table.Instance.CivDataAssets.GetCivInfo(playerData.PlayerCivId, out var civInfo) && civInfo.HouseSpriteList != null && textureIndex >= 0 && civInfo.HouseSpriteList.Count > textureIndex) sr.sprite = civInfo.HouseSpriteList[textureIndex]; house.transform.parent = _cityBuilding.transform; Vector3 tpos = _ROGrid.transform.position; //每层的层高 float levelHeight = 1.5f; tpos = new Vector3(tpos.x + 1.22f * (x - y), tpos.y + 0.7f * (x + y) + z * levelHeight - 7.5f + 0.7f * (4 - houseEdge), tpos.z + 0.9f - (30 + z - x - y) * 0.001f); house.transform.position = tpos; house.transform.localScale = 3.9f * Vector3.one; } } // 让 cityBuilding 下 house{x}_{y}_{z} 中 z >= h 的 sprite 半透(alpha=0.2),其余恢复 1.0 public void SetCityBuildingFadeAboveHeight(int h) { if (_cityBuilding == null) return; foreach (Transform child in _cityBuilding.transform) { if (!TryParseHouseZ(child.name, out int z)) continue; var sr = child.GetComponent(); if (sr == null) continue; var c = sr.color; c.a = z >= h ? 0.2f : 1.0f; sr.color = c; } } // 取消半透,cityBuilding 下所有 house 的 alpha 恢复 1.0 public void ClearCityBuildingFade() { if (_cityBuilding == null) return; foreach (Transform child in _cityBuilding.transform) { var sr = child.GetComponent(); if (sr == null) continue; var c = sr.color; c.a = 1.0f; sr.color = c; } } // 从 "house{x}_{y}_{z}" 形式的名字解析出 z(最后一段) private static bool TryParseHouseZ(string name, out int z) { z = 0; if (string.IsNullOrEmpty(name)) return false; int idx = name.LastIndexOf('_'); if (idx < 0 || idx == name.Length - 1) return false; return int.TryParse(name.Substring(idx + 1), out z); } public void RenderUpdataHighlight() { UpdateMoveHighlightSprite(); _moveHighlight.SetActive(IsMoveHighlight); _attackHighlight.SetActive(IsAttackHighlight); _selectHighlight.SetActive(IsSelectHighlight); UpdateMoveHighlightTypeSlots(); } private void UpdateMoveHighlightSprite() { if (_moveHighlightRenderer == null) return; if (IsMoveHighlight && IsEnhancedMoveHighlightEnabled() && (MoveHighlightTypes & MoveHighlightType.Enemy) != 0 && TryGetMoveHighlightVisual(MoveHighlightType.Enemy, out var enemyVisual) && enemyVisual.Sprite != null) { _moveHighlightRenderer.sprite = enemyVisual.Sprite; _moveHighlightRenderer.color = enemyVisual.Color; return; } _moveHighlightRenderer.sprite = _defaultMoveHighlightSprite; _moveHighlightRenderer.color = _defaultMoveHighlightColor; } private void InitMoveHighlightTypeGroup() { var group = _ROGrid.transform.Find("MoveHighlightTypeGroup") ?? _ROGrid.transform.Find("MoveHiglightTypeGroup") ?? _ROGrid.transform.Find("MoveHighlight/MoveHighlightTypeGroup") ?? _ROGrid.transform.Find("MoveHighlight/MoveHiglightTypeGroup"); if (group == null) return; _moveHighlightTypeGroup = group.gameObject; for (int i = 0; i < _moveHighlightTypeSlots.Length; i++) { int index = i + 1; var slot = group.Find($"Position{index}") ?? group.Find($"Pos{index}") ?? group.Find(index.ToString()); if (slot == null && i < group.childCount) slot = group.GetChild(i); if (slot == null) continue; _moveHighlightTypeSlots[i] = slot.gameObject; _moveHighlightTypeRenderers[i] = slot.GetComponent(); _moveHighlightTypeSlots[i].SetActive(false); } _moveHighlightTypeGroup.SetActive(false); } private void UpdateMoveHighlightTypeSlots() { if (_moveHighlightTypeGroup == null) return; if (!IsMoveHighlight || !IsEnhancedMoveHighlightEnabled() || MoveHighlightTypes == MoveHighlightType.None) { _moveHighlightTypeGroup.SetActive(false); for (int i = 0; i < _moveHighlightTypeSlots.Length; i++) if (_moveHighlightTypeSlots[i] != null) _moveHighlightTypeSlots[i].SetActive(false); return; } _moveHighlightTypeGroup.SetActive(true); int slotIndex = 0; foreach (var type in MoveHighlightDisplayOrder) { if ((MoveHighlightTypes & type) == 0) continue; if (slotIndex >= _moveHighlightTypeSlots.Length) break; var slot = _moveHighlightTypeSlots[slotIndex]; var renderer = _moveHighlightTypeRenderers[slotIndex]; if (slot == null || renderer == null) { slotIndex++; continue; } if (!TryGetMoveHighlightVisual(type, out var visual) || visual.Sprite == null) { continue; } renderer.sprite = visual.Sprite; renderer.color = visual.Color; slot.SetActive(true); slotIndex++; } for (int i = slotIndex; i < _moveHighlightTypeSlots.Length; i++) if (_moveHighlightTypeSlots[i] != null) _moveHighlightTypeSlots[i].SetActive(false); } private static bool TryGetMoveHighlightVisual(MoveHighlightType type, out MoveHighlightVisual visual) { visual = null; return ResourceCache.Instance?.SpriteCache?.TryGetMoveHighlightVisual(type, out visual) == true; } private static bool IsEnhancedMoveHighlightEnabled() { return ConfigManager.Instance?.Config?.EnhancedMoveHighlightEnabled ?? true; } public void SetSelectHighlight(bool v) { if (IsSelectHighlight == v) return; IsSelectHighlight = v; MapRenderer.Instance.HighlightGridIdSet.Add(_gridId); MapRenderer.Instance.HighlightGridIdSetRenderMark = true; } public void SetMoveHighlight(bool v) { SetMoveHighlight(v, MoveHighlightType.None); } public void SetMoveHighlight(bool v, MoveHighlightType types) { if (v && IsFogForSelfPlayer()) types = MoveHighlightType.None; if (IsMoveHighlight == v && MoveHighlightTypes == types) return; IsMoveHighlight = v; MoveHighlightTypes = v ? types : MoveHighlightType.None; MapRenderer.Instance.HighlightGridIdSet.Add(_gridId); MapRenderer.Instance.HighlightGridIdSetRenderMark = true; } private bool IsFogForSelfPlayer() { if (_fog != null && _fog.activeSelf) return true; var sight = _mapData?.PlayerMap?.SelfPlayerData?.Sight; return sight != null && !sight.CheckIsInSight(_gridId); } public void SetAttackHighlight(bool v) { if (IsAttackHighlight == v) return; IsAttackHighlight = v; MapRenderer.Instance.HighlightGridIdSet.Add(_gridId); MapRenderer.Instance.HighlightGridIdSetRenderMark = true; } private void UpdateLand() { if(_land == null) return; var com = _land?.GetComponent(); if (com == null) return; var oldSprite = com.sprite; if (oldSprite == null) return; com.color = _gridData.Player(Main.MapData, out var _) && _gridData.Terrain == TerrainType.Land ? terriColor : Color.white; var newSprite = Table.Instance.GridAndResourceDataAssets.GetTerrainSprite(_gridData); if (_gridData.HasSpType(GridSpType.LeyLine) && !_gridData.HasSpType(GridSpType.RemiliaGrid) && !_gridData.HasSpType(GridSpType.KaguyaGrid)) { var selfPlayer = Main.MapData.PlayerMap.SelfPlayerData; if (selfPlayer.CivEnum != CivEnum.Indian) newSprite = Table.Instance.GridAndResourceDataAssets.GetDefaultTerrainSprite(_gridData); } com.sprite = newSprite; //_land.GetComponent().sprite = Table.Instance.GridAndResourceDataAssets.GetTerrainSprite(_gridData); if (oldSprite != newSprite && _gridData.HasSpType(GridSpType.RemiliaGrid)) { PlayVFXInSight(new GridVFXParams(GridVFXType.RedMistCreate)); } } private void UpdateGridSp() { if (_gridSp == null) return; var renderer = _gridSp.GetComponent(); if (renderer == null) { _gridSp.SetActive(false); return; } var sprite = Table.Instance.GridAndResourceDataAssets.GetGridSpSprite(_gridData); if (renderer.sprite != sprite) renderer.sprite = sprite; _gridSp.SetActive(sprite != null); } private void UpdateRoad() { if (_gridData == null || _road == null || _mapData == null) return; //如果当前的feature没有road if (_gridData.Feature != TerrainFeature.Road) { for (int i = 1; i <= 9; i++) { int dirForHuman = i; int dirForComputer = dirForHuman - 1; var t = _road.transform.Find($"Road{dirForHuman}"); if (t != null) GameObject.Destroy(t.gameObject); } return; } //TODO 最好把dir做成enum for (int i = 1; i <= 9; i++) { int dirForHuman = i; int dirForComputer = dirForHuman - 1; var t = _road.transform.Find($"Road{dirForHuman}"); if (!_mapData.CheckIfNearByGridRoadCanConnenct(_gridData, dirForComputer)) { if (t != null) GameObject.Destroy(t.gameObject); continue; } if (t == null) { GameObject road = new GameObject($"Road{dirForHuman}"); SpriteRenderer sr = road.AddComponent(); if(ResourceCache.Instance?.SpriteCache?.Roads?.TryGetValue((_gridData.Terrain == TerrainType.Land ? "Road" : "WaterRoad") + dirForComputer,out var tmpSprite) != null) sr.sprite = tmpSprite; road.transform.parent = _road.transform; road.transform.localPosition = new Vector3(0, 0, 0); } } } private void UpdateMountain() { var renderer = _mountain?.GetComponent(); if (!renderer) return; renderer.sprite = Table.Instance.GridAndResourceDataAssets?.GetMountainSprite(_gridData); } private void UpdateForest() { var renderer = _forest?.GetComponent(); if (!renderer) return; renderer.sprite = Table.Instance.GridAndResourceDataAssets?.GetVegetationSprite(_gridData); } private void UpdateResource() { //TODO 时序问题要处理 开游戏第一帧报错 if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return; //if(!_freeland) forcesName = Table.Instance.QueryForcesName(_playerData.PlayerForceId); bool glow = (!_freeland && _playerData.Id == _mapData.PlayerMap.SelfPlayerData.Id && ((_gridData.Resource == ResourceType.Fruit && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.GainFruit)) || (_gridData.Resource == ResourceType.Animal && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.GainAnimal)) || (_gridData.Resource == ResourceType.Animal && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.TrainUnitKaguyaFrenchAnimalWarrior)) || (_gridData.Resource == ResourceType.Fish && _playerData.TechTree.CheckActionCan(GainFishActionId)) || (_gridData.Resource == ResourceType.Crop && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.BuildFarm)) || (_gridData.Resource == ResourceType.Metal && _playerData.TechTree.CheckIfHasTechAtom(TechAtom.BuildMine)))); if (_gridData.Resource == ResourceType.Starfish && _mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.Navigation)) glow = true; bool hasCity = _mapData.GetCityDataByTerritoryGid(_gridId, out var cityData); //处理隐藏没有科技情况下 metal、starfish、crop的情况 bool skip = false; if (_gridData.Resource == ResourceType.Crop) if (!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.Organization) && !_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.Farming) && !_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(TechType.RemiliaFarming)) skip = true; if (_gridData.Resource == ResourceType.Metal) if (!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.BuildMine) && !_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.UnitSkillMOUNTAINMOVE)) skip = true; if (_gridData.Resource == ResourceType.Starfish) if (!_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.UnitActionGather) && !_mapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTechAtom(TechAtom.UnitSkillOCEANMOVE)) skip = true; if (skip) { var renderer = _resource?.GetComponent(); if (!renderer) return; renderer.sprite = null; return; } //注意 playerData可能是null 对于中立格子来说 var resource = Table.Instance.GridAndResourceDataAssets.GetResourceSprite(_gridData.Resource,_playerData,_gridData); //如果是桥梁 处理mirror的情况 if (_gridData.Resource == ResourceType.Bridge) { if(_mapData.GridMap.CalcBridgeMirror(_gridData)) resource = Table.Instance.GridAndResourceDataAssets.GetResourceSprite(_gridData.Resource,_playerData,_gridData,mirror:true); } //如果是citycenter并且有城市了,就变为null if (_gridData.Resource == ResourceType.CityCenter && hasCity) resource = null; //如果是奇观,替换为对应奇观 if (_gridData.Resource == ResourceType.Wonder) resource = Table.Instance.GridAndResourceDataAssets.GetWonderSprite(_gridData.Wonder); var resRenderer = _resource?.GetComponent(); if (resRenderer) { if (resRenderer.sprite != resource) resRenderer.sprite = resource; //处理高光效果 resRenderer.material = glow ? ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_Glow: ResourceCache.Instance.MatCache.TH1URPShaders_Default; } } private void UpdateCityWall() { if (_cityWall.activeSelf) return; if (!_mapData.GetCityDataByGid(_gridId, out var cityData)) return; if (!cityData.CityWall) return; _cityWallMark = true; _cityWall.SetActive(true); } public void UpdateBorder() { //如果不是城市领土,不需要生成border if (_freeland) { _borderDownLeft.SetActive(false); _borderDownRight.SetActive(false); _borderUpLeft.SetActive(false); _borderUpRight.SetActive(false); return; } if (Table.Instance.PlayerDataAssets.GetPlayerInfo(_playerData, out var playerInfo)) { var c = playerInfo.Color; //c.a = 0.8f; var downLeftRender = _borderDownLeft?.GetComponent(); if (downLeftRender) downLeftRender.color = c; var downRightRender = _borderDownRight?.GetComponent(); if (downRightRender) downRightRender.color = c; var upRightRender = _borderUpRight?.GetComponent(); if (upRightRender) upRightRender.color = c; var upLeftRender = _borderUpLeft?.GetComponent(); if (upLeftRender) upLeftRender.color = c; } if (_mapData == null || _gridData == null) return; _borderDownLeft?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,4)); _borderDownRight?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,2)); _borderUpRight?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,6)); _borderUpLeft?.SetActive(!_mapData.CheckIfNearByGridSamePlayer(_gridData,8)); } private void UpdateCityBorder() { //如果没有rendermark 直接return if (!_gridData.CityBorderRenderMark) { _cityBorderDownLeft.SetActive(false); _cityBorderDownRight.SetActive(false); _cityBorderUpLeft.SetActive(false); _cityBorderUpRight.SetActive(false); return; } if (!_mapData.GetPlayerDataByTerritoryGridId(_gridData.Id, out var player)) return; var color = Color.red; if(player.Id == _mapData.PlayerMap.SelfPlayerId) color = Color.green; var cityBorderDownLeftRender = _cityBorderDownLeft?.GetComponent(); if (cityBorderDownLeftRender) cityBorderDownLeftRender.color = color; var cityBorderDownRightRender = _cityBorderDownRight?.GetComponent(); if (cityBorderDownRightRender) cityBorderDownRightRender.color = color; var cityBorderUpRightRender = _cityBorderUpRight?.GetComponent(); if (cityBorderUpRightRender) cityBorderUpRightRender.color = color; var cityBorderUpLeftRender = _cityBorderUpLeft?.GetComponent(); if (cityBorderUpLeftRender) cityBorderUpLeftRender.color = color; _cityBorderDownLeft.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,4)); _cityBorderDownRight.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,2)); _cityBorderUpRight.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,6)); _cityBorderUpLeft.SetActive(!_mapData.CheckIfNearByGridSameCity(_gridData,8)); } private void UpdateFog() { if (_mapData?.PlayerMap?.SelfPlayerData?.Sight?.SightGidSet == null || _gridData == null || _fog == null) { LogSystem.LogError($"GridRenderer.UpdateFog: missing map/sight/grid/fog data, gridId={_gridId}"); return; } bool isFog = !_mapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id); if (_fog.activeSelf != isFog) { if (isFog) { _fog.SetActive(true); } else { PlayVFXInSight(new GridVFXParams(GridVFXType.Fog)); //ClearHistoryRenderMark(); if (Timer.Instance == null) { _fog.SetActive(false); } else { Timer.Instance.TimerRegister(this, () => { if (_fog == null || _gridData == null) return; _fog.SetActive(false); if(_gridData.Resource == ResourceType.CityCenter || _gridData.Resource == ResourceType.Treasure) PlayVFXInSight(new GridVFXParams(GridVFXType.Treasure)); },RandomWait,"GridRenderer_UpdateFog"); } } } _land?.SetActive(!isFog); _gridSp?.SetActive(!isFog && _gridData.HasSpType(GridSpType.HakureiRune)); _road?.SetActive(!isFog); _mountain?.SetActive(!isFog); _forest?.SetActive(!isFog); _cityWall?.SetActive(!isFog&&_cityWallMark); _cityBuilding?.SetActive(!isFog); _resource?.SetActive(!isFog); if (isFog) { _borderDownLeft?.SetActive(false); _borderDownRight?.SetActive(false); _borderUpLeft?.SetActive(false); _borderUpRight?.SetActive(false); } else UpdateBorder(); } private void UpdateGridVFX() { //目前仅仅处理Fire这一种VFX var city = _gridData.CityOnGrid(Main.MapData); if (city == null) return; GridVFXPlayType playType = GridVFXPlayType.Play; _gridData.MainSelfPlayerVisibleUnit(out var unit); if(unit == null || unit.Player(Main.MapData) == city.Player(Main.MapData)) playType = GridVFXPlayType.Stop; PlayVFXInSight(new GridVFXParams(GridVFXType.Fire),playType); } public void SetBounceAnim(bool NeedRandomWait=false, bool isLevelupBounce = false) { if (!_ROGrid) return; if (needBounce) return; levelupBounce = isLevelupBounce; if(!NeedRandomWait) _bounceWaitTime = 0f; else { _bounceWaitTime = Random.Range(0,0.3f); } needBounce = true; isBounceDown = true; bounceTime = 0f; bounceUpPos = _ROGrid.transform.position; if(isLevelupBounce) bounceDownPos = new Vector3(_ROGrid.transform.position.x, _ROGrid.transform.position.y - 1.5f, _ROGrid.transform.position.z); else bounceDownPos = new Vector3(_ROGrid.transform.position.x, _ROGrid.transform.position.y - 0.5f, _ROGrid.transform.position.z); } public Vector3 GridVector3() { if (_gridData != null) return _gridData.V3(); return Vector3.zero; } } }