#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 объекту уровня менеджера, который затем отправит команду анимации соответствующему объекту.