Animations
概述
Fusion動畫範例展示了六個不同的方法,來使用Fusion處理動畫網路。
示例1到5使用轉譯準確的方法,而示例6代表一個刷新準確的方法。各個示例以大約一秒鐘的時間間隔來繪製腿和手臂的命中框,來展示伺服器角色及代理角色之間的結果精確度。在遊戲使用延遲補償時,動畫精確度特別重要。
下載
版本 | 發佈日期 | 下載 | |
---|---|---|---|
1.1.6 | Jul 11, 2023 | Fusion Animations 1.1.6 Build 211 |
資料夾架構
以6個小的獨立示例的集合來架構專案。
/01_AnimatorSimple | 示例1——附有動畫工具的已連線狀態 |
/02_AnimatorInterpolated | 示例2——附有動畫工具的已內插補點已連線狀態 |
/03_AnimatorStateSync | 示例3——附有動畫工具的狀態同步 |
/04_NetworkMecanimAnimator | 示例4——網路Mecanim動畫工具 |
/05_AnimancerFSM | 示例5——附有Animancer的網路FSM |
/06_FusionAnimationController | 示例6——Fusion動畫控制器 |
/Common | 所有示例通用的預製件、指令碼及材料 |
/ThirdParty | 第三方資產(模型、動畫、Animancer Lite) |
如何進行
開始遊戲
各個示例有其自己的場景檔案,其可以被開啟及遊玩。另一種方法是,可以從 開始 場景(/Common/Start)來開始所有示例。
為了展示的目的,建議使用附有一個主機端加上2個客戶端的多重同儕節點模式(開始主機端+ 2個客戶端 按鈕)。這允許您在編輯器中來看見及比較狀態授權、輸入授權及代理結果。
控制
所有示例只使用三個動畫狀態。預設播放閒置的動畫,按下 向上箭頭 鍵來開始角色跑步動畫,並且按下 空白 鍵來觸發跳躍動畫。
當以同儕節點模式遊玩時,可使用數字0、1、2,及3鍵以在它們之間切換。另一種方法是,可以從 跑者可見度控制 視窗(頂層選單 Fusion > 視窗 > 跑者可見度控制)來切換同儕節點。
理解動畫精確度
對於特定遊戲應用程式而言,在同儕節點之間的準確的動畫同步可能非常重要,比如準確的延遲補償。當動畫完全同步時,它確保在一個客戶端上識別的命中也將在伺服器上識別,從而獲得良好的玩家體驗。當然,這只適用於角色的命中框被動畫影響的情形。請查看Fusion操作手冊的動畫頁面,其中詳細說明了重要概念。
所有示例都顯示了本機玩家看到的(代理*角色的命中框顯示為藍色),以及在伺服器上出現的(顯示為綠色),腿和手臂命中框的預期位置。動畫的精確度越高,框就對齊的更緊密。
命中框繪製由位於玩家預製件的HitboxDraw
指令碼來執行。為了更好地比較不同,以50個刷新的間隔(大約一秒)來繪製命中框。
*代理物件 = 網路物件執行個體,其沒有輸入授權(不是由本機玩家控制),也沒有狀態授權(執行個體沒有關於它們的網路狀態的授權,通常是在伺服器上的執行個體)。簡單來說,當以一個客戶端遊玩時,代理角色是玩家可以看到的其他玩家。
模擬網路情況
在不佳的網路情況下,可以更好地觀察到已增加的動畫精確度的某些改變(比如使用已內插補點資料)。為了快速地模擬這樣的網路情況,可以使用像是Clumsy這樣的工具。請參見模擬網路情況章節以取得更多資訊。
示例1——附有動畫工具的已連線狀態
轉譯準確的方法
這個示例展示了最簡單的解決方案,其使用最新的網路狀態以控制動畫工具參數。
通常可以使用一個現有的網路狀態(比如_controller.Speed
)來控制動畫。基於在Render
方法中或來自OnChanged
回調的已連線資料,來設定轉譯準確的動畫。
C#
private CharacterController _controller;
private Animator _animator;
public override void Render()
{
if (_lastVisibleJump < _controller.JumpCount)
{
_animator.SetTrigger("Jump");
}
_lastVisibleJump = _controller.JumpCount;
_animator.SetFloat("Speed", _controller.Speed);
}
示例2——附有動畫工具的已內插補點已連線狀態
轉譯準確的方法
這個示例使用已內插補點網路資料,而不是僅使用最新的網路資料,因此比上一個示例更上一層樓。使用已內插補點資料可以使動畫更加精確,並且即使在網路情況不理想的情況下,也可以保持這樣的精確度(請參見模擬網路情況章節)。
C#
private CharacterController _controller;
private Animator _animator;
public override void Render()
{
int jumpCount = _useInterpolation == true ? _controller.InterpolatedJumpCount : _controller.JumpCount;
if (_lastVisibleJump < jumpCount)
{
_animator.SetTrigger("Jump");
}
_lastVisibleJump = jumpCount;
float speed = _useInterpolation == true ? _controller.InterpolatedSpeed : _controller.Speed;
_animator.SetFloat("Speed", speed);
}
為了比較已內插補點資料及最新的資料的使用,在玩家元件上有一個簡單的核取方塊。找到 Player_AnimatorInterpolated 預製件並且關閉 使用內插補點。以兩個額外的客戶端來開始遊戲,模擬一個不佳的網路(Clumsy——延遲100毫秒,下降20%)並且比較差異之處。
示例3——附有動畫工具的狀態同步
轉譯準確的方法
這個示例新增一個特殊的元件AnimatorStateSync
,其定期地同步目前的玩家動畫工具狀態及它們的時間。狀態同步可確保代理動畫將同步,即便是在玩家加入遊戲後或代理物件進入興趣區域時也將同步。
狀態同步對於長時間運行的動畫(比如運動),或是對於校正可能在轉譯準確的方法下發生的錯誤而言,可能特別重要。
示例:當一位本機玩家加入遊戲,遠端玩家已經執行了10秒鐘的跑步動畫。然而當沒有同步動畫時間的話,在本機玩家機器上的代理角色將從一開始來開始跑步動畫,從而導致不同的動畫時刻。這個時刻將隨著下一個動畫動作(比如跳躍)來自行校正,但在此之前,動畫將是不同步的。
示例4——網路Mecanim動畫工具
轉譯準確的方法
透過與Fusion SDK搭售的NetworkMecanimAnimator
(NMA)元件來同步動畫的一個簡單的解決方案。
網路Mecanim動畫工具不使用已內插補點的已連線資料,因此動畫精確度低於示例3的解決方案所能達到的精確度。請記得,NMA不使用現有的網路資料,而是複製目前的動畫工具參數到其自己的已連線資料架構,因此它將會使用更多頻寬,尤其是在已同步參數變動很大的情況。
請參見動畫文檔以了解更多關於網路Mecanim動畫工具的資訊。
C#
private CharacterController _controller;
private NetworkMecanimAnimator _networkAnimator;
public override void FixedUpdateNetwork()
{
if (IsProxy == true)
return;
if (Runner.IsForward == false)
return;
if (_controller.HasJumped == true)
{
_networkAnimator.SetTrigger("Jump", true);
}
_networkAnimator.Animator.SetFloat("Speed", _controller.Speed);
}
示例5——附有Animancer的網路FSM
轉譯準確的方法
這個示例使用一個熱門的第三方動畫資產Animancer及網路FSM附加元件,該附加元件目前只在這個範例中預覽。請記得,Animancer也可以在沒有FSM的情況下使用,其使用方法與在第一個示例中的情況類似。
網路FSM需要StateMachineController
元件以放在遊戲物件上,以及一個使用者指令碼(比如玩家),其持有狀態機器並執行IStateMachineOwner
介面。 StateMachineController
之後將自動地同步必要的資料到所有同儕節點,並且更新已註冊的機器。
C#
public class Player : NetworkBehaviour, IStateMachineOwner
{
private PlayerBehaviourMachine _fullBodyMachine;
void IStateMachineOwner.CollectStateMachines(List<IStateMachine> stateMachines)
{
var states = GetComponentsInChildren<PlayerStateBehaviour>();
var animancer = GetComponentInChildren<AnimancerComponent>();
_fullBodyMachine = new PlayerBehaviourMachine("Full Body", _controller, animancer, states);
stateMachines.Add(_fullBodyMachine);
}
}
基於狀態的變化來播放動畫。一個狀態代表一個單一玩家行為,其是在玩家階層中附加了StateBehaviour
指令碼的一個物件(比如跳躍狀態、運動狀態),或是繼承於State
指令碼的一個單純類別(在此示例中沒有展示)。
C#
public override void FixedUpdateNetwork()
{
if (IsProxy == true)
return;
if (_controller.HasJumped == true)
{
_fullBodyMachine.TryActivateState<PlayerJumpState>();
}
}
C#
public class PlayerJumpState : PlayerStateBehaviour
{
[SerializeField]
private ClipTransition _jumpClip;
protected override void OnEnterStateRender()
{
Animancer.Play(_jumpClip);
}
protected override void OnFixedUpdate()
{
if (Machine.StateTime >= _jumpClip.Length * _jumpClip.Speed)
{
// Jump animation should be finished, let's leave this state
Machine.TryDeactivateState(StateId);
}
}
}
可以建立由一個上層狀態控制的子狀態機器(下層機器),這有效地建立一個HFSM(階層式有限狀態機器)。舉例而言,一個下層機器可以是一個空中機器,其附有比如 跳躍、落下 及 著陸 等由一個 空中 上層狀態所控制的狀態。當控制有許多狀態的複雜動畫設定時,這樣的分離是有用的。
值得一提的是,預設網路FSM基於已內插補點資料來切換在代理上的狀態,並且提供目前狀態時間(Machine.StateTime
),從轉譯調用中檢查該時間時,該時間也會被內插補點。這確保了精細的動畫精確度,且無需付出過多的努力。
C#
public class PlayerLocomotionState : PlayerStateBehaviour
{
[SerializeField]
private LinearMixerTransition _moveMixer;
protected override void OnEnterStateRender()
{
Animancer.Play(_moveMixer);
// Update the animation time based on the state time
_moveMixer.State.Time = Machine.StateTime;
}
protected override void OnRender()
{
_moveMixer.State.Parameter = Controller.InterpolatedSpeed;
}
}
示例6——Fusion動畫控制器
刷新準確的方法
Fusion動畫控制器是一個 刷新準確的 動畫解決方案,直接在Unity的下層可遊玩的API的頂層上組建。
類似於 Mecanim,動畫控制器使用 動畫圖層 來運作。每個圖層含有一個或多個 動畫狀態。圖層及狀態都簡單地由物件階層中的物件所代表(請參見Player_FusionAnimationController
預製件)。透過AnimationController
元件,從程式碼來控制動畫。
C#
private CharacterController _controller;
private PlayerLocomotionState _locomotionState;
private PlayerJumpState _jumpState;
public override void FixedUpdateNetwork()
{
if (IsProxy == true)
return;
if (_controller.HasJumped == true)
{
_jumpState.Activate(0.15f);
}
else if (_jumpState.IsPlaying() == false || _jumpState.IsFinished(-0.15f, false) == true)
{
_locomotionState.Activate(0.15f);
}
}
Fusion動畫控制器是一個在BR200中使用的動畫控制器的精緻版本。因此,如需取得更詳細的動畫示例,請參見BR200。
第三方資產
動畫範例包含了由各自的創作者提供的多個資產。您可以在它們各自的網站上為您自己的專案取得完整的套件:
- Kybernetik的Animancer LITE
重要事項:為了在商業專案中使用它們,需要從各自的創作者購買一個授權。
Back to top