Как точно синхронизировать анимацию триггера с помощью Photon?

#c# #unity3d #photon

Вопрос:

Согласно заметке самих разработчиков Photon, которая появляется при попытке настроить представление Photon Animator с параметрами триггера, представление Photon Animator, похоже, не очень хорошо работает с параметрами триггера (я где-то читал, что у него скорость падения 40%, а мои собственные тесты показывают еще худшие результаты), и они даже предлагают нам использовать наш собственный пользовательский код с использованием RPC или RaiseEvents для достижения лучших результатов. Как же тогда синхронизировать анимации, запускаемые параметрами триггера?

Комментарии:

1. в чем заключается ваш вопрос?

2. Пожалуйста, проясните вашу конкретную проблему или предоставьте дополнительные сведения, чтобы выделить именно то, что вам нужно. Поскольку это написано в настоящее время, трудно точно сказать, о чем вы просите.

Ответ №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 = GetComponentlt;Animatorgt;();  }   #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)  GetComponentlt;NetworkedAnimationgt;().SendPlayAnimationEvent(photonView.ViewID, animation, "Trigger");  

Отправка правильного идентификатора photonviewId имеет решающее значение, поскольку события RaiseEvents вызываются для ВСЕХ объектов, подписавшихся на событие, поэтому вам нужен способ фильтрации только соответствующего объекта. В моем случае мне нужно было синхронизировать анимацию игрока, и, поскольку у каждого игрока есть PhotonView, я использовал PhotonView.ViewID в качестве механизма фильтрации. Другие могут пойти в другом направлении и не использовать PhotonView для фильтрации объектов, но, возможно, отправить RaiseEvent или RPC объекту уровня менеджера, который затем отправит команду анимации соответствующему объекту.