質問するログイン新規登録

Q&A

1回答

123閲覧

UnityC# PUN2の子オブジェクトのオブジェクト同期ができない

takoyaki0911

総合スコア0

Photon Cloud

Photon Cloudは、オンラインゲーム開発向けネットワークエンジン。リアルタイムマルチプレイ通信のプラットフォームであるPhotonの一つです。ネットワーク通信によるオンラインゲームを開発・運営するために必要なツールがサーバー環境に構築されています。

Photon Server

Photon Serverは、オンラインゲーム開発向けネットワークエンジン。リアルタイムマルチプレイ通信のプラットフォームであるPhotonの一つで、サーバにインストールして使うサーバアプリケーションです。全てカスタマイズが可能で権限管理もできます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2026/07/08 13:52

0

1

実現したいこと

PUN2を使用して2プレイヤー用のゲームを作りたいです。
メニュー画面からプレイヤー1とプレイヤー2を選び
1プレイヤーは人間(A・Sキーで左右移動)。2プレイヤーはその人間が持っているボール(Z・Xキーで左右移動)です。人間が親オブジェクトでボールが子オブジェクトです。

発生している問題・分からないこと

実行すると、
プレイヤー2側がボールを動かしても
プレイヤー1側から見てプレイヤー2側のボールが動きません。

該当のソースコード

Aの移動

1Aの移動 2using Photon.Pun; 3using Photon.Realtime; 4using UnityEngine; 5 6 7public class Aの移動 : MonoBehaviourPunCallbacks 8{ 9 public GameObject A; 10 11 12 13 14 15 // Start is called once before the first execution of Update after the MonoBehaviour is created 16 void Start() 17 { 18 19 } 20 21 // Update is called once per frame 22 void Update() 23 { 24 25 if (!photonView.IsMine) return; 26 { 27 28 29 if (Input.GetKey(KeyCode.A)) 30 { 31 A.transform.position += transform.right * 0.1f; 32 33 } 34 if (Input.GetKey(KeyCode.S)) 35 { 36 A.transform.position -= transform.right * 0.1f; 37 38 } 39 40 41 42 43 44 } 45 } 46 47 48 49 50 51 52 53 54 }

Bの移動

1Bの移動 2using Photon.Pun; 3using UnityEngine; 4using Photon.Realtime; 5 6public class Bの移動 : MonoBehaviourPunCallbacks 7{ 8 9 10 11 PhotonView operatorView; // 操作権を持つプレイヤー 12 // Start is called once before the first execution of Update after the MonoBehaviour is created 13 void Start() 14 { 15 16 } 17 18 // Update is called once per frame 19 void Update() 20 { 21 if (photonView.IsMine) return; 22 23 { 24 25 if (Input.GetKey(KeyCode.Z)) 26 { 27 transform.position += transform.right * 0.1f; 28 // B.transform.RotateAround(A.transform.position, Vector3.forward, 50 * Time.deltaTime); 29 } 30 31 32 if (Input.GetKey(KeyCode.X)) 33 { 34 transform.position -= transform.right * 0.1f; 35 //B.transform.RotateAround(A.transform.position, Vector3.forward, -50 * Time.deltaTime); 36 } 37 } 38 39 40 } 41 public void BBB() 42 { 43 photonView.TransferOwnership(PhotonNetwork.LocalPlayer); 44 } 45 46} 47 48 49 50 51
メニュースクリプト using UnityEngine; using UnityEngine.SceneManagement; public class メニュースクリプト : MonoBehaviour { public static byte type; // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { type = 0; } // Update is called once per frame void Update() { } public void B() { type = 1; SceneManager.LoadScene("ゲーム画面"); } public void B1() { type = 2; SceneManager.LoadScene("プレイ画面"); } }

PUN2

1PUN2 2using Photon.Pun; 3using Photon.Realtime; 4using UnityEngine; 5 6using UnityEngine.UI; 7 8public class PUN2 : MonoBehaviourPunCallbacks 9{ 10 public static int A; 11 12 13 public Bの移動 b; 14 15 16 17 public GameObject f; 18 19 private void Start() 20 { 21 22 if (!photonView.IsMine) 23 { 24 enabled = false; 25 return; 26 } 27 28 // PhotonServerSettingsの設定内容を使ってマスターサーバーへ接続する 29 PhotonNetwork.ConnectUsingSettings(); 30 } 31 32 // マスターサーバーへの接続が成功した時に呼ばれるコールバック 33 public override void OnConnectedToMaster() 34 { 35 // "Room"という名前のルームに参加する(ルームが存在しなければ作成して参加する) 36 PhotonNetwork.JoinOrCreateRoom("Room", new RoomOptions(), TypedLobby.Default); 37 } 38 39 // ゲームサーバーへの接続が成功した時に呼ばれるコールバック 40 public override void OnJoinedRoom() 41 { 42 43 44 45 46 47 48 49 50 51 52 53 54 byte type = メニュースクリプト.type; 55 // ▼ ボタン1:Aを生成 56 if (type == 1) 57 { 58 textA.enabled = true; 59 60 //インスタンス生成 61 GameObject s = PhotonNetwork.Instantiate("Sp", transform.position, Quaternion.identity); 62 63 64 65 66 67 //AからはBは動かない。 68 var c = f.GetComponentInChildren<Bの移動>(); 69 c.enabled = false; 70 71 72 } 73 74 // ▼ ボタン2:AがあればB操作をON 75 if (type == 2) 76 { 77 78 textB.enabled = true; 79 80 // まず A があるか確認 81 GameObject a = GameObject.FindWithTag("A"); 82 83// 2. 生成したインスタンスの子からスクリプトを探す 84 var c = f.GetComponentInChildren<Bの移動>(); 85 c.enabled = true; 86 87 88 89 90 91 92 //Aの移動をオフにする。 93 var A = f.GetComponent<Aの移動>(); 94 A.enabled = false; 95 96 97 98 99 100 101 } 102 } 103 104} 105 106 107 108 109 110 111 112

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

子オブジェクトのオブジェクト同期ができない。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

guest

回答1

0

「Bの移動」の19行目以降について、以下のように書かれています。

C#

1 void Update() 2 { 3 if (photonView.IsMine) return; 4 { 5 // ローカルの各種操作処理 6 } 7 }

この場合、photonView.IsMineがtrueのときに、return;のみが行われます。
{}の中の処理は、特にif文とは関係なく、returnされていなければ実行される具合になります。
つまり、この書き方は滅茶苦茶で、書き直すと以下のようになります。

C#

1 void Update() 2 { 3 if (photonView.IsMine) 4 { 5 return; 6 } 7 8 // ローカルの各種操作処理 9 }

上記を見てわかるように、photonView.IsMineが偽、つまり操作中のプレイヤーではないときに操作処理が行われるという真逆の処理になっています。
そのため、プレイヤー2からは操作できず、逆に他のプレイヤー(プレイヤー1)から操作できるようになっています。
直すには、これを逆(例えば!を付けるなど)をする必要があります。

また、この「Aの移動」や「Bの移動」にはPUN2で同期処理は含まれていません。
おそらく、PhotonTransformViewで位置を同期しているのだと思います。
ただ、私の記憶では入れ子にするとこれは正しく動作しなかったはずなので、代替えのコンポーネントがあるか探し、なければ自作することになると思います(そこは詳しくないので、すみませんが説明できません)
あるいは、親子関係を見直し、直接的な親子関係にしないという手もあると思います。


蛇足ですが、「Bの移動」のような日本語の名前にすると、正常に動作しないことが過去のUnityでありました。
他は動作しているとのことで、おそらく修正されたのだと思いますが、念のため使わないほうがいいかもしれません。

投稿2026/07/09 01:43

fiveHundred

総合スコア10552

takoyaki0911

2026/07/09 04:01

回答ありがとうございます。 「Aの移動」と「Bの移動」を if (!photonView.IsMine) { return; } に変更すると、 ボールが同期しますが、 人間が同期しなくなりました。
fiveHundred

2026/07/09 06:01

再度確認しましたが、ちゃんとドキュメント通りに書きましたか? コードを見た感じ、最初からプレイヤー1をシーン上に配置されているようですが、その場合「何らかの方法で配置済みのオブジェクトの所有権を変更する」か「そもそも根本的にやり方が間違っている」かのどっちかだと思います。 PUN2は詳しくありませんが、少なくとも記述のコードだけでは、「どちらが操作するオブジェクトか」すら設定できていないように思えます。 (そもそも、この手のものはプレイヤーオブジェクトはシーンに配置せずに特定の関数で生成することがほとんどだと思います)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.25%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問