385 lines
14 KiB
C#
385 lines
14 KiB
C#
using Logic;
|
||
using Logic.Multilingual;
|
||
using Logic.Skill;
|
||
using RuntimeData;
|
||
using TH1_Anim.UnitAtomAnim;
|
||
using TH1_Logic.Core;
|
||
using TH1Renderer;
|
||
using TH1Resource;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace TH1_Renderer
|
||
{
|
||
public class UnitRenderer
|
||
{
|
||
private uint _unitId;
|
||
private UnitData _unitData;
|
||
private PlayerData _playerData;
|
||
private GridData _gridData;
|
||
private GameObject _ROUnit;
|
||
private UnitMono _unitMono;
|
||
|
||
//------- 表现层RenderData ---------//
|
||
public bool IsAttackHighlight = false;
|
||
public bool IsSelectHighlight = false;
|
||
public bool IsAllyHighlight = false;
|
||
|
||
//--------------- AnimManager ----------------
|
||
public UnitAnimManager AnimManager;
|
||
|
||
|
||
private Vector3 originalPosition; // 记录初始位置
|
||
|
||
SpriteEffectController effectController;
|
||
|
||
//------bounce相关参数--------
|
||
bool _needBounce = false, _isBounceDown = true;
|
||
Vector3 bounceUpPos, bounceDownPos;
|
||
private float _bounceWaitTime = 0f;
|
||
float bounceTime = 0f;
|
||
|
||
|
||
bool _needMove = false;
|
||
Vector3 moveStartPos, moveEndPos;
|
||
float moveTime = 0f;
|
||
float moveFullTime = 0.3f;
|
||
bool renderVeteran = false;
|
||
private bool _isGlow = false;
|
||
|
||
private bool _needAttack = false;
|
||
private AttackAnimType _attackAnimType = AttackAnimType.None;
|
||
private float _attackTime = 0f;
|
||
private bool _isAttackGo = false;
|
||
private bool _isAttackBack = false;
|
||
private bool _isAttackArrow = false;
|
||
private bool _isAttackBomb = false;
|
||
private bool _isAttackRemilia = false;
|
||
private bool _isAttackPatchouli = false;
|
||
private bool _isAttackMokou = false;
|
||
private bool _isAttackReisen = false;
|
||
private bool _isAttackKaguya = false;
|
||
|
||
|
||
private Vector3 _attackTargetPos, _attackBackPos;
|
||
private bool _needBack;
|
||
private float _attackGoFullTime = 0.15f;
|
||
private float _attackBackFullTime = 0.15f;
|
||
|
||
public UnitRenderer(GameObject prefab,Transform father, uint uid)
|
||
{
|
||
_unitId = uid;
|
||
Main.MapData.UnitMap.GetUnitDataByUnitId(uid,out _unitData);
|
||
Main.MapData.GetPlayerDataByUnitId(uid, out _playerData);
|
||
Main.MapData.GetGridDataByUnitId(uid,out _gridData);
|
||
|
||
AnimManager = new UnitAnimManager();
|
||
|
||
Vector3 tpos = Table.Instance.GridToWorld(_gridData,"isUnit");
|
||
_ROUnit = GameObject.Instantiate(prefab, tpos, Quaternion.identity, father);
|
||
_unitMono = _ROUnit?.GetComponent<UnitMono>();
|
||
//InstantUpdateUnit(false);
|
||
|
||
}
|
||
|
||
public void Die()
|
||
{
|
||
//_ROUnit.gameObject.SetActive(false);
|
||
//Debug.Log("Delete !!!" + _unitData.Id + " name = " + _ROUnit.name + "; ID = " + _ROUnit.GetInstanceID());
|
||
//Debug.Log(_ROUnit.transform.Find("UnitSprite").GetComponent<SpriteRenderer>().sprite);
|
||
//_unitMono = null;
|
||
//Debug.Break();
|
||
|
||
GameObject.Destroy(_ROUnit.gameObject);
|
||
|
||
if(MapRenderer.Instance.ROUnitMap.TryGetValue(_unitId,out var _))
|
||
MapRenderer.Instance.ROUnitMap.Remove(_unitId);
|
||
_unitData = null;
|
||
}
|
||
|
||
public void InstantDisappear()
|
||
{
|
||
_ROUnit.SetActive(false);
|
||
}
|
||
|
||
public void InstantShow()
|
||
{
|
||
_ROUnit.SetActive(true);
|
||
}
|
||
|
||
public void Update()
|
||
{
|
||
AnimManager?.Update(_unitMono);
|
||
}
|
||
|
||
public void RenderUpdateUnitDefense()
|
||
{
|
||
if (_unitData == null || !_unitData.IsAlive()) return;
|
||
_unitMono.UpdateUnitDefense(_unitData.GetDefenseMultiplicationParam(Main.MapData));
|
||
}
|
||
|
||
public void RenderUpdateUnitImage()
|
||
{
|
||
if (_unitData == null ) return;
|
||
|
||
RenderUpdateUnitInfo();
|
||
|
||
|
||
//更新图像
|
||
RenderUpdateUnitSprite();
|
||
//更新防御显示信息
|
||
RenderUpdateUnitDefense();
|
||
//更新高亮
|
||
RenderUpdateUnitGlow();
|
||
//DebugRender
|
||
RenderUpdateDebug();
|
||
}
|
||
|
||
//这个会同时处理非player mapData的情况
|
||
//瞬间更新unit的视觉(不包括pos,不包括die,但是包括showoff) showoff开关,如果=true,先判断是否显隐,更新显隐,再决定更新image 如果=false,仅更新image,不处理显隐
|
||
//如果unit死了,不能直接die!!要等动画那边主动凋起才可以die
|
||
public bool InstantUpdateUnit(bool showoff)
|
||
{
|
||
//如果要做显隐更新,先判断显隐,显的情况下,再更新image
|
||
//如果不做显隐更新,直接更新image
|
||
if ((showoff && RenderUpdateUnitShowOff())
|
||
|| !showoff)
|
||
RenderUpdateUnitImage();
|
||
return _unitData != null && _unitData.InMainSight();
|
||
|
||
}
|
||
|
||
//瞬间更新unit的 die的情况
|
||
public bool InstantUpdateTryDie()
|
||
{
|
||
if (_unitData == null || !_unitData.IsAlive())
|
||
{
|
||
Die();
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//瞬间更新unit的pos到最新 最正确的位置
|
||
public void InstantUpdateUnitPos()
|
||
{
|
||
RenderUpdateUnitPosition();
|
||
}
|
||
|
||
public void RenderUpdateUnitInfo()
|
||
{
|
||
if (!_unitMono?.HealthText || !_unitMono?.UnitInfoBG) return;
|
||
_unitMono.HealthText.text = _unitData.Health.ToString();
|
||
//处理血量的颜色。如果血量<一半且<5,那么赋予红色,否则白色
|
||
if(_unitData.Health < 5 && _unitData.Health < _unitData.GetMaxHealth() / 2)
|
||
_unitMono.HealthText.color = _unitMono.UnitLowHealth;
|
||
else
|
||
_unitMono.HealthText.color = Color.white;
|
||
|
||
Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.UnitFullType, out var unitInfo);
|
||
var chessType = unitInfo.ChessType;
|
||
if (chessType == ChessType.None)
|
||
{
|
||
if(Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.CarryUnitFullType, out var carryUnitInfo))
|
||
chessType = carryUnitInfo.ChessType;
|
||
}
|
||
if (chessType != ChessType.None)
|
||
{
|
||
Table.Instance.UnitTypeDataAssets.GetChessTypeInfo(chessType ,out var chessInfo);
|
||
_unitMono.ChessImg.sprite = chessInfo.ChessSprite;
|
||
}
|
||
|
||
|
||
//根据敌我情况更新infoBG的颜色
|
||
//_unitInfoBGImg.sprite = (Main.MapData.SameUnion(_playerData.Id , Main.MapData.PlayerMap.SelfPlayerId)) ? ResourceCache.Instance.SpriteCache.UnitInfoSelf :
|
||
if (Main.MapData == null) return;
|
||
if (!Main.MapData.GetPlayerDataByUnitId(_unitData.Id, out var playerData)) return;
|
||
var col = _unitMono.UnitBGBlue;
|
||
if (playerData.Id != Main.MapData.PlayerMap.SelfPlayerId)
|
||
col =(Main.MapData.SameUnion(playerData.Id, Main.MapData.PlayerMap.SelfPlayerId))
|
||
? _unitMono.UnitBGGreen
|
||
: _unitMono.UnitBGRed;
|
||
_unitMono.ChessBG.color = col;
|
||
_unitMono.UnitInfoBG.color = col;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//如果是盟友,额外显示盟友标记
|
||
|
||
var showUnionIcon = Main.MapData.SameUnion(playerData.Id, Main.MapData.PlayerMap.SelfPlayerId) &&
|
||
playerData.Id != Main.MapData.PlayerMap.SelfPlayerId;
|
||
_unitMono.UnionBG.SetActive(showUnionIcon);
|
||
|
||
//更改兵种显示文字
|
||
if(Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_unitData.UnitType,_unitData.GiantType,_unitData.UnitLevel,out var info))
|
||
MultilingualManager.Instance.SetUIText(_unitMono.UnitInfoName,info.Name);
|
||
}
|
||
|
||
public void RenderUpdateDebug()
|
||
{
|
||
if (DebugCenter.Instance.DebugMode)
|
||
{
|
||
if(!_unitMono.RODebugText.activeSelf)
|
||
_unitMono.RODebugText.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
_unitMono.RODebugText.SetActive(false);
|
||
return;
|
||
}
|
||
|
||
_unitMono.DebugText.text = "";
|
||
_unitMono.DebugText.text += $"ID{_unitId} AP{_unitData.AP} MP{_unitData.MP} CP{_unitData.MP}\n";
|
||
|
||
//如果不是我方单位,显示军团及unit的战略
|
||
_unitMono.DebugText.text += $"Lid={_unitData.LegionId}\n";
|
||
if(!Main.MapData.CheckUnitIdBelongPlayerId(_unitData.Id,Main.MapData.PlayerMap.SelfPlayerData.Id))
|
||
if (MainEditor.Instance.Data != null)
|
||
{
|
||
MainEditor.Instance.GetUnitStrategy(_unitId, _unitData.LegionId, _playerData.Id, out var st,
|
||
out var tar, out var type);
|
||
_unitMono.DebugText.text += $"ST:{st} TAR:{tar} TYPE:{type}";
|
||
}
|
||
}
|
||
public bool RenderUpdateUnitShowOff()
|
||
{
|
||
if (_unitData == null || _unitMono == null)
|
||
return false;
|
||
bool ret = _unitData.InMainSight();
|
||
_unitMono.gameObject.SetActive(ret); //如果不在玩家视野,就暂时隐藏这个单位的显示
|
||
return ret;
|
||
}
|
||
public void RenderUpdateUnitGlow()
|
||
{
|
||
var player = _unitData.Player(Main.MapData);
|
||
if (player == null) return;
|
||
Sprite sprite;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out sprite))
|
||
return;
|
||
_unitMono.SpriteRenderer.sprite = sprite;
|
||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Default;
|
||
_isGlow = false;
|
||
|
||
//首先处理玩家(判断是否置灰或者高亮)
|
||
if (player.IsSelfPlayer())
|
||
{
|
||
//如果MP>0 或者周围有可以攻击的目标,或者可以移动的目标,或者说可以占领城市
|
||
if (_unitData.MP > 0
|
||
|| MapRenderer.Instance.CheckUnitHasMoveAttackTarget(_unitId)
|
||
|| MapRenderer.Instance.CheckUnitHasSpecialUnitActionTarget(_unitId))
|
||
{
|
||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_Glow;
|
||
_isGlow = true;
|
||
|
||
}
|
||
else
|
||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_WhiteOverlay;
|
||
}
|
||
//然后处理AI(主要就判断是否置灰)
|
||
else
|
||
{
|
||
//如果是正在行动的AI
|
||
if (Main.MapData.CurPlayer == player)
|
||
{
|
||
if(_unitData.MP == 0 && _unitData.CP == 0 && _unitData.AP == 0 && _unitData.MP == 0)
|
||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_WhiteOverlay;
|
||
}
|
||
else
|
||
//如果是还没行动的AI
|
||
if(Main.MapData.GetPlayerHasActedInBigTurn(player))
|
||
{
|
||
//啥都不做
|
||
}
|
||
//否则是已经行动过的AI
|
||
else
|
||
{
|
||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_WhiteOverlay;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public void RenderUpdataHighlight()
|
||
{
|
||
_unitMono.AttackHighlight.SetActive(IsAttackHighlight);
|
||
_unitMono.SelectHighlight.SetActive(IsSelectHighlight);
|
||
_unitMono.AllyHighlight.SetActive(IsAllyHighlight);
|
||
}
|
||
|
||
public void SetSelectHighlight(bool v)
|
||
{
|
||
if (IsSelectHighlight == v)
|
||
return;
|
||
IsSelectHighlight = v;
|
||
MapRenderer.Instance.HighlightUnitIdSet.Add(_unitId);
|
||
MapRenderer.Instance.HighlightUnitIdSetRenderMark = true;
|
||
}
|
||
|
||
public void SetAttackHighlight(bool v)
|
||
{
|
||
if (IsAttackHighlight == v)
|
||
return;
|
||
IsAttackHighlight = v;
|
||
MapRenderer.Instance.HighlightUnitIdSet.Add(_unitId);
|
||
MapRenderer.Instance.HighlightUnitIdSetRenderMark = true;
|
||
}
|
||
|
||
public void SetAllyHighlight(bool v)
|
||
{
|
||
if (IsAllyHighlight == v)
|
||
return;
|
||
IsAllyHighlight = v;
|
||
MapRenderer.Instance.HighlightUnitIdSet.Add(_unitId);
|
||
MapRenderer.Instance.HighlightUnitIdSetRenderMark = true;
|
||
}
|
||
|
||
public void RenderUpdateUnitSprite()
|
||
{
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out var sprite))
|
||
return;
|
||
_unitMono.SpriteRenderer.sprite = sprite;
|
||
//RenderUpdateUnitSpecialSprite();
|
||
|
||
}
|
||
|
||
public void RenderUpdateUnitSpecialSprite()
|
||
{
|
||
if (_unitData.UnitFullType.GiantType != GiantType.EgyptianMeiling) return;
|
||
if (!_unitData.GetSkill(SkillType.MEILINGREST, out var skill)) return;
|
||
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out var sprite))
|
||
return;
|
||
_unitMono.SpriteRenderer.sprite = sprite;
|
||
|
||
//为红美铃做额外处理
|
||
var meilingRest = skill as MeilingRestSkill;
|
||
if (meilingRest?.Sleeping ?? false)
|
||
_unitMono.SpriteRenderer.sprite = ResourceCache.Instance.SpriteCache.MeilingZzz;
|
||
}
|
||
|
||
public void RenderUpdateUnitPosition()
|
||
{
|
||
var t = _unitData.Grid(Main.MapData)?.Pos;
|
||
if (t == null) return;
|
||
_unitMono.transform.position = Table.Instance.GridPosToWorld(new Vector2Int(t.X,t.Y),"isUnit");
|
||
}
|
||
|
||
public Vector3 GetPosition()
|
||
{
|
||
return _ROUnit.transform.position;
|
||
}
|
||
|
||
public bool isGlow()
|
||
{
|
||
return _isGlow;
|
||
}
|
||
|
||
}
|
||
} |