naetoru2144
@naetoru2144

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

PUN2で位置が同期されない

Q&A

Closed

解決したいこと

他プレイヤーの回転に加えて、位置も同期したい

概要

Unityでオンラインゲームを制作しています。
同期のためのライブラリはPUN2,位置の同期にはPhotonTransformViewを使用しています。
相手プレイヤーの回転は同期されるのですが位置が同期されません。どうすればいいのでしょうか...

設定状況

  • プレイヤーオブジェクトに付いているPhoton関係のスクリプトは以下三つです
    • PhotonView
    • PhotonTransformView
      • PositionとRotationにチェック
    • PhotonAnimatorView
  • プレイヤーの親オブジェクトはありません

実際の動作動画

右側が操作している画面、左側がそれを見ている画面です。
位置は同期されておらず、回転とアニメーションは同期されている状況と解釈しています。

自分で試したこと

  • キャラクターを動かすスクリプトのUpdateの中身をPhotonView.isMineがTrueの時のみ実行するようにした
  • キャラクターを動かすスクリプト、ルームやキャラクターの作成を行うスクリプトの継承元を MonoBehaviourPunCallbacks に設定した

(追記)

  • キャラクターのインスタンスをPhotonMetwork.Instantiate()で作成した

その他

他に必要な情報、コード等あれば追加致します

スクリプト(追記)

  • プレイヤーコントローラー
PlayerController.cs
using UnityEngine;
using Photon.Pun;

[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviourPunCallbacks
{
  [SerializeField] private float moveSpeed = 3;
  [SerializeField] private float runSpeed = 5;
  [SerializeField] private float jumpPower = 8;
  [SerializeField] private Animator animator;
  [SerializeField] private earthground _earthground;
  [SerializeField] private GameObject Camera;
  private bool _pastgrounddetection;
  private CharacterController _characterController;
  private Transform _transform;
  private Vector3 _moveVelocity;
  private Vector3 _eulerAngles;
  PhotonView PV;
    
  private void Awake()
  {
    PV = GetComponent<PhotonView>();
  }

  private void Start()
  {
    //CharacterControllerとtransformを取得
    _characterController = GetComponent<CharacterController>();
    _transform = transform;
    
    if(!PV.IsMine)
      {
        Destroy(GetComponentInChildren<Camera>().gameObject);
        Destroy(GetComponent<Rigidbody>());
        //Destroy(GetComponent<CharacterController>());
      }
  }

  private void FixedUpdate()
  {
    //isMineは正常に動作
    Debug.Log(PV.IsMine);
    if( PV.IsMine == false ) return;//追加

    // 移動のための入力受付
    _moveVelocity.x = Input.GetAxis("Horizontal") * moveSpeed;
    _moveVelocity.z = Input.GetAxis("Vertical") * moveSpeed;
    // カメラの回転をキャラクタの回転に反映
    _eulerAngles = Camera.transform.rotation.eulerAngles;
    transform.rotation = Quaternion.Euler( 0, _eulerAngles.y, 0);

    // ジャンプの入力受付とキャラクタの動作
    if (_earthground.ground_detection == true)
    {
      if (Input.GetKey(KeyCode.Space))
      {
        _moveVelocity.y = jumpPower;
        animator.SetBool("is_jumping", true);
      }
      else
      {
        animator.SetBool("is_jumping", false);
      }
    }
    else
    {
      //もし地面に接触していなければ重力の加速
      _moveVelocity.y += Physics.gravity.y * Time.deltaTime;
    }
    
    if( _pastgrounddetection == false && _earthground.ground_detection == true)
    {
      animator.SetBool("is_jumping", false);
    }

    _pastgrounddetection = _earthground.ground_detection;

    //shiftで走らせる
    if (Input.GetKey(KeyCode.LeftShift) && (_moveVelocity.x != 0 || _moveVelocity.z != 0))
    {
      animator.SetBool("is_running", true);
      _moveVelocity.x = Input.GetAxis("Horizontal") * runSpeed;
      _moveVelocity.z = Input.GetAxis("Vertical") * runSpeed;
    }
    else
    {
      animator.SetBool("is_running", false);
    }

    if (Input.GetMouseButton(0))
    {
      animator.SetTrigger("shot");
    }
    
    //↑で取った左右入力を反映して移動
    _characterController.Move(transform.rotation * _moveVelocity * Time.deltaTime);
    
    animator.SetFloat("MoveSpeed", new Vector3(_moveVelocity.x, 0, _moveVelocity.z).magnitude);
  }
}

  • ルーム作成
RandomMatchMaker.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun; // ★追加
using Photon.Realtime; // ★追加

public class RandomMatchMaker : MonoBehaviourPunCallbacks
{
    public GameObject Player;
    void Start()
    {
        PhotonNetwork.ConnectUsingSettings();
    }
    
    public override void OnConnectedToMaster()
    {
        PhotonNetwork.JoinRandomRoom();
    }

    public override void OnJoinedLobby()
    {
        PhotonNetwork.JoinRandomRoom();
    }

    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        RoomOptions roomOptions = new RoomOptions();
        roomOptions.MaxPlayers = 8; // 最大8人まで入室可能
        PhotonNetwork.CreateRoom(null, roomOptions); //第一引数はルーム名
    }

    public override void OnJoinedRoom()
    {
        PhotonNetwork.Instantiate(
        "Player",
        new Vector3(Random.Range(0f,20f),Random.Range(0f,20f), Random.Range(0f,20f)),   //ポジション
        Quaternion.identity,    //回転
        0
    );
    }
}


0

2Answer

よくある失敗なのでが、両プレイヤーのオブジェクトを用意するときにPhotonNetwork.Instantiate()は使っていますか?ご確認ください

1Like

Comments

  1. @naetoru2144

    Questioner

    回答ありがとうございます!
    はい、その関数を使っていると思います...

  2. なるほど、、、

    isMineがちゃんと正しく設定されているか、Debug.Console()などで確認できますか?
    エディタ側で動かしているオブジェクトがtrueで、それ以外のオブジェクトがfalseなら正常なのですが、、、

  3. @naetoru2144

    Questioner

    確認してみます!少々お待ちください🙇‍♂️

  4. @naetoru2144

    Questioner

    isMineの確認を付けるとTrueとFalseがコンソールに出現し、ビルド側を中断するとFalseのみ消えました。Unity側がTrue、ビルド側がFalseを出力しているのではないかと解釈しています。
    他にはどうすればいいでしょうか...(;ω;)(一応スクリプトも追記いたしました...

  5. なるほど、ありがとうございました。

    スクリプトを再度拝読しましたら、遅ればせながら原因がわかった気がします。

    移動を、スクリプト側ではなく、Animator経由で行っていることが間接的に原因となっていることと推察しています。

    僕もまだまだPUN2の理解が甘いので、どうしてPhotonTransformViewで座標を完全に同期できないのか説明ができないのですが、PUN2からはPhotonAnimationViewが用意されているので、これがカギになりそうだと感じています。

    一度PhotonAnimationViewを設定するとどうなるか、試していただけないでしょうか。

  6. @naetoru2144

    Questioner

    ご回答ありがとうございます。
    すみません、コメントが分かりにくかったのですが、移動は_characterController.Moveで完結しており、animator.SetFloatはなくてもローカルでの座標移動が行われるものになっております(PhotonAnimatorviewもすでに利用しております)

自己解決

CharacterController.Move()とPhotonTransformViewを同時に使うと、位置が同期されなくなるようです。移動をAddforceにした所解消されました。

0Like

Your answer might help someone💌