LoginSignup
7
6

More than 5 years have passed since last update.

PUNで動的にAnimator込みの同期オブジェクトを同期する

Last updated at Posted at 2018-09-01

やりたいこと => PhotonObjectをスクリプトから生成する

PhotonObjectをスクリプトから生成するやり方、あまり記事がひっかかりません。
みんなPhotonNetwork.Instantiate()でResourcesから引っ張ってきてるんでしょうか?
とりあえず以下の先人の記事を読んでください。

Photon Unity Networkingで動的に同期オブジェクトを生成する方法

この記事はそれにPhotonAnimationViewを追加して使い回せるようそれっぽくメソッド化したものです。
無茶苦茶やってるので解説読んでから使ってください。

コード

Dresser.cs
    public static GameObject DressAsPhotonObject(GameObject plainObject, int viewId, int ownerId)
    {
        // PhotonView.
        PhotonView photonView = plainObject.AddComponent<PhotonView>();
        photonView.viewID = viewId;
        photonView.ownerId = ownerId;
        photonView.synchronization = ViewSynchronization.UnreliableOnChange;
        photonView.ObservedComponents = new List<Component>();

        // Transform.
        PhotonTransformView photonTransformView = plainObject.AddComponent<PhotonTransformView>();
        photonTransformView.m_PositionModel.SynchronizeEnabled = true;
        photonTransformView.m_RotationModel.SynchronizeEnabled = true;
        photonTransformView.m_ScaleModel.SynchronizeEnabled = true;

        // Animator.
        PhotonAnimatorView photonAnimatorView = plainObject.AddComponent<PhotonAnimatorView>();
        Animator animator = plainObject.GetComponent<Animator>();
        // Animator layer
        for (var count = 0; count < animator.layerCount; count++)
        {            
            photonAnimatorView.SetLayerSynchronized(count, PhotonAnimatorView.SynchronizeType.Discrete);
        }
        // Animator Parameter
        foreach (AnimatorControllerParameter animatorControllerParameter in animator.parameters)
        {
            photonAnimatorView.SetParameterSynchronized(animatorControllerParameter.name,
                (PhotonAnimatorView.ParameterType) animatorControllerParameter.type,
                PhotonAnimatorView.SynchronizeType.Discrete);
        }

        // add list
        photonView.ObservedComponents.Add(photonTransformView);
        photonView.ObservedComponents.Add(photonAnimatorView);

        return plainObject;
    }

こんな感じで使う


[SerializeField] private GameObject _prefab;

    public enum RaiseEventType : byte
    {
        Create = 1,
    }

    void Start()
    {
        PhotonNetwork.OnEventCall += CreatePhoton;
        var sendData = new int[2];
        sendData[0] = PhotonNetwork.AllocateViewID();
        sendData[1] = PhotonNetwork.player.ID;
        var option = new RaiseEventOptions
        {
            CachingOption = EventCaching.AddToRoomCache,
            Receivers = ReceiverGroup.All,
        };
        PhotonNetwork.RaiseEvent((byte) RaiseEventType.Create, sendData, true, option);
    }


    private void CreatePhoton(byte eventCode, object content, int senderId)
    {
        if (eventCode == (byte) RaiseEventType.Create)
        {
            var receiveData = content as int[];
            var plainObjects = Instantiate(_prefab);
            PhotonDresser.DressAsPhotonObject(plainObjects, receiveData[0], receiveData[1]);
        }
    }

解説

PhotonView


// まずは大本のPhotonView.
PhotonView photonView = plainObject.AddComponent<PhotonView>();
// PhotonNetwork.AllocateViewID()で用意してもらったviewID
photonView.viewID = viewId;
// とりあえず作ったplayerのIDぶちこんどく
photonView.ownerId = ownerId;
// デフォルトがoff.わたしはこれでしにました
photonView.synchronization = ViewSynchronization.UnreliableOnChange;
// newしとかないとしぬ
photonView.ObservedComponents = new List<Component>();

PhotonTransFormView


// Transform.
// インスペクタ上で見られる設定は対応する~Modelに設定できるメソッドやプロパティがある.
// 見ればわかるが各Modelクラスはただのデータクラス.あまりクセがないので特に言うことがない。
PhotonTransformView photonTransformView = plainObject.AddComponent<PhotonTransformView>();
photonTransformView.m_PositionModel.SynchronizeEnabled = true;
photonTransformView.m_RotationModel.SynchronizeEnabled = true;
photonTransformView.m_ScaleModel.SynchronizeEnabled = true;

PhotonAnimatorView


// Animator.
PhotonAnimatorView photonAnimatorView = plainObject.AddComponent<PhotonAnimatorView>();
Animator animator = plainObject.GetComponent<Animator>();

// 特定のレイヤーだけ同期する、みたいな用途はあまり考えづらいが……。普通は全部同期する気がする.
// もちろん実際に使う場合は「layerIndexはどうせ0,1,2...なんだろ? 死ねぇ!」とループでブチ回すのではなく、
// ちゃんとAnimator.GetLayerIndex(レイヤー名)で取るべき.
// しかしそうなるとこのメソッドの汎用性がなくなる…….
for (var count = 0; count < animator.layerCount; count++)
{
    photonAnimatorView.SetLayerSynchronized(count, PhotonAnimatorView.SynchronizeType.Discrete);
}

// パラメータなんざ全部同期しときゃいいんだよ! オラァ!
foreach (AnimatorControllerParameter animatorControllerParameter in animator.parameters)
{
    // AnimatorControllerParameterType = PhotonAnimatorView.ParameterType
    // 別のenumだが両方 int enum で定義値が一緒なので直にキャストしても動く.
    // 変更することがあるとも思えないのでそのまま使う.
    // そのままAnimatorControllerParameterType使ったらよかったのでは?
    photonAnimatorView.SetParameterSynchronized(animatorControllerParameter.name,
        (PhotonAnimatorView.ParameterType) animatorControllerParameter.type,
        PhotonAnimatorView.SynchronizeType.Discrete);
}

return

// PhotonViewに渡しとかないと同期されない.
photonView.ObservedComponents.Add(photonTransformView);
photonView.ObservedComponents.Add(photonAnimatorView);

// 余談だが動的に生成したPhotonObjectはリストとかに入れて管理するより
// タグつけて適宜GameObject.FindGameObjectsWithTag(TAG)で取得したほうがいいような気がする.
// リストに死んだの入ってたらめんどくさいし.
return plainObject;

結論

適宜よいように改変して使ってください。
Photonは公式ドキュメントが絶妙にふわふわしているので、ある程度それらしいことを検索してわからなかったらコード読んだほうが早いです。PhotonViewとかPhotonNetworkとか。
また、こうして動的にPhotonObjectを生成するには各クライアントで実行する必要があります。[PunRPC]はあまり使わないでサンプルで書いたみたいにRaiseEventでやったほうがいいです。
慣れるとRaiseEventばっかり使うようになってきます。キャッシュ管理とかいろいろべんり。
CustomPropertiesにブチ込んでそのコールバックで……みたいな手もなくは……ないんですが……?
一応動いてはいるんですが、なんかやばそうな気がするのでやめたほうがいいです、多分。

参考資料

Photon Unity Networkingで動的に同期オブジェクトを生成する方法

Photonでオブジェクトをスポーンする方法の調査およびIPunPrefabPoolとUniRx.Toolkit.ObjectPoolを使ったオブジェクトプールのサンプル

【Unity】僕もPhotonを使いたい #10 RaiseEvent

ほんとうにいいたかったこと

あんちゃん! なんか2出てるけど何が変わったのかよくわからんから調べといて!

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6