473 lines
20 KiB
C#
473 lines
20 KiB
C#
using Logic;
|
||
using Logic.Multilingual;
|
||
using RuntimeData;
|
||
using TH1_Anim.UnitAtomAnim;
|
||
using TH1_Logic.Core;
|
||
using TH1Renderer;
|
||
using TH1Resource;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
|
||
namespace TH1_Renderer
|
||
{
|
||
public class UnitRenderer
|
||
{
|
||
private uint _unitId;
|
||
private UnitData _unitData;
|
||
private CityData _cityData;
|
||
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 _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.GetCityDataByUnitId(uid,out _cityData);
|
||
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>();
|
||
RenderUpdateUnitAll();
|
||
|
||
}
|
||
|
||
public void Die()
|
||
{
|
||
GameObject.Destroy(_ROUnit.gameObject);
|
||
if(MapRenderer.Instance.ROUnitMap.TryGetValue(_unitId,out var _))
|
||
MapRenderer.Instance.ROUnitMap.Remove(_unitId);
|
||
}
|
||
|
||
|
||
public void Update()
|
||
{
|
||
AnimManager?.Update(_unitMono);
|
||
if (_unitData != null)
|
||
{
|
||
if (_unitData.RenderMark)
|
||
{
|
||
_unitData.RenderMark = false;
|
||
RenderUpdateUnitAll();
|
||
}
|
||
|
||
}
|
||
|
||
//没有任何需要变化的情况,直接return
|
||
//if (!_needBounce && !_needMove && !_needAttack &&!_unitData.RenderMark && !_unitData.AttackRenderMark && !_unitData.BounceRenderMark)return;
|
||
|
||
//GridData curGridData = _gridData;
|
||
//Main.MapData.UnitMap.GetUnitDataByUnitId(_unitId,out _unitData);
|
||
//Main.MapData.GetGridDataByUnitId(_unitId,out _gridData);
|
||
//Main.MapData.GetPlayerDataByUnitId(_unitId,out _playerData);
|
||
|
||
//先处理_unitData的各种renderMark
|
||
/*if (_unitData.BounceRenderMark)
|
||
{
|
||
_unitData.BounceRenderMark = false;
|
||
SetBounceAnim(_unitData.BounceRenderMakrWaitTime);
|
||
_unitData.BounceRenderMakrWaitTime = 0f;
|
||
}
|
||
if (_unitData.RenderMark)
|
||
{
|
||
_unitData.RenderMark = false;
|
||
//如果已经死亡
|
||
if (!_unitData.Alive)
|
||
_ROUnit.SetActive(false);
|
||
else
|
||
{
|
||
//如果需要移动
|
||
if (_gridData != curGridData)
|
||
{
|
||
bool startSight = Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(curGridData.Id);
|
||
bool endSight = Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id);
|
||
//如果移动开始和结束的位置没有视野,直接重置位置
|
||
if (!startSight && !endSight)
|
||
_ROUnit.transform.position = Table.Instance.GridToWorld(_gridData,"isUnit");
|
||
//如果开始没视野,结束有视野,先setActive true
|
||
else if (!startSight && endSight)
|
||
{
|
||
_ROUnit.SetActive(true);
|
||
PlayMoveAnim(_gridData, Table.Instance.AnimDataAssets.MoveAnimTime);
|
||
}
|
||
//如果开始有视野,结束没视野,或者开始结束都有视野 ,交给move结束的时候判断,结束时会根据有没有视野的情况设置自己的active
|
||
else if(startSight)
|
||
{
|
||
_ROUnit.SetActive(true);
|
||
PlayMoveAnim(_gridData, Table.Instance.AnimDataAssets.MoveAnimTime);
|
||
}
|
||
}
|
||
RenderUpdateUnitAll();
|
||
}
|
||
|
||
}
|
||
else if (_unitData.AttackRenderMark)
|
||
{
|
||
_unitData.AttackRenderMark = false;
|
||
SetAttackAnim(_unitData.AttackRenderMarkAttackAnimType,_unitData.AttackRenderMarkTargetPos,_unitData.AttackRenderMarkNeedBack);
|
||
}*/
|
||
|
||
|
||
//处理attack bounce 和move 动画,优先move,然后attack 最后再bounce 三者冲突,必须用if else 独立处理
|
||
/*if (_needMove)
|
||
{
|
||
//Debug.Log($"Moving from {moveStartPos} to {moveEndPos}" );
|
||
moveTime += Time.deltaTime / moveFullTime;
|
||
_ROUnit.transform.position = Vector3.Lerp(moveStartPos, moveEndPos, moveTime);
|
||
if (moveTime >= 1f)
|
||
{
|
||
//Debug.Log($"Unit {_unitId} move completed. In sight: {Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id)}");
|
||
_needMove = false;
|
||
Vector2Int tt = Table.Instance.WorldToGrid(_ROUnit.transform.position, "isUnit");
|
||
if (!Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(_gridData.Id))
|
||
_ROUnit.SetActive(false);
|
||
}
|
||
}
|
||
|
||
else
|
||
if (_needAttack)
|
||
{
|
||
|
||
//如果处在攻击对方状态
|
||
if (_isAttackGo)
|
||
{
|
||
_attackTime += Time.deltaTime / _attackGoFullTime;
|
||
if(_needBack)
|
||
_ROUnit.transform.position = Vector3.Lerp(_attackBackPos, _attackTargetPos, _attackTime * 0.7f);
|
||
else
|
||
_ROUnit.transform.position = Vector3.Lerp(_attackBackPos, _attackTargetPos, _attackTime);
|
||
if (_attackTime >= 1f)
|
||
{
|
||
_isAttackGo = false;
|
||
if (_needBack)
|
||
{
|
||
_isAttackBack = true;
|
||
_attackTime = 0f;
|
||
}
|
||
else
|
||
_needAttack = false;
|
||
}
|
||
}
|
||
//如果已经攻击完毕正在回程
|
||
else if (_isAttackBack)
|
||
{
|
||
_attackTime += Time.deltaTime / _attackBackFullTime;
|
||
_ROUnit.transform.position = Vector3.Lerp(_attackTargetPos, _attackBackPos, _attackTime * 0.7f + 0.3f);
|
||
if (_attackTime >= 1f)
|
||
{
|
||
_isAttackBack = false;
|
||
_needAttack = false;
|
||
}
|
||
}
|
||
//如果远程arrow
|
||
else if (_isAttackArrow)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos,_attackTargetPos,ProjectileType.Arrow,ProjectileMoveType.Parabola);
|
||
_isAttackArrow = false;
|
||
_needAttack = false;
|
||
}
|
||
else if (_isAttackBomb)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos,_attackTargetPos,ProjectileType.Bomb,ProjectileMoveType.Parabola);
|
||
_isAttackBomb = false;
|
||
_needAttack = false;
|
||
}
|
||
else if (_isAttackRemilia)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos,_attackTargetPos,ProjectileType.RemiliaAttack,ProjectileMoveType.Straight);
|
||
_isAttackRemilia = false;
|
||
_needAttack = false;
|
||
}
|
||
else if (_isAttackPatchouli)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos,_attackTargetPos,ProjectileType.PatchouliAttack,ProjectileMoveType.Straight);
|
||
_isAttackPatchouli = false;
|
||
_needAttack = false;
|
||
}
|
||
else if (_isAttackMokou)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos,_attackTargetPos,ProjectileType.MokouAttack,ProjectileMoveType.Straight);
|
||
_isAttackPatchouli = false;
|
||
_needAttack = false;
|
||
}
|
||
else if (_isAttackReisen)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos,_attackTargetPos,ProjectileType.ReisenAttack,ProjectileMoveType.Straight);
|
||
_isAttackPatchouli = false;
|
||
_needAttack = false;
|
||
}
|
||
else if (_isAttackKaguya)
|
||
{
|
||
MapRenderer.Instance.ProjectileManager.CreateProjectile(_attackBackPos + Vector3.up * 1f,_attackTargetPos + Vector3.up * 1f,ProjectileType.KaguyaAttack,ProjectileMoveType.Straight);
|
||
_isAttackPatchouli = false;
|
||
_needAttack = false;
|
||
}
|
||
|
||
}
|
||
else
|
||
if (_needBounce)
|
||
{
|
||
if (_bounceWaitTime > 0){
|
||
_bounceWaitTime -= Time.deltaTime;
|
||
}
|
||
else
|
||
if (_isBounceDown)
|
||
{
|
||
bounceTime += Time.deltaTime / bounceDownFullTime;
|
||
_ROUnit.transform.position = Vector3.Lerp(bounceUpPos, bounceDownPos, bounceTime);
|
||
if (bounceTime >= 1f)
|
||
{
|
||
_isBounceDown = false;
|
||
bounceTime = 0f;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
bounceTime += Time.deltaTime / bounceUpFullTime;
|
||
_ROUnit.transform.position = Vector3.Lerp(bounceDownPos, bounceUpPos, bounceTime);
|
||
if (bounceTime >= 1f)
|
||
_needBounce = false;
|
||
|
||
}
|
||
}
|
||
*/
|
||
|
||
}
|
||
|
||
public void RenderUpdateUnitAll()
|
||
{
|
||
if (_unitData == null) return;
|
||
|
||
renderVeteran = _unitData.Veteran;
|
||
RenderUpdateUnitInfo();
|
||
|
||
|
||
//更新图像
|
||
RenderUpdateUnitSrpite();
|
||
//更新防御显示信息
|
||
RenderUpdateUnitDefense();
|
||
//更新高亮
|
||
RenderUpdateUnitGlow();
|
||
|
||
//初拉单位和selfplayer的视野关系
|
||
RenderUpdateSelfPlayerSight();
|
||
//DebugRender
|
||
RenderUpdateDebug();
|
||
|
||
|
||
|
||
}
|
||
|
||
public void RenderUpdateUnitInfo()
|
||
{
|
||
_unitMono.HealthText.text = _unitData.Health.ToString();
|
||
//处理血量的颜色。如果血量<一半且<5,那么赋予红色,否则白色
|
||
if(_unitData.Health < 5 && _unitData.Health < _unitData.GetMaxHealth() / 2)
|
||
_unitMono.HealthText.color = Color.red;
|
||
else
|
||
_unitMono.HealthText.color = Color.white;
|
||
//根据敌我情况更新infoBG的颜色
|
||
//_unitInfoBGImg.sprite = (Main.MapData.SameUnion(_playerData.Id , Main.MapData.PlayerMap.SelfPlayerId)) ? ResourceCache.Instance.SpriteCache.UnitInfoSelf :
|
||
if(!Main.MapData.GetPlayerDataByUnitId(_unitData.Id,out var playerData))return;
|
||
if (playerData.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
_unitMono.UnitInfoBGImg.material = ResourceCache.Instance.MatCache.GradientBG_Blue;
|
||
else
|
||
_unitMono.UnitInfoBGImg.material = (Main.MapData.SameUnion(playerData.Id , Main.MapData.PlayerMap.SelfPlayerId)) ? ResourceCache.Instance.MatCache.GradientBG_Green :
|
||
ResourceCache.Instance.MatCache.GradientBG_Red;
|
||
|
||
|
||
|
||
//如果是盟友,额外显示盟友标记
|
||
|
||
var showUnionIcon = Main.MapData.SameUnion(playerData.Id, Main.MapData.PlayerMap.SelfPlayerId) &&
|
||
playerData.Id != Main.MapData.PlayerMap.SelfPlayerId;
|
||
_unitMono.UnionIcon.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 void RenderUpdateSelfPlayerSight()
|
||
{
|
||
if (!Main.MapData.GetGridDataByUnitId(_unitData.Id, out var gridData)) return;
|
||
if (!Main.MapData.PlayerMap.SelfPlayerData.Sight.CheckIsInSight(gridData.Id))
|
||
_unitMono.gameObject.SetActive(false); //如果不在玩家视野,就暂时隐藏这个单位的显示
|
||
else
|
||
_unitMono.gameObject.SetActive(true);
|
||
}
|
||
public void RenderUpdateUnitGlow()
|
||
{
|
||
var player = _unitData.Player(Main.MapData);
|
||
if (player == null) return;
|
||
bool isSelfPlayer = (player == Main.MapData.PlayerMap.SelfPlayerData);
|
||
|
||
//如果MP>0 或者周围有可以攻击的目标,或者可以移动的目标,或者说可以占领城市
|
||
if (_unitData.MP > 0
|
||
|| MapRenderer.Instance.CheckUnitHasMoveAttackTarget(_unitId)
|
||
|| MapRenderer.Instance.CheckUnitHasSpecialUnitActionTarget(_unitId))
|
||
{
|
||
|
||
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;
|
||
if (isSelfPlayer)
|
||
_unitMono.SpriteRenderer.material = ResourceCache.Instance.MatCache.TH1URPShaders_Sprite_Glow;
|
||
|
||
}
|
||
else
|
||
{
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out var sprite))
|
||
return;
|
||
_unitMono.SpriteRenderer.sprite = sprite;
|
||
_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 RenderUpdateUnitSrpite()
|
||
{
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitSprite(Main.MapData, _unitData, out var sprite))
|
||
return;
|
||
_unitMono.SpriteRenderer.sprite = sprite;
|
||
}
|
||
|
||
public void RenderUpdateUnitDefense()
|
||
{
|
||
float defenseBonus = _unitData.GetExtraDefense(Main.MapData);
|
||
switch (defenseBonus)
|
||
{
|
||
case 1.0f:
|
||
_ROUnit.transform.Find("Defense").gameObject.SetActive(false);
|
||
_ROUnit.transform.Find("SuperDefense").gameObject.SetActive(false);
|
||
break;
|
||
case 1.5f:
|
||
_ROUnit.transform.Find("Defense").gameObject.SetActive(true);
|
||
_ROUnit.transform.Find("SuperDefense").gameObject.SetActive(false);
|
||
break;
|
||
case 4.0f:
|
||
_ROUnit.transform.Find("Defense").gameObject.SetActive(false);
|
||
_ROUnit.transform.Find("SuperDefense").gameObject.SetActive(true);
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
public Vector3 GetPosition()
|
||
{
|
||
return _ROUnit.transform.position;
|
||
}
|
||
|
||
}
|
||
} |