如何使用 Photon 准确同步触发动画?

Posted

技术标签:

【中文标题】如何使用 Photon 准确同步触发动画?【英文标题】:How to sync trigger animations using Photon accurately? 【发布时间】:2021-12-24 02:18:54 【问题描述】:

根据 Photon 开发人员自己的说明,当您尝试使用触发参数设置 Photon Animator View 时,Photon Animator View 似乎无法很好地使用触发参数(我在某处读到它有 40% 的下降率,而我自己的测试显示更糟糕的结果),他们甚至建议我们使用我们自己的自定义代码,使用 RPC 或 RaiseEvents 来获得更好的结果。那么如何同步触发参数触发的动画呢?

【问题讨论】:

你的问题是什么? 请澄清您的具体问题或提供更多详细信息以准确突出您的需求。正如目前所写的那样,很难准确地说出你在问什么。 【参考方案1】:

我想出了这个可以用来同步动画的类(任何动画,不仅仅是触发动画)。它使用 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 发送到管理器级别的对象,然后将动画命令发送到适当的对象。

【讨论】:

以上是关于如何使用 Photon 准确同步触发动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过Photon PUN同步变量

使用 Unity 和 Photon PUN,有没有办法在运行时使用 SetTile() 同步更改对瓷砖地图的更改?

Photon Unity:变量不使用 PunRPC 同步

unity的PUN如何同步自定义脚本

如何使用 Photon 发送结构

使用 Photon Unity Network(多人游戏)在 Unity 中实时同步