TH1/Unity/Assets/Scripts/TH1_Renderer/UnitRenderer.cs
2025-09-26 22:04:28 +08:00

473 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}