Merge pull request 'fixbug/animation-loop' (#381) from fixbug/animation-loop into develop

Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/381
This commit is contained in:
namth
2026-04-22 10:08:57 +00:00
15 changed files with 143864 additions and 54 deletions
@@ -1410,6 +1410,7 @@ GameObject:
- component: {fileID: 8354143382850346745}
- component: {fileID: 4448389894352443543}
- component: {fileID: 2791476417509046288}
- component: {fileID: 5118003806955342754}
m_Layer: 0
m_Name: "\u5996\u7CBE"
m_TagString: Untagged
@@ -2426,6 +2427,19 @@ MonoBehaviour:
- {fileID: 7400000, guid: 4272f3e6213068440b4f6bcbade34750, type: 2}
- {fileID: 7400000, guid: 31417b3fc94fd0f479454dc3fcfb5607, type: 2}
- {fileID: 7400000, guid: 62d8692c72987e049b94423ec51d734a, type: 2}
--- !u!114 &5118003806955342754
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5544128592671745444}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 472c24b873524423f95454131fd11da6, type: 3}
m_Name:
m_EditorClassIdentifier:
combinedActionSO: {fileID: 11400000, guid: ae900b2279845c944a6379064aff6f29, type: 2}
--- !u!1 &5909446679138261478
GameObject:
m_ObjectHideFlags: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ae900b2279845c944a6379064aff6f29
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -907,6 +907,7 @@ GameObject:
- component: {fileID: 5951415567811727370}
- component: {fileID: 2933135962091378275}
- component: {fileID: 720054061806230412}
- component: {fileID: 3892901130224629286}
m_Layer: 0
m_Name: "\u7FBD\u7075\u5973"
m_TagString: Untagged
@@ -2108,6 +2109,19 @@ MonoBehaviour:
- {fileID: 7400000, guid: 7dc5fb07f4f5562499bc69b645d4ed9d, type: 2}
- {fileID: 7400000, guid: 7a81940d288270d469be4f8b5230d733, type: 2}
- {fileID: 7400000, guid: 733d485f56790364189789dddbfffcfb, type: 2}
--- !u!114 &3892901130224629286
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1769235238873837677}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 472c24b873524423f95454131fd11da6, type: 3}
m_Name:
m_EditorClassIdentifier:
combinedActionSO: {fileID: 11400000, guid: 5c996ee4f0bbbba458a4557f2d3e2ae3, type: 2}
--- !u!1 &1815801885025748105
GameObject:
m_ObjectHideFlags: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5c996ee4f0bbbba458a4557f2d3e2ae3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -755,6 +755,7 @@ GameObject:
- component: {fileID: 8453557373466821518}
- component: {fileID: 2236231879345885960}
- component: {fileID: 1351688607369250648}
- component: {fileID: 6701388848577721347}
m_Layer: 0
m_Name: "\u7FBD\u8292\u7537"
m_TagString: Untagged
@@ -1873,6 +1874,19 @@ MonoBehaviour:
- {fileID: 7400000, guid: 7a1b518cc0ca31d409bddbea883fa85c, type: 2}
- {fileID: 7400000, guid: be95dd6728dc0ec4fa115f3f7f50ba60, type: 2}
- {fileID: 7400000, guid: 6f09eb60a12c79346989125f988affb5, type: 2}
--- !u!114 &6701388848577721347
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4570049467700484810}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 472c24b873524423f95454131fd11da6, type: 3}
m_Name:
m_EditorClassIdentifier:
combinedActionSO: {fileID: 11400000, guid: dae367eca7e062443b66ab96aca2c742, type: 2}
--- !u!1 &4654364276745040637
GameObject:
m_ObjectHideFlags: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dae367eca7e062443b66ab96aca2c742
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -44,7 +44,7 @@ namespace BrewMonster.Scripts
GetPlayer().SetPos(GetPlayer().GetPos() + vDir * fMoveDist);
}
if (GetPlayer().m_FightCnt.IncCounter(dwDeltaTime))
if (GetPlayer().m_FightCnt.IncCounter(dwDeltaTime * 1000))
{
Finish();
}
@@ -159,7 +159,6 @@ namespace BrewMonster.Scripts
return m_iType;
}
}
public class CECEPIdleWorkMatcher : CECEPWorkMatcher
{
int m_iType;
@@ -355,7 +354,6 @@ namespace BrewMonster.Scripts
new List<CECEPWork>()
};
private int m_iCurWorkType;
public CECEPWorkMan(EC_ElsePlayer pElsePlayer)
{
m_pElsePlayer = pElsePlayer;
@@ -798,12 +796,11 @@ namespace BrewMonster.Scripts
if (!GetPlayer().m_FightCnt.IsFull()){
GetPlayer().m_FightCnt.IncCounter(dwDeltaTime);
}
//todo: get model and check
// if (GetPlayer().GetPlayerModel() != null){
if (GetPlayer().GetPlayerModel() != null){
if (CECPlayer.IsMoveStandAction(GetPlayer().GetLowerBodyAction())){
GetPlayer().PlayAction(GetStandAction(), false);
}
// }
}
}
int GetStandAction()
@@ -38,7 +38,7 @@ public class CECCounter
public bool IncCounter(float dwCounter)
{
m_dwCounter += dwCounter;
return (m_dwCounter >= m_dwPeriod);
return (m_dwCounter >= m_dwPeriod) ? true : false;
}
// Decrease counter
+15 -12
View File
@@ -294,7 +294,7 @@ namespace BrewMonster
protected GameObject GetDummyModel(int i) => (i!=(int)PLAYERMODEL_TYPE.PLAYERMODEL_MAJOR&&i<(int)PLAYERMODEL_TYPE.PLAYERMODEL_MAX) ? m_pModels[i]:null;
protected GameObject GetMajorModel() => m_pModels[(int)PLAYERMODEL_TYPE.PLAYERMODEL_MAJOR];
protected GameObject GetPetModel() => m_pPetModel;
protected CECModel GetPlayerModel() => m_pPlayerCECModel;
public CECModel GetPlayerModel() => m_pPlayerCECModel;
protected const int OBJECT_EXT_STATE_COUNT = 6;
protected bool IsMajorModel(GameObject pModel) => GetMajorModel() != null && pModel == GetMajorModel();
public enum WeaponHangerPosition
@@ -1176,11 +1176,11 @@ namespace BrewMonster
}
}
public bool PlayAction(int iAction, bool bRestart = true, int iTransTime = 200, bool bQueue = false)
public bool PlayAction(int iAction, bool bRestart = true, int iTransTime = 200, bool bQueue = false, bool isElsePlayer = false)
{
return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue);
}
public bool PlayAction(int iAction, int actionConfigID, bool bRestart = true, int iTransTime = 200, bool bQueue = false)
public bool PlayAction(int iAction, int actionConfigID, bool bRestart = true, int iTransTime = 200, bool bQueue = false, bool isElsePlayer = false)
{
return PlayActionWithConfig(iAction, actionConfigID, bRestart, iTransTime, bQueue);
}
@@ -1634,7 +1634,6 @@ namespace BrewMonster
string szShapeName = string.Empty;
GetShapeName(ref szShapeName);
int weapon_type = GetShowingWeaponType();
Debug.Log($"[THN]: PlayAttackAction weapon_type: {weapon_type}");
int nTime1 = 0, nTime2 = 0;
int iAction = (int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 + nRand;
bool bHideFX = false;//!CECOptimize::Instance().GetGFX().CanShowAttack(GetCharacterID(), GetClassID());
@@ -1653,7 +1652,6 @@ namespace BrewMonster
{
// “起? 动作(挥起)
Debug.Log($"[THN]: PlayAttackAction action with weapon type: {weapon_type} and weapon attached: {m_bWeaponAttached}");
szAct = EC_Utility.BuildActionName(action, weapon_type, "起");
int iTransTime = 200;
//EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szShapeName, szAct, iTransTime, true));
@@ -1723,8 +1721,6 @@ namespace BrewMonster
PLAYER_ACTION stand_action = m_PlayerActions[(int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND];
szAct = EC_Utility.BuildActionName(stand_action, 0);
int iTranstime = 300;
queueActionEvent.SetData(szShapeName, szAct, SetApplyDamage, false, attackEvent, iTranstime, false);
//EventBus.PublishChannelClass(m_PlayerInfo.cid, queueActionEvent);
m_pActionController.QueueNonSkillActionWithName(iAction, szAct, iTranstime, false, false, true, false);
/* QueueNonSkillActionWithName(ACT_FIGHTSTAND, szAct, 300, false, bHideFX, true);
@@ -3883,20 +3879,23 @@ namespace BrewMonster
public string AnimationName;
public int ITransTime;
public bool IsForceStopPrevious;
public bool IsLoop;
public CECAttackEvent AttackEvent;
public PlayActionEvent(string shapeName, string animationName, int iTransTime, bool isForceStopPrevious = false, CECAttackEvent attackEvent = null)
public PlayActionEvent(string shapeName, string animationName, int iTransTime, bool isForceStopPrevious = false, CECAttackEvent attackEvent = null, bool isLoop = false)
{
this.AnimationName = shapeName + animationName;
ITransTime = iTransTime;
IsForceStopPrevious = isForceStopPrevious;
AttackEvent = attackEvent;
IsLoop = isLoop;
}
public PlayActionEvent(string animationName, int iTransTime, bool isForceStopPrevious = false, CECAttackEvent attackEvent = null)
public PlayActionEvent(string animationName, int iTransTime, bool isForceStopPrevious = false, CECAttackEvent attackEvent = null, bool isLoop = false)
{
this.AnimationName = animationName;
ITransTime = iTransTime;
IsForceStopPrevious = isForceStopPrevious;
AttackEvent = attackEvent;
IsLoop = isLoop;
}
}
public struct PLAYER_ACTION
@@ -3912,8 +3911,9 @@ namespace BrewMonster
public CECAttackEvent AttackEvent;
public bool IsHitAnim;
public bool IsForceStopPrevious;
public bool IsLoop;
public QueueActionEvent(string animationName, Action<bool, CECAttackEvent> setFlag, bool isHitAnim,
CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false)
CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false, bool isLoop = false)
{
this.AnimationName = animationName;
SetFlag = setFlag;
@@ -3921,10 +3921,11 @@ namespace BrewMonster
AttackEvent = attackEvent;
ITransTime = iTransTime;
IsForceStopPrevious = isForceStopPrevious;
IsLoop = isLoop;
}
public void SetData(string shapeName, string animationName, Action<bool, CECAttackEvent> setFlag, bool isHitAnim,
CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false)
CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false, bool isLoop = false)
{
this.AnimationName = shapeName + animationName;
SetFlag = setFlag;
@@ -3932,9 +3933,10 @@ namespace BrewMonster
AttackEvent = attackEvent;
ITransTime = iTransTime;
IsForceStopPrevious = isForceStopPrevious;
IsLoop = isLoop;
}
public void SetData(string animationName, Action<bool, CECAttackEvent> setFlag, bool isHitAnim,
CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false)
CECAttackEvent attackEvent, int iTransTime, bool isForceStopPrevious = false, bool isLoop = false)
{
this.AnimationName = animationName;
SetFlag = setFlag;
@@ -3942,6 +3944,7 @@ namespace BrewMonster
AttackEvent = attackEvent;
ITransTime = iTransTime;
IsForceStopPrevious = isForceStopPrevious;
IsLoop = isLoop;
}
}
public enum PLAYER_ACTION_TYPE
+5 -5
View File
@@ -671,10 +671,10 @@ public class CECModel
}
var actionInfos = combinedAction.m_ActLst;
var isLoop = combinedAction.m_nLoops == 1;
EventBus.PublishChannel(m_nId, new PlayActionEvent(actionInfos[0].m_strName, nTransTime, bForceStop, attackEvent));
EventBus.PublishChannel(m_nId, new PlayActionEvent(actionInfos[0].m_strName, nTransTime, bForceStop, attackEvent, isLoop));
for(int i = 1; i < actionInfos.Count; i++)
{
EventBus.PublishChannelClass(m_nId, new QueueActionEvent(actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false));
EventBus.PublishChannelClass(m_nId, new QueueActionEvent(actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false, isLoop));
}
var eventInfoList = combinedAction.m_EventInfoLst;
if(eventInfoList != null && eventInfoList.Count > 0)
@@ -688,7 +688,7 @@ public class CECModel
{
string soundpath = AFile.NormalizePath(sfx.m_strFilePaths[0]);
soundpath = soundpath.ToLower();
SFXManager.Instance.PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget();
SFXManager.Instance.PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget();
}
}
@@ -717,10 +717,10 @@ public class CECModel
}
var actionInfos = combinedAction.m_ActLst;
var isLoop = combinedAction.m_nLoops == 1;
EventBus.PublishChannelClass(m_nId, new QueueActionEvent(actionInfos[0].m_strName, null, false, attackEvent, nTransTime, bForceStopPrevAct));
EventBus.PublishChannelClass(m_nId, new QueueActionEvent(actionInfos[0].m_strName, null, false, attackEvent, nTransTime, bForceStopPrevAct, isLoop));
for(int i = 1; i < actionInfos.Count; i++)
{
EventBus.PublishChannelClass(m_nId, new QueueActionEvent(actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false));
EventBus.PublishChannelClass(m_nId, new QueueActionEvent(actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false, isLoop));
}
return true;
}
@@ -167,20 +167,19 @@ namespace BrewMonster
{
m_pEPWorkMan.StartNormalWork(new CECEPWorkMove(m_pEPWorkMan));
}
// Play action
if (IsValidAction(m_iCurAction))
{
if (!IsPlayingAction((int)PLAYER_ACTION_TYPE.ACT_TRICK_JUMP) && !IsPlayingAction((int)PLAYER_ACTION_TYPE.ACT_TRICK_RUN))
{
if (m_iMoveMode == Move_Mode.MOVE_JUMP || m_iMoveMode == Move_Mode.MOVE_SLIDE)
PlayAction((int)PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false);
PlayAction((int)PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 200, false, true);
else
PlayAction(GetMoveStandAction(true), false);
PlayAction(GetMoveStandAction(true), false, 200, false, true);
}
}
}
else
PlayAction(GetMoveStandAction(true), true, 1, false);
PlayAction(GetMoveStandAction(true), true, 200, false, true);
}
public bool MovingTo(float dwDeltaTime)
@@ -217,7 +216,7 @@ namespace BrewMonster
if (Math.Abs(fMoveDelta - 0f) <= float.Epsilon || fMoveDelta >= fDist) //!fMoveDelta <=> (Math.Abs(fMoveDelta - 0f) <= float.Epsilon) Compare with 0
{
SetPos(m_vServerPos);
PlayAction(GetMoveStandAction(false), true, 1, false);
PlayAction(GetMoveStandAction(false), true, 200, false);
bRet = true;
}
else
@@ -277,7 +276,7 @@ namespace BrewMonster
{
m_bStopMove = false;
SetPos(Cmd.dest);
PlayAction(GetMoveStandAction(true), true, 1, false);
PlayAction(GetMoveStandAction(true), true, 200, false);
m_pEPWorkMan.FinishWork(CECEPWork.EP_work_ID.WORK_MOVE);
return;
}
@@ -323,7 +322,7 @@ namespace BrewMonster
m_pEPWorkMan.StartNormalWork(new CECEPWorkMove(m_pEPWorkMan));
}
PlayAction(GetMoveStandAction(true), true, 1, false);
PlayAction(GetMoveStandAction(true), true, 200, false);
}
public float GetDistToHost() { return m_fDistToHost; }
+79 -22
View File
@@ -11,7 +11,9 @@ namespace BrewMonster
{
public string AnimationName;
public bool IsForceStopPrevious;
public int ITransTime;
public CECAttackEvent AttackEvent;
public bool IsLoop;
}
public class PlayerVisual : MonoBehaviour
{
@@ -31,10 +33,15 @@ namespace BrewMonster
private const float FadeTime = 100;
private const FadeMode FadeMode = Animancer.FadeMode.FixedDuration;
QueueActionEvent queueActionEvent;
private string previousAnimationName;
private void PlayActionEventHandler(PlayActionEvent @event)
{
//when this trigger, clear all the animation in the queue which in the same layer of animancer
//prevent enqueue the same loop animation
bool loopcheck = @event.IsLoop == true && previousAnimationName == @event.AnimationName;
if(loopcheck)
{
return;
}
if (_animationQueue.Count > 0)
{
_animationQueue.Enqueue(new AnimationQueue
@@ -46,7 +53,8 @@ namespace BrewMonster
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
return;
}
InternalPlayAnimation(@event.AnimationName, @event.ITransTime);
previousAnimationName = @event.AnimationName;
InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode, @event.IsLoop);
ApplyAttackSignalOnAnimationEnd(@event.AttackEvent);
}
public void InitPlayerEventDoneHandler()
@@ -133,15 +141,24 @@ namespace BrewMonster
}
public bool EnqueueAnimation(QueueActionEvent @event)
{
if (namedAnimancer == null) return false;
if (namedAnimancer == null)
{
return false;
}
if(previousAnimationName == @event.AnimationName)
{
return false;
}
previousAnimationName = @event.AnimationName;
_animationQueue.Enqueue(new AnimationQueue
{
AnimationName = @event.AnimationName,
IsForceStopPrevious = @event.IsForceStopPrevious,
AttackEvent = null
ITransTime = @event.ITransTime,
AttackEvent = @event.AttackEvent,
IsLoop = @event.IsLoop
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
if (!isHit)
{
queueActionEvent = @event;
@@ -149,23 +166,51 @@ namespace BrewMonster
}
return true;
}
/// <summary>
/// This function is used to enqueue an animation for looping when the animancer is not set to looping
/// </summary>
/// <param name="animationName"></param>
/// <returns></returns>
private bool EnqueueAnimationForLooping(string animationName)
{
if (namedAnimancer == null)
{
return false;
}
//prevent call if these is a animation already in the queue
if(_animationQueue.Count > 0)
{
return false;
}
_animationQueue.Enqueue(new AnimationQueue
{
AnimationName = animationName,
IsForceStopPrevious = false,
AttackEvent = null,
IsLoop = true
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
return true;
}
private void PlayNext()
{
if (_animationQueue.Count == 0)
{
return;
}
else
{
string animationQueueString = "";
foreach(var animation in _animationQueue)
{
animationQueueString += animation.AnimationName + ", ";
}
}
// if (_currentState == null)
// {
// _animationQueue.Dequeue();
// return;
// }
//peek next if IsForceStopPrevious is true, force end
if (_animationQueue.Peek().IsForceStopPrevious)
{
Debug.Log($" InternalPlayAnimation PlayNext: Force Stop Previous");
_currentState.Stop();
_currentState?.Stop();
_currentState = null;
}
if (_currentState != null && _currentState.NormalizedTime < 1f) return;
@@ -175,7 +220,8 @@ namespace BrewMonster
}
var animationQueue = _animationQueue.Dequeue();
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
InternalPlayAnimation(animationQueue.AnimationName);
previousAnimationName = animationQueue.AnimationName;
InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode, animationQueue.IsLoop);
ApplyAttackSignalOnAnimationEnd(animationQueue.AttackEvent);
}
private void ApplyAttackSignalOnAnimationEnd(CECAttackEvent attackEvent)
@@ -192,7 +238,10 @@ namespace BrewMonster
}
void ApplyDamage()
{
if (queueActionEvent == null) return;
if (queueActionEvent == null)
{
return;
}
isHit = false;
queueActionEvent.SetFlag(true, queueActionEvent.AttackEvent);
queueActionEvent = null;
@@ -203,7 +252,8 @@ namespace BrewMonster
}
public bool IsAnimationExist(string animationName)
{
return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
var exists = namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
return exists;
}
private string _currentAnimationName;
@@ -213,19 +263,26 @@ namespace BrewMonster
/// <param name="animationName"></param>
/// <param name="duration"></param>
/// <param name="fadeMode"></param>
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode)
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode, bool isLoop = false)
{
if (namedAnimancer == null)
{
return;
}
bool isState = namedAnimancer.States.TryGet(animationName, out var existingState) ? true : false;
if (isState)
{
_currentState = namedAnimancer.TryPlay(animationName, duration / 1000, fadeMode);
_currentAnimationName = animationName;
//Debug.Log($"InternalPlayAnimation: removeShapeName 1 TriggerName={removeShapeName}");
//if the animation is looping and the current state is not looping, play the animation again
if(isLoop == true && _currentState.IsLooping == false)
{
_currentState.Time = 0;
_currentState.Events.OnEnd = () => EnqueueAnimationForLooping(animationName);
}
return;
}
BMLogger.LogError($"Null name animation: {animationName}");
//BMLogger.LogError($"Null name animation: {animationName}");
}
/// <summary>