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

Q&A

1回答

204閲覧

UnityC# Pun2 カスタムプロパティの初期化について

takoyaki0911

総合スコア0

Photon Cloud

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

Photon Server

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

C#

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

Unity

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

0グッド

0クリップ

投稿2026/09/01 01:22

0

0

実現したいこと

以下のオンラインゲームを制作したいです。
~スタート画面~
スタートボタン

~ゲーム画面~
①タイマーの開始

②プレイヤーのオブジェクトを生成

③1秒間隔で上から黒いボールが降ってきて
それに触れると、触れたプレイヤーに+1点

④タイマーの終了

⑤次の画面へ遷移

~リザルト画面~
①画面に得点を表示

②戻るボタンを押すと、
得点とタイマーをリセットしてから
スタート画面に遷移。

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

ゲームをまた最初から始めるとき
1回目に獲得した得点と経過して0になったタイマーを最初の設定に戻したい。

該当のソースコード

using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public class シーン移動 : MonoBehaviour { void Start() { } public void StartButton() { SceneManager.LoadScene("ゲーム画面"); } public void BackButton() { SceneManager.LoadScene("スタート画面"); } }
using Photon.Pun; using UnityEngine; using UnityEngine.UI; using ExitGames.Client.Photon; public class スコアボード用スクリプト : MonoBehaviour { public Text text; private void Start() { } void Update() { if (text == null) return; // 追加: 安全チェック text.text = ""; foreach (var p in PhotonNetwork.PlayerList) { var props = p.CustomProperties; int score = props.ContainsKey("Score") ? (int)props["Score"] : 0; string lastHit = props.ContainsKey("LastHit") ? (string)props["LastHit"] : ""; text.text += $"{p.NickName} : {score}点 {lastHit}\n"; } } }
using Photon.Pun; using Photon.Realtime; using UnityEngine; using ExitGames.Client.Photon; using System.Globalization; public class HitManager : MonoBehaviourPun { public static HitManager Instance; void Awake() { if (Instance == null) { Instance = this; } } [PunRPC] public void NotifyHit(int actorNumber) { Player targetPlayer = null; foreach (var p in PhotonNetwork.PlayerList) { if (p.ActorNumber == actorNumber) { targetPlayer = p; break; } } if (targetPlayer == null) return; // 2. そのプレイヤーの Score を +1 する Hashtable props = new Hashtable(); int currentScore = 0; if (targetPlayer.CustomProperties.ContainsKey("Score")) { currentScore = (int)targetPlayer.CustomProperties["Score"]; } props["Score"] = currentScore + 1; // 3. CustomProperties を更新して全員に同期 targetPlayer.SetCustomProperties(props); Debug.Log($"Score updated for {targetPlayer.NickName}: {currentScore} -> {currentScore + 1}"); } }
using ExitGames.Client.Photon; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.UI; public class 制限時間スクリプト : MonoBehaviourPunCallbacks { [SerializeField] private float limitSeconds = 60f; [SerializeField] private Text timerText; private const string StartTimeKey = "StartTime"; private bool isFinished = false; // void Start() // 修正前 public override void OnJoinedRoom() // // 修正 ルーム参加後に開始時刻を設定 { if (PhotonNetwork.IsMasterClient) { Hashtable hash = new Hashtable(); hash[StartTimeKey] = PhotonNetwork.Time; PhotonNetwork.CurrentRoom.SetCustomProperties(hash); } } void Update() { if (PhotonNetwork.CurrentRoom == null) // // 修正 CurrentRoomがnullなら止める return; if (PhotonNetwork.CurrentRoom.CustomProperties == null) // // 修正 念のためnullチェック return; if (!PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey(StartTimeKey)) return; double startTime = (double)PhotonNetwork.CurrentRoom.CustomProperties[StartTimeKey]; double elapsed = PhotonNetwork.Time - startTime; double remain = limitSeconds - elapsed; if (remain < 0) remain = 0; if (timerText != null) // // 修正 timerText未設定でも落ちないようにする timerText.text = Mathf.CeilToInt((float)remain).ToString(); if (!isFinished && remain <= 0) { isFinished = true; TimeUp(); } } void TimeUp() { Debug.Log("制限時間終了"); } }

PUN2スクリプト

1using Photon.Pun; 2 3using Photon.Realtime; 4using UnityEngine; 5 6// MonoBehaviourPunCallbacksを継承して、PUNのコールバックを受け取れるようにする 7public class SampleScene : MonoBehaviourPunCallbacks 8{ 9 public static int A; 10 private void Start() 11 { 12 13 // プレイヤー自身の名前を"Player"に設定する 14 PhotonNetwork.NickName = "Player"; 15 16 17 18 19 // PhotonServerSettingsの設定内容を使ってマスターサーバーへ接続する 20 PhotonNetwork.ConnectUsingSettings(); 21 22 23 24 25 26 27 28 29 } 30 31 // マスターサーバーへの接続が成功した時に呼ばれるコールバック 32 public override void OnConnectedToMaster() 33 { 34 // "Room"という名前のルームに参加する(ルームが存在しなければ作成して参加する) 35 PhotonNetwork.JoinOrCreateRoom("Room", new RoomOptions(), TypedLobby.Default); 36 } 37 38 // ゲームサーバーへの接続が成功した時に呼ばれるコールバック 39 public override void OnJoinedRoom() 40 { 41 42 PhotonNetwork.NickName = "Player" + PhotonNetwork.LocalPlayer.ActorNumber + ""; // 43 44 45 46 47 48 49 GameObject bullet = PhotonNetwork.Instantiate("Sphere", transform.position, Quaternion.identity); 50 51 52 bullet.GetComponent<Destry>().ownerActorNumber = PhotonNetwork.LocalPlayer.ActorNumber; 53 54 55 } 56 57 58 private void Update() 59 { 60 if (Input.GetKeyDown(KeyCode.Space)) 61 { 62 PhotonNetwork.Instantiate("Black", new Vector3(0,5,0), Quaternion.identity); 63 64 65 66 67 } 68 } 69 70 71 72}

試したこと・調べたこと

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

結果はできませんでした。

補足

特になし

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

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

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

takoyaki0911

2026/09/01 01:54

【リザルト表示スクリプト】 using UnityEngine; using UnityEngine.UI; using Photon.Pun; public class bbb : MonoBehaviour { public Text text; void Update() { if (text == null) return; // 追加: 安全チェック text.text = ""; foreach (var p in PhotonNetwork.PlayerList) { var props = p.CustomProperties; int score = props.ContainsKey("Score") ? (int)props["Score"] : 0; string lastHit = props.ContainsKey("LastHit") ? (string)props["LastHit"] : ""; text.text += $"{p.NickName} : {score}点 {lastHit}\n"; } } }
takoyaki0911

2026/09/01 01:55

【スクリプトの置き場所】 スタート画面… シーン移動 ゲーム画面… スコアボード用スクリプト…ゲーム画面シーンのテキストにアタッチします。 PUN2スクリプト HitManager 制限時間スクリプト リザルト画面… シーン移動 リザルトスクリプト
guest

回答1

0

① シーン移動スクリプトを変更
現在の シーン移動 を以下に置き換えてください。

c#

1using Photon.Pun; 2using Photon.Realtime; 3using ExitGames.Client.Photon; 4using UnityEngine; 5using UnityEngine.SceneManagement; 6 7public class シーン移動 : MonoBehaviourPun 8{ 9 private const string ScoreKey = "Score"; 10 private const string StartTimeKey = "StartTime"; 11 12 // スタートボタン 13 public void StartButton() 14 { 15 if (!PhotonNetwork.InRoom) 16 { 17 Debug.LogWarning("Photonのルームに参加していません。"); 18 return; 19 } 20 21 // 自分がMasterClientなら直接開始 22 if (PhotonNetwork.IsMasterClient) 23 { 24 StartGame(); 25 } 26 else 27 { 28 // MasterClientにゲーム開始を依頼 29 photonView.RPC(nameof(RequestStartGame), RpcTarget.MasterClient); 30 } 31 } 32 33 // 他のプレイヤーからゲーム開始を依頼されたとき 34 [PunRPC] 35 private void RequestStartGame() 36 { 37 if (!PhotonNetwork.IsMasterClient) 38 return; 39 40 StartGame(); 41 } 42 43 // 実際にゲームを開始する処理 44 private void StartGame() 45 { 46 // 全プレイヤーのスコアを0にする 47 foreach (Player player in PhotonNetwork.PlayerList) 48 { 49 Hashtable props = new Hashtable(); 50 props[ScoreKey] = 0; 51 props["LastHit"] = ""; 52 53 player.SetCustomProperties(props); 54 } 55 56 // タイマーの開始時刻を「今」にリセット 57 Hashtable roomProps = new Hashtable(); 58 roomProps[StartTimeKey] = PhotonNetwork.Time; 59 60 PhotonNetwork.CurrentRoom.SetCustomProperties(roomProps); 61 62 Debug.Log("ゲーム開始:スコアとタイマーをリセットしました。"); 63 64 // 全員をゲーム画面へ移動 65 PhotonNetwork.LoadLevel("ゲーム画面"); 66 } 67 68 // 戻るボタン 69 public void BackButton() 70 { 71 PhotonNetwork.LoadLevel("スタート画面"); 72 } 73}

② 制限時間スクリプトを変更
以下に変更してください。

c#

1using Photon.Pun; 2using UnityEngine; 3using UnityEngine.UI; 4 5public class 制限時間スクリプト : MonoBehaviourPun 6{ 7 [SerializeField] private float limitSeconds = 60f; 8 [SerializeField] private Text timerText; 9 10 private const string StartTimeKey = "StartTime"; 11 12 private bool isFinished = false; 13 14 void Start() 15 { 16 isFinished = false; 17 } 18 19 void Update() 20 { 21 if (!PhotonNetwork.InRoom) 22 return; 23 24 if (PhotonNetwork.CurrentRoom.CustomProperties == null) 25 return; 26 27 if (!PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey(StartTimeKey)) 28 return; 29 30 double startTime = 31 (double)PhotonNetwork.CurrentRoom.CustomProperties[StartTimeKey]; 32 33 double elapsed = PhotonNetwork.Time - startTime; 34 double remain = limitSeconds - elapsed; 35 36 if (remain < 0) 37 remain = 0; 38 39 if (timerText != null) 40 { 41 timerText.text = Mathf.CeilToInt((float)remain).ToString(); 42 } 43 44 if (!isFinished && remain <= 0) 45 { 46 isFinished = true; 47 TimeUp(); 48 } 49 } 50 51 private void TimeUp() 52 { 53 Debug.Log("制限時間終了"); 54 55 // MasterClientだけがリザルト画面へ移動 56 if (PhotonNetwork.IsMasterClient) 57 { 58 PhotonNetwork.LoadLevel("リザルト画面"); 59 } 60 } 61}

③ スコアについて
現在の HitManager は基本的にそのままでも大丈夫です。

c#

1[PunRPC] 2public void NotifyHit(int actorNumber) 3{ 4 Player targetPlayer = null; 5 6 foreach (var p in PhotonNetwork.PlayerList) 7 { 8 if (p.ActorNumber == actorNumber) 9 { 10 targetPlayer = p; 11 break; 12 } 13 } 14 15 if (targetPlayer == null) 16 return; 17 18 Hashtable props = new Hashtable(); 19 20 int currentScore = 0; 21 22 if (targetPlayer.CustomProperties.ContainsKey("Score")) 23 { 24 currentScore = (int)targetPlayer.CustomProperties["Score"]; 25 } 26 27 props["Score"] = currentScore + 1; 28 29 targetPlayer.SetCustomProperties(props); 30 31 Debug.Log( 32 $"Score updated for {targetPlayer.NickName}: " + 33 $"{currentScore} -> {currentScore + 1}" 34 ); 35}

④ リザルト画面から戻る場合

c#

1public void BackButton() 2{ 3 SceneManager.LoadScene("スタート画面"); 4}

でもスタート画面には戻れます。

ただし、ここでスコアを0にする必要はありません。

なぜなら、

スタートボタンを押した瞬間

にスコアを0にする設計にしたからです。

最終的な考え方
今回一番重要なのは、「ルーム参加」と「ゲーム開始」を分けることです。

OnJoinedRoom()

ルームに参加しただけ

まだタイマー開始しない

スタート画面

スタートボタン

Score = 0
StartTime = PhotonNetwork.Time

ゲーム画面

60秒

リザルト

これなら、2回目、3回目とゲームを繰り返しても、スコアとタイマーが毎回初期状態に戻ります。

なお、複数人で同じPhoton Roomに入ってプレイする仕様なら、PhotonNetwork.LoadLevel() を使ったMasterClientによるシーン同期も重要なので、SampleScene 側で PhotonNetwork.AutomaticallySyncScene = true; を設定しておくことをおすすめします。

投稿2026/09/04 06:30

nryu783

総合スコア6

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.25%

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

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

質問する

関連した質問