質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
87.20%
Photon Cloud

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

Photon Server

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

受付中

Unity、Photonで多数決機能を実装する方法

studyUSAAA
studyUSAAA

総合スコア17

Photon Cloud

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

Photon Server

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

0回答

0評価

0クリップ

106閲覧

投稿2022/07/02 07:14

Unity、Photon初心者です。お手数をおかけしてしまい、大変申し訳ございませんが、助けてくださると助かります。

[やりたいこと]
・Unity✖︎Photonで多数決機能を実装したい
AとB、2つの動画をボタン式の選択肢で提示し、複数人の多数決で多く選択された方の動画が流れるシステムを作りたい。

[出来ていること]
①ボタンを選択したら対応した動画が流れる。(notマルチプレイ対応)
②Photonサーバーに接続し、複数の人数が動画を選択できる状態になる(動画の同期は出来ていない)

[教えていただきたいこと(お手数をおかけしますが、コードを教えていただけると助かります)]
投票の管理をマスタークライアントで行う
①ReceiverGroup に MasterClient を指定して Photon.Pun.PhotonNetwork.RaiseEvent() を呼び、投票内容をマスタークライアントに送る
(最初にプレイヤーの人数を認識する。次にChange V Buttonスクリプトにおいてボタンを押したらマスターに投票結果を送る?)
②マスタークライアントは投票を集計して最多得票を決定し、同じく RaiseEvent で全員に結果を送る
(参加者の人数と投票結果から、多数決で選ばれた動画を再生するようにRaiseEventで全員に命令?)
*Change V Buttonスクリプトを書き換えればいいのでしょうか。。。?

[現状]
1.動画の選択再生(マルチ非対応、一人で選択したら動画が流れる状況)
イメージ説明

①PlaneオブジェクトにVideo PlayerとChange VIdeoスクリプト(動画を読み込んで再生)をアタッチ
イメージ説明

C#

using UnityEngine; using UnityEngine.Video; public class ChangV : MonoBehaviour { public VideoPlayer Vp { get; private set; } void Start() { Vp = GetComponent<VideoPlayer>(); //↓VideoPlayerの再生準備ができたとき、OnVideoPlayerPreparedが呼ばれる Vp.prepareCompleted += OnVideoPlayerPrepared; } void OnVideoPlayerPrepared(VideoPlayer vp) { vp.Play(); } public void ChangeVideo(VideoID id) { //既にVideoPlayerに動画が読み込まれている場合 if (Vp.clip != null) { Vp.Stop(); //↓その動画をメモリから解放する Resources.UnloadAsset(Vp.clip); } var meta = id.GetMeta(); // var title = meta.Title; //動画をメモリに読み込む Vp.clip = Resources.Load<VideoClip>(meta.Path); //↓VideoPlayerに再生準備をさせる Vp.Prepare(); } }

②Canvasにボタンの親オブジェクトを配置し、Change V Button Contorollerスクリプト(ボタンの管理)をアタッチ
イメージ説明

C#

using UnityEngine; using UnityEngine.Assertions; using UnityEngine.Video; /// <summary> /// ボタンの管理 /// すべてのボタンをこのスクリプトがアタッチされた子に配置 /// </summary> public class ChangVButtonController : MonoBehaviour { [SerializeField] ChangV changV; /// <summary> /// Videoが再生中か? /// </summary> public bool IsPlaying => changV.Vp.isPlaying; ChangVButton[] buttons; void Awake() { buttons = GetComponentsInChildren<ChangVButton>(true); Assert.IsTrue(buttons.Length > 0, "ボタンが0です。すべてのボタンをこのスクリプトがアタッチされた子に配置してください。"); } void Start() { foreach (var button in buttons) { button.SetController(this); } changV.Vp.loopPointReached += OnLoopPointReached; } public void ChangeVideo(VideoID videoID) { Assert.IsTrue(!IsPlaying, "再生中に再生が呼ばれました"); changV.ChangeVideo(videoID); foreach (var button in buttons) { button.gameObject.SetActive(false); } } void OnLoopPointReached(VideoPlayer source) { foreach (var button in buttons) { button.gameObject.SetActive(true); } } void Reset() { changV = FindObjectOfType<ChangV>(); } }

③ボタンA,BにChang V Buttonスクリプト(動画の選択)をアタッチ
イメージ説明

C#

using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Button))] public class ChangVButton : MonoBehaviour { [SerializeField] Button playButton; [SerializeField] VideoID playTarget; ChangVButtonController controller; void Start() { playButton.onClick.AddListener(ClickPlayButton); } public void SetController(ChangVButtonController controller) { this.controller = controller; } /// <summary> /// プレイボタンのクリック /// </summary> void ClickPlayButton() { if (!controller.IsPlaying) { controller.ChangeVideo(playTarget); } } void Reset() { playButton = GetComponent<Button>(); } }

④アセットにVideoMetaDataスクリプト(動画の管理)を追加

C#

using System.Collections.Generic; using UnityEngine; /// <summary> /// ビデオのID /// ※ 最初に設定する順番変更禁止。増やす場合は後に追加 /// </summary> public enum VideoID { London = 0, op = 1, yasi = 2, // 他動画のIDをここに追加していく } public class VideoMeta { public VideoID ID; public string Title; public string Path; // 入れたい情報を書き足していく } public static class VideoExtensions { static readonly IEnumerable<VideoMeta> Metas = new VideoMeta[] { new VideoMeta { ID = VideoID.London, Title = "ロンドン", Path = "London" }, new VideoMeta { ID = VideoID.op, Title = "op", Path = "op" }, new VideoMeta { ID = VideoID.yasi, Title = "yasi", Path = "yasi" }, // 他動画の情報をここに追加していく }; /// <summary> /// Videoの情報を取得 /// </summary> public static VideoMeta GetMeta(this VideoID id) { foreach (var meta in Metas) { if (meta.ID == id) { return meta; } } Debug.LogError($"存在しないVideo {id}"); return default; } }

2.複数人で動画選択(Photon実装)
①アバター(白い円)のプレハブを作成し、AvatarControllerスクリプト(マスカーソルに合わせて白い円を動かす)→誰がどの選択肢を選ぶか見えるように
イメージ説明

C#

using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; // MonoBehaviourPunCallbacksを継承して、photonViewプロパティを使えるようにする public class AvatarController : MonoBehaviourPunCallbacks { private void Update() { // 自身が生成したオブジェクトだけに移動処理を行う if (photonView.IsMine) { Vector3 touchScreenPosition = Input.mousePosition; // 10.0fに深い意味は無い。画面に表示したいので適当な値を入れてカメラから離そうとしているだけ. touchScreenPosition.z = 120.0f; Camera gameCamera = Camera.main; Vector3 touchWorldPosition = gameCamera.ScreenToWorldPoint(touchScreenPosition); transform.position = touchWorldPosition; } } }

②OtherPlayersオブジェクトにOtherPlayersスクリプト(Photonサーバーに接続したらアバター(白い円)を作成する)をアタッチ
イメージ説明

C#

using Photon.Pun; using Photon.Realtime; using UnityEngine; // MonoBehaviourPunCallbacksを継承して、PUNのコールバックを受け取れるようにする public class OtherPlayers : MonoBehaviourPunCallbacks { private void Start() { // プレイヤー自身の名前を"Player"に設定する PhotonNetwork.NickName = "Player"; // PhotonServerSettingsの設定内容を使ってマスターサーバーへ接続する PhotonNetwork.ConnectUsingSettings(); } // マスターサーバーへの接続が成功した時に呼ばれるコールバック public override void OnConnectedToMaster() { // "Room"という名前のルームに参加する(ルームが存在しなければ作成して参加する) PhotonNetwork.JoinOrCreateRoom("Room", new RoomOptions(), TypedLobby.Default); } // ゲームサーバーへの接続が成功した時に呼ばれるコールバック public override void OnJoinedRoom() { // ランダムな座標に自身のアバター(ネットワークオブジェクト)を生成する var position = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f)); PhotonNetwork.Instantiate("Avatar", position, Quaternion.identity); } }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Photon Cloud

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

Photon Server

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。