c# - 如何使用 Photon 准确同步触发动画?
问题描述
根据 Photon 开发人员自己的说明,当您尝试使用触发参数设置 Photon Animator View 时,Photon Animator View 似乎无法很好地使用触发参数(我在某处读到它有 40% 的掉落率,并且我自己的测试显示更糟糕的结果),他们甚至建议我们使用我们自己的自定义代码,使用 RPC 或 RaiseEvents 来获得更好的结果。那么我们如何去同步触发参数触发的动画呢?
解决方案
我想出了这个可以用来同步动画的类(任何动画,不仅仅是触发动画)。它使用 RaiseEvent(也可以使用 RPC 来完成)。
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using ExitGames.Client.Photon;
namespace Workbench.Wolfsbane.Multiplayer
{
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(PhotonView))]
public class NetworkedAnimation : MonoBehaviourPunCallbacks
{
#region private fields
Animator anim;
#endregion
#region monobehaviours
public override void OnEnable()
{
base.OnEnable();
PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
}
public override void OnDisable()
{
base.OnDisable();
PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
}
private void Start()
{
anim = GetComponent<Animator>();
}
#endregion
#region private methods
private void OnEvent(EventData photonEvent)
{
byte eventCode = photonEvent.Code;
if (eventCode == PlayAnimationEventCode)
{
object[] data = (object[])photonEvent.CustomData;
int targetPhotonView = (int)data[0];
if (targetPhotonView == this.photonView.ViewID)
{
string animatorParameter = (string)data[1];
string parameterType = (string)data[2];
object parameterValue = (object)data[3];
switch (parameterType)
{
case "Trigger":
anim.SetTrigger(animatorParameter);
break;
case "Bool":
anim.SetBool(animatorParameter, (bool)parameterValue);
break;
case "Float":
anim.SetFloat(animatorParameter, (float)parameterValue);
break;
case "Int":
anim.SetInteger(animatorParameter, (int)parameterValue);
break;
default:
break;
}
}
}
}
#endregion
#region public methods
public const byte PlayAnimationEventCode = 1;
public void SendPlayAnimationEvent(int photonViewID, string animatorParameter, string parameterType, object parameterValue = null)
{
object[] content = new object[] { photonViewID, animatorParameter, parameterType, parameterValue };
RaiseEventOptions raiseEventOptions = new RaiseEventOptions { Receivers = ReceiverGroup.All };
PhotonNetwork.RaiseEvent(PlayAnimationEventCode, content, raiseEventOptions, SendOptions.SendReliable);
}
#endregion
}
}
用法:
// in some other script (that is on the same object)
GetComponent<NetworkedAnimation>().SendPlayAnimationEvent(photonView.ViewID, animation, "Trigger");
发送正确的 photonviewId 至关重要,因为在订阅事件的所有对象上都会调用 RaiseEvents,因此您需要一种方法来仅过滤适当的对象。在我的例子中,我需要同步播放器动画,因为每个播放器都有一个 photonView,所以我使用 photonView.viewID 作为过滤器机制。其他人可能会走不同的方向,不使用 photonView 过滤对象,但可能将 RaiseEvent 或 RPC 发送到管理器级别的对象,然后将动画命令发送到适当的对象。
推荐阅读
- css - 在 asp.net core mvc 中设置背景图片
- python - Python 和 Sqlite3:显示来自数据库的错误输出
- typescript - 带有 src 和测试的打字稿配置
- node.js - 没有为 Electron 的入门应用程序定义流程
- java - 谷歌登录失败的Android工作室
- vba - getLabel 可以安全使用(VBA、PowerPoint)吗?
- vue.js - 当用户单击按钮 vuejs 时,如何使对象中的项目为真?
- flutter - Flutter:如何在 Navigator.pushNamedAndRemoveUntil() 完成后执行操作
- vue.js - vue/vuetify 属性与模板文字绑定的奇怪行为
- java - 为什么我不能将 CustomType ArrayList 添加到 Object ArrayLists 的 ArrayList 中?