fix gfx hit not sych with animation. Fix wrong animation timing with long weapon. Add animation scaling speed

This commit is contained in:
Tran Hai Nam
2026-05-17 15:48:29 +07:00
parent 285697bf8b
commit c851c46292
9 changed files with 10163 additions and 300 deletions
+12 -77
View File
@@ -1,4 +1,3 @@
using System;
using Animancer;
using BrewMonster;
using System.Collections.Generic;
@@ -12,10 +11,10 @@ namespace BrewMonster
public string AnimationName;
public bool IsForceStopPrevious;
public int ITransTime;
public CECAttackEvent AttackEvent;
public bool IsLoop;
public ChannelAct ChannelAct;
public int Rank;
public float PlaySpeed;
}
public class PlayerVisual : MonoBehaviour
{
@@ -26,7 +25,6 @@ namespace BrewMonster
[SerializeField] private AnimancerState _currentState;
[SerializeField] private Queue<AnimationQueue> _animationQueue = new Queue<AnimationQueue>();
[SerializeField] private List<string> _animationList = new List<string>();
[SerializeField] private bool isHit;
[SerializeField] private int id;
[SerializeField] private bool isDebug;
[SerializeField] private bool debugNamePlateBounds;
@@ -34,7 +32,6 @@ namespace BrewMonster
private const float FadeTime = 100;
private const FadeMode FadeMode = Animancer.FadeMode.FixedDuration;
QueueActionEvent queueActionEvent;
private string previousAnimationName;
private void PlayActionEventHandler(PlayActionEvent @event)
{
@@ -56,24 +53,25 @@ namespace BrewMonster
{
AnimationName = @event.AnimationName,
IsForceStopPrevious = @event.IsForceStopPrevious,
AttackEvent = @event.AttackEvent,
ITransTime = @event.ITransTime,
ChannelAct = @event.ChannelAct,
Rank = @event.Rank
Rank = @event.Rank,
PlaySpeed = @event.PlaySpeed
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
return;
}
}
previousAnimationName = @event.AnimationName;
InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode);
ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank, @event.AnimationName, @event.IsLoop);
InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode, @event.PlaySpeed);
ApplyAnimationEndCallbacks(@event.AnimationName, @event.IsLoop);
}
public void InitPlayerEventDoneHandler()
{
namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
if (namedAnimancer == null)
{
BrewMonster.BMLogger.LogWarning("InitPlayerEventDoneHandler animancer == null");
BMLogger.LogWarning("InitPlayerEventDoneHandler animancer == null");
return;
}
var player = GetComponentInParent<CECPlayer>();
@@ -89,7 +87,6 @@ namespace BrewMonster
_playerInfo = player.GetPlayInfo();
id = _playerInfo.cid;
EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.SubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
EventBus.SubscribeChannel<ClearComActFlagAllRankNodesEvent>(_playerInfo.cid, ClearComActFlagAllRankNodesEventHandler);
_eventBusSubscribed = true;
}
@@ -102,7 +99,6 @@ namespace BrewMonster
if (!_eventBusSubscribed)
return;
EventBus.UnsubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.UnsubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
EventBus.UnsubscribeChannel<ClearComActFlagAllRankNodesEvent>(_playerInfo.cid, ClearComActFlagAllRankNodesEventHandler);
_eventBusSubscribed = false;
}
@@ -131,54 +127,14 @@ namespace BrewMonster
{
_animationQueue.Clear();
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
if (isHit)
{
ApplyDamage();
}
//todo: this is dummy to force change to idle state
// EventBus.PublishChannel(_playerInfo.cid, new PlayActionEvent("站立_通用"));
}
private void QueueActionEventHandler(QueueActionEvent @event)
{
if (!EnqueueAnimation(@event))
{
BMLogger.LogError("HoangDev : EnqueueAnimation Failed");
}
}
private void Update()
{
PlayNext();
}
public bool EnqueueAnimation(QueueActionEvent @event)
{
if (namedAnimancer == null)
{
return false;
}
if(previousAnimationName == @event.AnimationName)
{
return false;
}
previousAnimationName = @event.AnimationName;
_animationQueue.Enqueue(new AnimationQueue
{
AnimationName = @event.AnimationName,
IsForceStopPrevious = @event.IsForceStopPrevious,
ITransTime = @event.ITransTime,
AttackEvent = @event.AttackEvent,
IsLoop = @event.IsLoop,
ChannelAct = @event.ChannelAct,
Rank = @event.Rank
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
if (!isHit)
{
queueActionEvent = @event;
isHit = @event.IsHitAnim;
}
return true;
}
/// <summary>
/// This function is used to enqueue an animation for looping when the animancer is not set to looping
/// </summary>
@@ -199,7 +155,6 @@ namespace BrewMonster
{
AnimationName = animationName,
IsForceStopPrevious = false,
AttackEvent = null,
IsLoop = true
});
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
@@ -219,45 +174,24 @@ namespace BrewMonster
_currentState = null;
}
if (_currentState != null && _currentState.NormalizedTime < 1f) return;
if (isHit)// have it relative to check _currentState == null?
{
ApplyDamage();
}
var animationQueue = _animationQueue.Dequeue();
_animationList = _animationQueue.Select(q => q.AnimationName).ToList();
previousAnimationName = animationQueue.AnimationName;
InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode);
ApplyAnimationEndCallbacks(animationQueue.AttackEvent, animationQueue.ChannelAct, animationQueue.Rank, animationQueue.AnimationName,animationQueue.IsLoop);
InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode, animationQueue.PlaySpeed);
ApplyAnimationEndCallbacks(animationQueue.AnimationName, animationQueue.IsLoop);
}
private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank, string animationName, bool isLoop)
private void ApplyAnimationEndCallbacks( string animationName, bool isLoop)
{
if (_currentState == null) return;
_currentState.Events.OnEnd = () =>
{
if (attackEvent != null)
attackEvent.m_bSignaled = true;
if(isLoop)
{
EnqueueAnimationForLooping(animationName);
}
if (channelAct == null || string.IsNullOrEmpty(animationName))
return;
var node = channelAct.GetNodeByRank((byte)rank);
node?.m_pActive?.m_ActionNames?.Remove(animationName);
};
}
void ApplyDamage()
{
if (queueActionEvent == null)
{
return;
}
isHit = false;
queueActionEvent.SetFlag(true, queueActionEvent.AttackEvent);
queueActionEvent = null;
}
private void OnDestroy()
{
UnregisterPlayerEventHandlers();
@@ -281,7 +215,7 @@ 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, float playSpeed = 1.0f)
{
if (namedAnimancer == null)
{
@@ -292,6 +226,7 @@ namespace BrewMonster
{
_currentState = namedAnimancer.TryPlay(animationName, duration / 1000, fadeMode);
_currentState.Time = 0;
_currentState.Speed = playSpeed > 0f ? playSpeed : 1.0f;
_currentAnimationName = animationName;
return;
}