动画逻辑迭代 探索动画更新

This commit is contained in:
kawagiri 2025-10-10 23:08:50 +08:00
parent 160892af6e
commit 1fc2b26844
8 changed files with 248 additions and 81 deletions

View File

@ -29,6 +29,7 @@ namespace TH1_Anim
Die,
CityConnectExpUp,
CityConnectExpDown,
MoveExplorer,
Max
}
@ -51,6 +52,7 @@ namespace TH1_Anim
FragmentType.Die => new FragmentDie(data as FragmentUnitData),
FragmentType.CityConnectExpUp => new FragmentCityConnectExpUp(data as FragmentCityExpUpData),
FragmentType.CityConnectExpDown => new FragmentCityConnectExpUp(data as FragmentCityExpUpData),
FragmentType.MoveExplorer => new FragmentMoveExplorer(data as FragmentMoveExplorerData),
_ => null
};
}

View File

@ -73,6 +73,16 @@ namespace TH1_Anim
return null;
}
public static IFragmentData Create(FragmentType type,GameObject obj,GridData originGrid,GridData targetGrid,FragmentMoveExplorerType moveType = FragmentMoveExplorerType.NormalMove)
{
if (type == FragmentType.MoveExplorer)
{
return new FragmentMoveExplorerData(type,obj,originGrid,targetGrid,moveType);
}
Debug.Log("错误的fragmentType fragmentData创建失败#5");
return null;
}
}
public abstract class IFragmentData
@ -112,6 +122,25 @@ namespace TH1_Anim
}
}
public enum FragmentMoveExplorerType {FirstMove,NormalMove,LastMove }
public class FragmentMoveExplorerData : IFragmentData
{
public GameObject Explorer;
public GridData OriginGrid;
public GridData TargetGrid;
public FragmentMoveExplorerType MoveType;
public FragmentMoveExplorerData(FragmentType type, GameObject explorer,GridData originGrid,GridData targetGrid,FragmentMoveExplorerType moveType = FragmentMoveExplorerType.NormalMove) : base(type)
{
Explorer = explorer;
OriginGrid = originGrid;
TargetGrid = targetGrid;
MoveType = moveType;
}
}
//Attack AttackAndCounter MoveKill NotMoveKill 共用这个
public class FragmentAttackAndCounterData : IFragmentData
{

View File

@ -83,7 +83,7 @@ namespace TH1_Anim.Fragments
}
//Step #2 第二个动画(瞬时) update表现
if (progressTime >= _step1_time && !_step2_update)
if (progressTime >= _step2_time && !_step2_update)
{
_step2_update = true;
Data.UnitRenderer.RenderUpdateUnitAll();

View File

@ -0,0 +1,106 @@
/*
* @Author:
* @Description:
* @Date: 20250701 14:07:05
* @Modify:
*/
using Logic.Audio;
using RuntimeData;
using TH1_Anim.UnitAtomAnim;
using TH1_DataAssetsScript;
using TH1_Logic.Core;
using TH1_Renderer.UnitAtomAnim;
using TH1Renderer;
using UnityEngine;
namespace TH1_Anim.Fragments
{
//用于探索者Explorer的每一次单次移动
public class FragmentMoveExplorer : FragmentBase
{
public FragmentMoveExplorerData Data;
private bool _step1_move;
private bool _step2_update;
private float _step1_time;
private float _step2_time;
public FragmentMoveExplorer(FragmentMoveExplorerData data) : base()
{
Data = data;
if (Data.Explorer == null || Data.OriginGrid == null || Data.TargetGrid == null)
{
State = FragmentState.Wrong;
return;
};
_step1_move = false;
_step1_time = Data.MoveType == FragmentMoveExplorerType.FirstMove ? 0.1f : 0.2f;
_step2_time = _step1_time + Table.Instance.AnimDataAssets.MoveAnimTime;
Duration = _step2_time;
State = FragmentState.Prepare;
}
public override bool CheckDone(float progressTime)
{
if (!_step1_move || !_step2_update)
return false;
if (progressTime <= Duration)
return false;
return true;
}
public override void OnFinished()
{
}
public override void OnUpdate(float progressTime)
{
//Step #0 处理超时情况2倍时长
if (progressTime > Duration + 10f)
{
_step1_move = true;
_step2_update = true;
return;
}
//Step #1 第一个动画播放move
if (progressTime >= _step1_time && !_step1_move)
{
_step1_move = true;
MapRenderer.Instance.CameraController.CameraFocusOnGrid(Data.TargetGrid);
if(Data.MoveType == FragmentMoveExplorerType.FirstMove)
Data.OriginGrid.Renderer(Main.MapData)?.PlayVFX(new GridVFXParams(GridVFXType.Fog));
//AUDIO 播放移动音效
AudioManager.Instance.PlayAudio("SFX/UNIT_move");
return;
}
//Step #1.5 渲染explorer的移动
if (progressTime >= 0 && progressTime < _step2_time && _step1_move)
{
float t = (progressTime - _step1_time) / (_step2_time - _step1_time);
if(Data.Explorer?.transform != null)
Data.Explorer.transform.position = Vector3.Lerp(Data.OriginGrid.V3(),Data.TargetGrid.V3(), t);
}
//Step #2 第二个动画(瞬时) update表现
if (progressTime >= _step2_time && !_step2_update)
{
_step2_update = true;
if (Data.MoveType == FragmentMoveExplorerType.LastMove)
{
Object.Destroy(Data.Explorer);
Data.TargetGrid.Renderer(Main.MapData)?.PlayVFX(new GridVFXParams(GridVFXType.Fog));
}
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 66093d9b74140e447abfba82d982828e
timeCreated: 1751340289

View File

@ -1122,9 +1122,7 @@ namespace Logic.Action
if (_actionId.CityLevelUpActionType == CityLevelUpActionType.Explorer)
{
// 1. 锁定玩家输入
Main main = GameObject.FindObjectOfType<Main>();
main.InputLogic.LockInput();
//Debug.Log("玩家输入已锁定");
//main.InputLogic.LockInput();
// 2. 创建临时探索者图像3秒后自动销毁
MapRenderer.Instance.CreateTemporaryExplorer(gridData, 3f);

View File

@ -824,6 +824,16 @@ namespace Logic
if (dip.DiplomacyState == DiplomacyState.League) coin *= 2;
return coin;
}
public void TryAddMeetPlayer(MapData map, PlayerData p1, GridData p2)
{
var unit = p2.Unit(map);
var city = p2.CityOnGrid(map);
if(unit != null && unit.Player(map) != null && !p1.MeetPlayers.Contains(unit.Player(map).Id))
AddMeetPlayer(map,p1,unit.Player(map));
if(city != null && city.Player(map) != null && !p1.MeetPlayers.Contains(city.Player(map).Id))
AddMeetPlayer(map,p1,city.Player(map));
}
public void AddMeetPlayer(MapData map, PlayerData p1, PlayerData p2)
{
@ -1153,10 +1163,11 @@ namespace Logic
foreach (var id in gidList)
{
if (!playerData.Sight.SightGidSet.Add(id)) continue;
count++;
if (!mapData.GridMap.GetGridDataByGid(id, out var gridData)) continue;
if (!mapData.GetCapitalCityDataByPlayerId(playerData.Id, out var city)) continue;
//如果是真人玩家,加入地块被新显示的播放队列
if (Main.MapData == mapData && playerData.IsSelfPlayer())
@ -1165,30 +1176,19 @@ namespace Logic
PresentationManager.EnqueueTask(new FragmentSequencerTask(FragmentFactory.Create(FragmentType.GridUpdate, data)));
}
//尝试判断gridData有没有带来新的meetplayerList
TryAddMeetPlayer(mapData, playerData, gridData);
//处理发现tower的情况
if (gridData.Resource == ResourceType.Tower)
{
Main.CityLogic.GridGiveCityExp(mapData,playerData,gridData,city,1);
/*Main.CityLogic.CityUpdateExp(mapData,city,1);
//如果是真map真人玩家播放获得exp动画
if (mapData.IsCurrentShowMap() && playerData.IsSelfPlayer())
{
if (MapRenderer.Instance.ROGridMap.TryGetValue(gridData.Id, out var originGridRenderer)
&& mapData.GetGridDataByCityId(city.Id, out var g2)
&& MapRenderer.Instance.ROGridMap.TryGetValue(g2?.Id ?? 0, out var targetGridRenderer)
&& MapRenderer.Instance.ROCityInfoMap.TryGetValue(city.Id, out var targetCityInfoRenderer))
{
var data = FragmentDataFactory.Create(FragmentType.CityExp, originGridRenderer, targetGridRenderer,targetCityInfoRenderer);
PresentationManager.EnqueueTask(new FragmentSequencerTask(FragmentFactory.Create(FragmentType.CityExp,data)));
}
}*/
//更新奇观情况,可能弹出奇观通知
UpdateWonder(mapData,playerData);
}
// TODOTODOTODO
}
//更新视野后,要更新联通情况

View File

@ -6,7 +6,10 @@ using UnityEngine.SceneManagement;
using RuntimeData;
using Logic;
using Logic.CrashSight;
using TH1_Anim;
using TH1_Core.Managers;
using TH1_Logic.Core;
using TH1_Presentation.Sequencer.Task;
using TH1_Renderer;
using TH1Resource;
using UnityEngine.UI;
@ -210,7 +213,7 @@ namespace TH1Renderer
}
// 处理探索者移动
if (_explorerIsMoving && _temporaryExplorer != null)
/*if (_explorerIsMoving && _temporaryExplorer != null)
{
_explorerMoveTime += Time.deltaTime;
float t = Mathf.Clamp01(_explorerMoveTime / _explorerMoveDuration);
@ -261,7 +264,7 @@ namespace TH1Renderer
_main.InputLogic.UnlockInput();
}
}
}
}*/
//-------- 处理UI数据 ---------//
//处理高亮
@ -290,19 +293,7 @@ namespace TH1Renderer
if (_mapData.UnitMap.UnitMapRenderMark)
{
_mapData.UnitMap.UnitMapRenderMark = false;
//检查有无单位销毁
//var t = ROUnitMap;
/*List<uint> toRemove = new List<uint>();
foreach (var roUnitId in ROUnitMap.Keys)
{
if (!Main.MapData.UnitMap.GetUnitDataByUnitId(roUnitId, out var unitData))
toRemove.Add(roUnitId);
}
foreach (var roUnitId in toRemove)
{
ROUnitMap.Remove(roUnitId);
}*/
//更新新增单位
RenderUpdateUnitMap();
}
@ -519,64 +510,101 @@ namespace TH1Renderer
// 创建临时探索者并向视野最少的方向移动
public void CreateTemporaryExplorer(GridData gridData, float maxDuration)
{
// 获取玩家数据 - 使用领土所属关系获取
// Step #1 鲁棒性判断
if (!Main.MapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var playerData))
{
Debug.LogWarning("无法获取玩家数据,无法创建探索者");
return;
}
// 检查是否是自己的玩家
bool isSelfPlayer = playerData.Id == Main.MapData.PlayerMap.SelfPlayerData.Id;
// Step #2 如果不是自己的玩家直接计算10步探索并更新视野不进行渲染
// 如果不是自己的玩家直接计算10步探索并更新视野不进行渲染
if (!isSelfPlayer)
// 重置移动计数和当前目标格子
_explorerMoveCount = 0;
_currentTargetGridData = gridData;
_explorerPreviousPosition = new Vector2Int(-1, -1);
GameObject spriteObject;
//如果是真人玩家,提前设置对象
if (playerData.IsSelfPlayer())
{
//Debug.Log("非自己玩家的探索者,直接计算探索路径");
// 重置移动计数和当前目标格子
_explorerMoveCount = 0;
_currentTargetGridData = gridData;
_explorerPreviousPosition = new Vector2Int(-1, -1);
// 直接计算10步探索
for (int i = 0; i < _explorerMaxMoves; i++)
{
// 如果当前目标格子为空,结束探索
if (_currentTargetGridData == null)
break;
// 计算下一步移动
Vector2Int currentPos = new Vector2Int(_currentTargetGridData.Pos.X, _currentTargetGridData.Pos.Y);
// 更新视野
Main.PlayerLogic.UpdateSightByRadius(Main.MapData, playerData, _currentTargetGridData, 1);
// 保存当前位置作为上一个位置
Vector2Int prevPos = currentPos;
_explorerPreviousPosition = prevPos;
// 计算下一步移动方向(不渲染,只计算)
CalculateNextExplorerMove(_currentTargetGridData, playerData, out var nextGridData);
// 如果无法移动,结束探索
if (nextGridData == null)
break;
// 更新当前目标格子
_currentTargetGridData = nextGridData;
_explorerMoveCount++;
}
// 完成探索后解锁输入 ,只有是玩家才需要解锁输入
if(playerData.Id == Main.MapData.PlayerMap.SelfPlayerId)
_main.InputLogic.UnlockInput();
return;
_temporaryExplorer = new GameObject("TemporaryExplorer");
_temporaryExplorer.transform.position = Table.Instance.GridToWorld(gridData, "isUnit");
_temporaryExplorer.transform.SetParent(_unitRenderMap, false);
spriteObject = new GameObject("UnitSprite");
spriteObject.transform.SetParent(_temporaryExplorer.transform, false);
SpriteRenderer spriteRenderer = spriteObject.AddComponent<SpriteRenderer>();
//把小人图像位置下移一点
spriteObject.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
var t = spriteObject.transform.localPosition;
t.y -= 0.4f;
spriteObject.transform.localPosition = t;
// 设置explorer的sprite
UnitType explorerUnitType = UnitType.Warrior; // 使用战士单位类型
if (Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(explorerUnitType, GiantType.None, 0, out var unitTypeInfo)
&& Table.Instance.UnitTypeDataAssets.GetUnitSpriteByInfo(unitTypeInfo, playerData, out var sprite))
spriteRenderer.sprite = sprite;
}
// 直接计算10步探索
for (int i = 0; i < _explorerMaxMoves; i++)
{
// 如果当前目标格子为空,结束探索
if (_currentTargetGridData == null)
break;
// 计算下一步移动
Vector2Int currentPos = new Vector2Int(_currentTargetGridData.Pos.X, _currentTargetGridData.Pos.Y);
// 保存当前位置作为上一个位置
Vector2Int prevPos = currentPos;
_explorerPreviousPosition = prevPos;
// 计算下一步移动方向(不渲染,只计算)
CalculateNextExplorerMove(_currentTargetGridData, playerData, out var nextGridData);
//Step #5 处理视觉(只有自己玩家才会做
if (playerData.IsSelfPlayer())
{
// 如果无法移动,结束探索 TODO 有一点点风险,之后处理吧 现在无法移动就改成原地移动了
if (nextGridData == null)
nextGridData = _currentTargetGridData;
bool lastMove = i + 1 == _explorerMaxMoves;
FragmentMoveExplorerType moveType = FragmentMoveExplorerType.NormalMove;
if(i == 0)
moveType = FragmentMoveExplorerType.FirstMove;
if (i + 1 == _explorerMaxMoves)
moveType = FragmentMoveExplorerType.LastMove;
var data = FragmentDataFactory.Create(FragmentType.MoveExplorer,_temporaryExplorer,_currentTargetGridData,nextGridData,moveType);
PresentationManager.EnqueueTask(new FragmentSequencerTask(FragmentFactory.Create(FragmentType.MoveExplorer,data)));
}
//Step #6 更新视野
var radius = 1;
if (nextGridData.Feature == TerrainFeature.Mountain) radius = 2;
Main.PlayerLogic.UpdateSightByRadius(Main.MapData, playerData, nextGridData, radius);
// 更新当前目标格子
_currentTargetGridData = nextGridData;
_explorerMoveCount++;
}
// 完成探索后解锁输入 ,只有是玩家才需要解锁输入
if(playerData.Id == Main.MapData.PlayerMap.SelfPlayerId)
_main.InputLogic.UnlockInput();
// Step #3 如果是真人玩家
// 以下是原有的渲染逻辑,只有自己的玩家才会执行
// 如果已经有临时探索者,先销毁
if (_temporaryExplorer != null)
/*if (_temporaryExplorer != null)
{
GameObject.Destroy(_temporaryExplorer);
_temporaryExplorer = null;
@ -635,6 +663,7 @@ namespace TH1Renderer
_temporaryExplorerStartPos = worldPos;
_temporaryExplorerTime = 0f;
_temporaryExplorerActive = true;
*/
}
// 计算八个方向的视野情况并选择视野最少的方向移动