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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

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

Unity

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

Q&A

解決済

1回答

1361閲覧

【Unity】【Photon】List<List<〇〇>>を含むクラスのシリアル化

melonplus

総合スコア14

C#

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

Unity

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

0グッド

0クリップ

投稿2020/07/26 04:06

編集2020/07/26 11:16

Photonのカスタムタイプを自作しようとしています。

実現したいこと

独自のクラスをシリアル化できるようにしたい。(RoomInfoをカスタムタイプとして登録したい。)
下記のコードでは、シリアル化できない、とエラーが出る。

コード

カスタムタイプを登録するためのクラス

C#

1using System; 2using System.Collections.Generic; 3using ExitGames.Client.Photon; 4using UnityEngine; 5 6public class MyCustomType : MonoBehaviour 7{ 8 private static readonly byte[] bufferBoxInfo = new byte[4]; 9 10 public static void Register() 11 { 12 PhotonPeer.RegisterType(typeof(RoomInfo), (byte)'R', SerializeRoomInfo, DeserializeRoomInfo); 13 PhotonPeer.RegisterType(typeof(BoxInfo), (byte)'B', SerializeBoxInfo, DeserializeBoxInfo); 14 } 15 16 public static short SerializeRoomInfo(StreamBuffer outStream, object customObject) 17 { 18 var roomInfo = (RoomInfo) customObject; 19 var boxInfosBytes = Protocol.Serialize(roomInfo.BoxInfos); 20 var bufferBoxInfos = new byte[boxInfosBytes.Length]; 21 var index = 0; 22 lock (bufferBoxInfos) 23 { 24 Array.Copy(boxInfosBytes, 0, bufferBoxInfos, index, boxInfosBytes.Length); 25 outStream.Write(bufferBoxInfos, 0, boxInfosBytes.Length); 26 } 27 return (short) boxInfosBytes.Length; 28 } 29 30 public static object DeserializeRoomInfo(StreamBuffer inStream, short length) 31 { 32 var boxInfos = new List<List<BoxInfo>>(); 33 var bufferBoxInfos = new byte[length]; 34 var index = 0; 35 lock (bufferBoxInfos) 36 { 37 inStream.Read(bufferBoxInfos, index, length); 38 boxInfos = (List<List<BoxInfo>>)Protocol.Deserialize(bufferBoxInfos); 39 } 40 return new RoomInfo(boxInfos); 41 } 42 43 public static short SerializeBoxInfo(StreamBuffer outStream, object customObject) 44 { 45 var boxInfo = (BoxInfo) customObject; 46 lock (bufferBoxInfo) 47 { 48 var bytes = bufferBoxInfo; 49 var off = 0; 50 Protocol.Serialize(boxInfo.PlayerId, bytes, ref off); 51 outStream.Write(bytes, 0, 4); 52 return 4; 53 } 54 } 55 56 public static object DeserializeBoxInfo(StreamBuffer inStream, short length) 57 { 58 int playerId; 59 lock (bufferBoxInfo) 60 { 61 inStream.Read(bufferBoxInfo, 0, length); 62 var off = 0; 63 Protocol.Deserialize(out playerId, bufferBoxInfo, ref off); 64 } 65 return new BoxInfo(playerId); 66 } 67}

RoomInfo

C#

1using System; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class RoomInfo : MonoBehaviour 6{ 7 8 private List<List<BoxInfo>> boxInfos; 9 10 public RoomInfo(List<List<BoxInfo>> boxInfos) 11 { 12 this.boxInfos = boxInfos; 13 } 14 15 public RoomInfo() 16 { 17 this.boxInfos = new List<List<BoxInfo>>(); 18 } 19 20 public RoomInfo(int height, int width) 21 { 22 this.boxInfos = new List<List<BoxInfo>>(); 23 for (var y = 0; y < height; y++) 24 { 25 var list = new List<BoxInfo>(); 26 for (var x = 0; x < width; x++) 27 { 28 var boxInfo = new BoxInfo(); 29 list.Add(boxInfo); 30 } 31 boxInfos.Add(list); 32 } 33 } 34 35 public List<List<BoxInfo>> BoxInfos 36 { 37 get 38 { 39 return boxInfos; 40 } 41 set 42 { 43 boxInfos = value; 44 } 45 } 46 47 private BoxInfo GetBoxInfo(int x, int y) 48 { 49 var target = boxInfos[x][y]; 50 if (target == null) 51 { 52 Debug.Log("exception " + x + " " + y); 53 throw new IndexOutOfRangeException(); 54 } 55 return target; 56 } 57 public int GetBoxInfoPlayerId(int x, int y) 58 { 59 return GetBoxInfo(x, y).PlayerId; 60 } 61 62 public void SetBoxInfoPlayerId(int x, int y, int playerId) 63 { 64 GetBoxInfo(x, y).PlayerId = playerId; 65 } 66}

BoxInfo

C#

1using System; 2//using static RoomProperty; 3 4public class BoxInfo 5{ 6 private int playerId { get; set; } 7 8 public int PlayerId 9 { 10 get 11 { 12 return playerId; 13 } 14 set 15 { 16 playerId = value; 17 } 18 } 19 20 public BoxInfo(int playerId) 21 { 22 this.playerId = playerId; 23 } 24 25 public BoxInfo() 26 { 27 // RoomPrepertyでNullPlayerId = -1と定義しています 28 this.playerId = NullPlayerId; 29 } 30}

エラーメッセージ

Exception: cannot serialize(): System.Collections.Generic.List`1[System.Collections.Generic.List`1[BoxInfo]] ExitGames.Client.Photon.Protocol16.Serialize (ExitGames.Client.Photon.StreamBuffer dout, System.Object serObject, System.Boolean setType) (at <11e9abbca912444aa80ed58a280369fc>:0)

参考

Photonでの直列化 | Photon Engine

開発環境

Unity 2018.4.19f1 Personal
PUN 2.18.1

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bboydaisuke

2020/07/26 10:50

「RoomInfoをカスタムタイプとして登録したい」ということは、MyCustomType 内に 2 つ出てくる Protocol.Serialize() の内、先に出てくる方でエラーになっているということでよいですか? この辺は、コードを全部読まなくてもわかるように書いて欲しいです。 using ディレクティブを省いていますが、Protocol クラスの完全修飾名が ExitGames.Client.Photon.Protocol であることとかはきちんと覚えていないので、using ディレクティブは省かないでください。完全修飾名がわからないとリファレンスを探せないためです。エラーメッセージを見ればわかるだろうと考えているんだと思いますが、最後まで読んで戻らないといけないのは面倒です。
melonplus

2020/07/26 11:21

SerializeRoomInfoでエラーが発生していると思われます。以後、気を付けたいと思います。
guest

回答1

0

ベストアンサー

多分 JsonUtility のようなノリで値を渡すとシリアライズして返してくれることを期待してコーディングしたんだと思いますが、参考として挙げている「Photonでの直列化」というドキュメントを見るとそうじゃないみたいですよ。どうやってシリアル化するかを基本型まで自分で分解して決めていく、みたいなことが書かれています。

その証拠に該当の関数にこんなものを渡しても同じエラーになります。

csharp

1using UnityEngine; 2using ExitGames.Client.Photon; 3 4[System.Serializable] 5public class TestClass 6{ 7 public float x; 8 9 public TestClass() 10 { 11 this.x = 0; 12 } 13} 14 15public class TestPhotonSerialize : MonoBehaviour 16{ 17 void Start() 18 { 19 byte[] bArray; 20 21 TestClass t = new TestClass(); 22 bArray = Protocol.Serialize(t); 23 } 24}

もちろん Vector2, Vector3 などを渡しても同じエラーになります。
あとは何のためにシリアライズしたいのかもう一度考えるといいと思います。Event とか RPC に使う時は Photon では object で渡せるので、自分でシリアライズする必要はなかったと思います。

投稿2020/07/26 11:42

bboydaisuke

総合スコア5308

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melonplus

2020/07/26 12:24

ルームのCustomPropertiesにRoomInfoを渡しているのですが、Objectで渡すとはどういうことでしょうか?
bboydaisuke

2020/07/27 15:08 編集

それは「Event とか RPC に使う時は」の話で、大事なのは「何のためにシリアライズしたいのか」です。それをどうしてもやらなければならないならしっかりドキュメントを読み込んで自分のカスタムクラスにシリアライズの処理を追加しなければなりません。
melonplus

2020/07/26 13:36

ルーム情報の同期を行うため、ルーム情報をまとめたクラスをカスタムプロパティにセットしています。この方法では、やはりシリアル化が必要なようです。どこを探しても多次元リストをシリアル化しているものは見つかりませんでしたので、その方法についての質問に至りました。もう少し考えて見ることにします。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問