ここで、紹介する作品は、ドラックによるカメラの回転を、全てのクライアントで行えて、その画面を共有する作品です。
この作品では、以下の2つの自作モジュール群の利用例として作ったものです。
このページの例は、サーバーとクライアント機能をまとめた1つの作品例ですが、
サーバー用の作品とクライアント用作品が別々になっている2つの作品例は、別途こちらのページで紹介しています。
各モジュール詳細は、下記表のリンクをが参照ください。
TCP通信用モジュール | TcpCommunication.cs TcpAppServer.cs |
TCPのバイナリや文字列通信を容易にするモージュールです。 |
シリアライズ用モジュール | BinaryPack.cs | 汎用的なバイナリのシリアライズ・デシリアライズ モジュールで上記の通信用データを対象に使っています。 |
using UnityEngine; public class DragRotate : MonoBehaviour { Vector3 Center_position;//ここを中心に回転 Camera mainCamera; Vector3 prevMousePosition;// 以前のマウス位置 bool prevMouseButton0 = false;// 以前のマウスボタン状態 void Start() { Center_position = new Vector3(0, 0, 0);//ここを中心に回転 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);// 動的生成 Material mat = cube.GetComponent<Renderer>().material; mat.color = new Color(0.5f, 0.5f, 0.5f);//色設定 mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 0, -3);//カメラ位置初期位置 } void Update() { bool nowMouseButtonOn0 = Input.GetMouseButton(0);// 現在のマウス位置を取得 if (this.prevMouseButton0 == false && nowMouseButtonOn0)//マウスボタンを押し込んだ瞬間? { this.prevMousePosition = Input.mousePosition; } else if (nowMouseButtonOn0)//マウスボタンを押し続けている間? { Vector3 diff = Input.mousePosition - prevMousePosition; diff *= 0.2f;// 回転速度を付加 // カメラを、Center_positionを中心に回転 mainCamera.transform.RotateAround(Center_position, Vector3.up, diff.x); mainCamera.transform.RotateAround(Center_position, mainCamera.transform.right, -diff.y); this.prevMousePosition = Input.mousePosition; } this.prevMouseButton0 = nowMouseButtonOn0; } }なお、上記では現在のマウス位置を取得のInput.GetMouseButton(0);だけを利用して、ドラック操作を判定している。
右のUpdateの方が、始めに作ったコードで、簡潔で正しく動作しそうに見える。 しかし、Unity 2022.3.1f1の時点で、Unityエディタでの実行で Input.GetMouseButtonDown(0)のtrue判定を見失う場合がある実験結果が得られた。 (ビルドした作品では正しく動作するので、不具合原因を見つけるのに苦労した。) 以上の不具合より、このコードは使わないこにして、前述のフラグ操作のコードに変更した。 しかし、この考え方は後述のネットワーク化した時の受信側で採用しています。 |
using UnityEngine; public class DragRotate : MonoBehaviour { Vector3 Center_position;//ここを中心に回転 Camera mainCamera; Vector3 prevMousePosition;// 以前のマウス位置 void Start() { Center_position = new Vector3(0, 0, 0);//ここを中心に回転 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);// 動的生成 Material mat = cube.GetComponent<Renderer>().material; mat.color = new Color(0.5f, 0.5f, 0.5f);//色設定 mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 0, -3);//カメラ位置初期位置 } void Update() { if (Input.GetMouseButtonDown(0))//マウスボタンを押し込んだ瞬間? { this.prevMousePosition = Input.mousePosition; } else if (Input.GetMouseButton(0))//マウスボタンを押し続けている間? { Vector3 diff = Input.mousePosition - prevMousePosition; diff *= 0.2f;// 回転速度を付加 // カメラを、Center_positionを中心に回転 mainCamera.transform.RotateAround(Center_position, Vector3.up, diff.x); mainCamera.transform.RotateAround(Center_position, mainCamera.transform.right, -diff.y); this.prevMousePosition = Input.mousePosition; } } } |
using System.IO; using UnityEngine; public class DragRotateNotNet : MonoBehaviour { Vector3 Center_position;//ここを中心に回転 Camera mainCamera; Vector3 prevMousePosition;// 以前のマウス位置 bool prevMouseButton0 = false;// 以前のマウスボタン状態 // オペレータ操作によるイベント情報記憶用 string eventStr = ""; // イベント識別文字列 "MouseButtonDown" or "MouseButton" Vector3 mousePosition;// 情報伝達に使うマウスの位置 void Start() { Center_position = new Vector3(0, 0, 0);//ここを中心に回転 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);// 動的生成 Material mat = cube.GetComponent<Renderer>().material; mat.color = new Color(0.5f, 0.5f, 0.5f);//色設定 mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 0, -3);//カメラ位置初期位置 } void FixedUpdate() { // オペレータ操作によるイベント情報は、一旦、情報伝達変数に記憶 bool nowMouseButtonOn0 = Input.GetMouseButton(0);// 現在のマウス位置を取得 if (this.prevMouseButton0 == false && nowMouseButtonOn0)//マウスボタンを押し込んだ瞬間? { this.eventStr = "MouseButtonDown";// 後で、クライアント側イベント情報の送信部になる this.mousePosition = Input.mousePosition; } else if (nowMouseButtonOn0)//マウスボタンを押し続けている間? { this.eventStr = "MouseButton";// 後で、クライアント側イベント情報の送信部になる this.mousePosition = Input.mousePosition; } this.prevMouseButton0 = nowMouseButtonOn0; // 伝達変数のイベント情報で、動作を進行させる(後で、サーバ側イベント受信部の処理になる) if (this.eventStr == "MouseButtonDown")//マウスボタンを押し込んだ瞬間? { this.prevMousePosition = this.mousePosition; } else if (this.eventStr == "MouseButton")//マウスボタンを押し続けている間? { Vector3 diff = mousePosition - prevMousePosition; diff *= 0.2f;// 回転速度を付加 mainCamera.transform.RotateAround(Center_position, Vector3.up, diff.x); mainCamera.transform.RotateAround(Center_position, mainCamera.transform.right, -diff.y); prevMousePosition = mousePosition; eventStr = ""; } } }の箇所が大きく変更・追加した部分です。
using UnityEngine; using System; using System.Buffers.Binary; public class SerializeVector3Array//Vector3のオブジェクトの配列をシリアライズ { const int ObjectOfVector3Array = 30; //識別ID (重複しないように注意して番号を指定) public Vector3 [] v3array;// Serialize対象データ public static bool Initialize()//デリゲート配列に登録関数 { //MyDataのオブジェクト識別IDの復元関数の登録 if (BinaryPack.dencoders[ObjectOfVector3Array] != null) throw new Exception("BinaryPackの識別IDが重複しています"); BinaryPack.dencoders[ObjectOfVector3Array] = getObjectOfMyData; return true; } public SerializeVector3Array() { }// コンストラクタ public SerializeVector3Array(Vector3 [] v3array)// コンストラクタ { this.v3array = v3array;//シリアライズ対象 } public static BinaryPack.Data getBytesByMyData(SerializeVector3Array pram)//シリアライズ { Vector3[] v3array = pram.v3array; BinaryPack.Data binData = new BinaryPack.Data(ObjectOfVector3Array); binData.bytes = new byte[2 + 4 * 3 * v3array.Length]; byte [] byV3Count = new byte[2]; BinaryPrimitives.WriteUInt16BigEndian(byV3Count, (ushort)v3array.Length); int idx = 0; Buffer.BlockCopy(byV3Count, 0, binData.bytes, idx, byV3Count.Length); idx += byV3Count.Length; for (int n=0; n < v3array.Length; n++) { BinaryPack.Data v3 = BinaryPack.getBytesByFloat(v3array[n].x); Buffer.BlockCopy(v3.bytes, 0, binData.bytes, idx, v3.bytes.Length); idx += v3.bytes.Length; v3 = BinaryPack.getBytesByFloat(v3array[n].y); Buffer.BlockCopy(v3.bytes, 0, binData.bytes, idx, v3.bytes.Length); idx += v3.bytes.Length; v3 = BinaryPack.getBytesByFloat(v3array[n].z); Buffer.BlockCopy(v3.bytes, 0, binData.bytes, idx, v3.bytes.Length); idx += v3.bytes.Length; } return binData; } public static SerializeVector3Array getObjectOfMyData(byte[] buffer, ref int idx)//デシリアライズ { // 配列のidx 位置からのバイナリをSerializeStrVector3に変換 SerializeVector3Array obj = new SerializeVector3Array(); byte[] byV3Count = new byte[2]; Buffer.BlockCopy(buffer, idx, byV3Count, 0, sizeof(ushort)); UInt16 v3count = BinaryPrimitives.ReadUInt16BigEndian(byV3Count);//後ろに並ぶbyte数を取得 obj.v3array = new Vector3[v3count]; idx += 2; for (int n = 0; n < v3count; n++) { Vector3 v3 = new Vector3(); v3.x = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); v3.y = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); v3.z = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.v3array[n] = v3; } return obj; } public static void test()// 単体テスト用 シリアライズ後に復元して、正しくデシリアライズできたか確かめる { //bool regSerializeVector3Array = SerializeVector3Array.Initialize(); // オブジェクト識別IDの登録 //シリアライズ SerializeVector3Array v3array = new SerializeVector3Array(); v3array.v3array = new Vector3[2]; // v3arrayに送信情報を設定 v3array.v3array[0] = new Vector3(0.1f, 0.2f, 0.3f); v3array.v3array[1] = new Vector3(0.5f, 0.6f, 0.7f); byte[] buffer = BinaryPack.getBynary(SerializeVector3Array.getBytesByMyData(v3array)); // デシリアライズ(復元)して、検証 SerializeVector3Array v3array2 = (SerializeVector3Array)BinaryPack.getObjectOfOne(buffer, 0); Debug.Log($"v3array2.v3array[0] :{v3array2.v3array[0]}"); Debug.Log($"v3array2.v3array[0] :{v3array2.v3array[0]}"); } }上記は、SerializeVector3Array.test()で検証用メソッドが実行できる。
using System.IO; using UnityEngine; public class DragRotateNotNet : MonoBehaviour { Vector3 Center_position;//ここを中心に回転 Camera mainCamera; Vector3 prevMousePosition;// 以前のマウス位置 bool prevMouseButton0 = false;// 以前のマウスボタン状態 // オペレータ操作によるイベント情報記憶用 string eventStr = ""; // イベント識別文字列 "MouseButtonDown" or "MouseButton" Vector3 mousePosition;// 情報伝達に使うマウスの位置 // シリアライズ用変数の初期化 static bool regSerializeVector3Array = SerializeVector3Array.Initialize(); // オブジェクト識別IDの登録 const string filePath = "Serialize.bin"; void Start() { Center_position = new Vector3(0, 0, 0);//ここを中心に回転 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);// 動的生成 Material mat = cube.GetComponent<Renderer>().material; mat.color = new Color(0.5f, 0.5f, 0.5f);//色設定 mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 0, -3);//カメラ位置初期位置 // SerializeVector3Array.test(); return; // シリアライス単体のテストデバック BinPacket.topSize = 2; //一回の送信で使うBinPacketの先頭のパケットサイズの記憶バイトを4から2に変更 // filePathのファイルが存在すれば、そのファイル内容で初期表示 FileInfo fileInfo = new FileInfo(filePath); if (true && fileInfo.Exists) { byte[] buffer = new byte[fileInfo.Length]; using (FileStream stream = File.Open(filePath, FileMode.Open)) { int idx = 0; while (idx < buffer.Length) { idx += stream.Read(buffer, idx, buffer.Length - idx);// ファイルから読み込む } } SerializeVector3Array v3array = (SerializeVector3Array)BinaryPack.getObjectOfOne(buffer, 0); mainCamera.transform.position = v3array.v3array[0]; mainCamera.transform.rotation = Quaternion.Euler(v3array.v3array[1]);//オイラー角からQuaternionへ } } void FixedUpdate() { // オペレータ操作によるイベント情報は、一旦、情報伝達変数に記憶 bool nowMouseButtonOn0 = Input.GetMouseButton(0);// 現在のマウス位置を取得 if (this.prevMouseButton0 == false && nowMouseButtonOn0)//マウスボタンを押し込んだ瞬間? { this.eventStr = "MouseButtonDown";// 後で、クライアント側イベント情報の送信部になる this.mousePosition = Input.mousePosition; } else if (nowMouseButtonOn0)//マウスボタンを押し続けている間? { this.eventStr = "MouseButton";// 後で、クライアント側イベント情報の送信部になる this.mousePosition = Input.mousePosition; } this.prevMouseButton0 = nowMouseButtonOn0; // 伝達変数のイベント情報で、動作を進行させる(後で、サーバ側イベント受信部の処理になる) if (this.eventStr == "MouseButtonDown")//マウスボタンを押し込んだ瞬間? { this.prevMousePosition = this.mousePosition; } else if (this.eventStr == "MouseButton")//マウスボタンを押し続けている間? { Vector3 diff = mousePosition - prevMousePosition; diff *= 0.2f;// 回転速度を付加 mainCamera.transform.RotateAround(Center_position, Vector3.up, diff.x); mainCamera.transform.RotateAround(Center_position, mainCamera.transform.right, -diff.y); prevMousePosition = mousePosition; eventStr = ""; } } public void OnApplicationQuit()// プログラム終了時に、SerializeStrVector3オブジェクトをファイル化 { SerializeVector3Array v3array = new SerializeVector3Array(); v3array.v3array = new Vector3[2]; // v3arrayに送信情報を設定 v3array.v3array[0] = mainCamera.transform.position; v3array.v3array[1] = mainCamera.transform.rotation.eulerAngles;//Quaternionからオイラー角へ byte[] buffer = BinaryPack.getBynary(SerializeVector3Array.getBytesByMyData(v3array)); using (FileStream stream = File.Open(filePath, FileMode.Create)) { stream.Write(buffer, 0, buffer.Length);// ファイルに書き込み } } }
using UnityEngine; using System; public class SerializeCamera { const int ObjectOfSerializeCamera = 50; //識別ID (重複しないように注意して番号を指定) public Vector3 position;// Serialize対象データ public Quaternion rotation;// Serialize対象データ public static bool Initialize()//デリゲート配列に登録関数 { //MyDataのオブジェクト識別IDの復元関数の登録 if (BinaryPack.dencoders[ObjectOfSerializeCamera] != null) throw new Exception("BinaryPackの識別IDが重複しています"); BinaryPack.dencoders[ObjectOfSerializeCamera] = getObjectOfMyData; return true; } public SerializeCamera() { }// コンストラクタ public SerializeCamera(Camera camera)// コンストラクタ { this.position = camera.transform.position;//シリアライズ対象 this.rotation = camera.transform.rotation;//シリアライズ対象 } public static BinaryPack.Data getBytesByMyData(Camera camera)//シリアライズ { BinaryPack.Data positionX = BinaryPack.getBytesByFloat(camera.transform.position.x); BinaryPack.Data potitionY = BinaryPack.getBytesByFloat(camera.transform.position.y); BinaryPack.Data potitionZ = BinaryPack.getBytesByFloat(camera.transform.position.z); BinaryPack.Data rotationX = BinaryPack.getBytesByFloat(camera.transform.rotation.x); BinaryPack.Data rotationY = BinaryPack.getBytesByFloat(camera.transform.rotation.y); BinaryPack.Data rotationZ = BinaryPack.getBytesByFloat(camera.transform.rotation.z); BinaryPack.Data rotationW = BinaryPack.getBytesByFloat(camera.transform.rotation.w); BinaryPack.Data binData = new BinaryPack.Data(ObjectOfSerializeCamera); binData.bytes = new byte[sizeof(float) * 3 + sizeof(float) * 4]; int idx = 0;// 以下で、7つのバイト列を結合したbyte配列を作る Buffer.BlockCopy(positionX.bytes, 0, binData.bytes, idx, positionX.bytes.Length); idx += positionX.bytes.Length; Buffer.BlockCopy(potitionY.bytes, 0, binData.bytes, idx, potitionY.bytes.Length); idx += potitionY.bytes.Length; Buffer.BlockCopy(potitionZ.bytes, 0, binData.bytes, idx, potitionZ.bytes.Length); idx += potitionZ.bytes.Length; Buffer.BlockCopy(rotationX.bytes, 0, binData.bytes, idx, rotationX.bytes.Length); idx += rotationX.bytes.Length; Buffer.BlockCopy(rotationY.bytes, 0, binData.bytes, idx, rotationY.bytes.Length); idx += rotationY.bytes.Length; Buffer.BlockCopy(rotationZ.bytes, 0, binData.bytes, idx, rotationZ.bytes.Length); idx += rotationZ.bytes.Length; Buffer.BlockCopy(rotationW.bytes, 0, binData.bytes, idx, rotationW.bytes.Length); idx += rotationW.bytes.Length; return binData; } public static SerializeCamera getObjectOfMyData(byte[] buffer, ref int idx)//デシリアライズ { // 配列のidx 位置からのバイナリをSerializeStrVector3に変換 SerializeCamera obj = new SerializeCamera(); obj.position.x = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.position.y = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.position.z = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.rotation.x = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.rotation.y = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.rotation.z = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); obj.rotation.w = (float)BinaryPack.getObjectOfFloat(buffer, ref idx); return obj; } public static void test() { // bool regSerializeCamera = SerializeCamera.Initialize(); // オブジェクト識別IDの登録 // カメラにテストデータを設定、シリアライズ後に復元して、正しくデシリアライズできたか確かめる Camera mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 1, -10); //テストデータ Vector3 rotationEuler = new Vector3(0,0,0); //テストデータ mainCamera.transform.rotation = Quaternion.Euler(rotationEuler);//オイラー角からQuaternionへ Debug.Log($"{mainCamera.transform.position},{mainCamera.transform.rotation}"); // (0.00, 1.00, -10.00),(0.00000, 0.00000, 0.00000, 1.00000) BinaryPack.Data data = SerializeCamera.getBytesByMyData(mainCamera);//シリアライズ byte[] buffer = BinaryPack.getBynary(data);//シリアライズのオブジェクト識別IDをセット // デシリアライズ(復元)の確認 SerializeCamera serializeCamera = (SerializeCamera)BinaryPack.getObjectOfOne(buffer, 0); Debug.Log($"{serializeCamera.position},{serializeCamera.rotation}"); // (0.00, 1.00, -10.00),(0.00000, 0.00000, 0.00000, 1.00000) rotationEuler = serializeCamera.rotation.eulerAngles;//Quaternionからオイラー角へ Debug.Log($"オイラー角:{rotationEuler}"); // オイラー角: (0.00, 0.00, 0.00) この実行結果で、この例では正しいいと検証した。 } }SerializeVector3Arrayの代わりに、上記のSerializeCameraクラスを利用するように変更した DragRotateNotNet.csを以下に示します。
using System.IO; using UnityEngine; public class DragRotateNotNet : MonoBehaviour { Vector3 Center_position;//ここを中心に回転 Camera mainCamera; Vector3 prevMousePosition;// 以前のマウス位置 bool prevMouseButton0 = false;// 以前のマウスボタン状態 // オペレータ操作によるイベント情報記憶用 string eventStr = ""; // イベント識別文字列 "MouseButtonDown" or "MouseButton" Vector3 mousePosition;// 情報伝達に使うマウスの位置 // シリアライズ用変数の初期化 static bool regSerializeCamera = SerializeCamera.Initialize(); // オブジェクト識別IDの登録 const string filePath = "Serialize.bin"; void Start() { Center_position = new Vector3(0, 0, 0);//ここを中心に回転 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);// 動的生成 Material mat = cube.GetComponent<Renderer>().material; mat.color = new Color(0.5f, 0.5f, 0.5f);//色設定 mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 0, -3);//カメラ位置初期位置 // SerializeCamera.test(); return; // シリアライス単体のテストデバック BinPacket.topSize = 2; //一回の送信で使うBinPacketの先頭のパケットサイズの記憶バイトを4から2に変更 // filePathのファイルが存在すれば、そのファイル内容で初期表示 FileInfo fileInfo = new FileInfo(filePath); if (true && fileInfo.Exists) { byte[] buffer = new byte[fileInfo.Length]; using (FileStream stream = File.Open(filePath, FileMode.Open)) { int idx = 0; while (idx < buffer.Length) { idx += stream.Read(buffer, idx, buffer.Length - idx);// ファイルから読み込む } } SerializeCamera serializeCamera = (SerializeCamera)BinaryPack.getObjectOfOne(buffer, 0); mainCamera.transform.position = serializeCamera.position; mainCamera.transform.rotation = serializeCamera.rotation; } } void FixedUpdate() { // オペレータ操作によるイベント情報は、一旦、情報伝達変数に記憶 bool nowMouseButtonOn0 = Input.GetMouseButton(0);// 現在のマウス位置を取得 if (this.prevMouseButton0 == false && nowMouseButtonOn0)//マウスボタンを押し込んだ瞬間? { this.eventStr = "MouseButtonDown";// 後で、クライアント側イベント情報の送信部になる this.mousePosition = Input.mousePosition; } else if (nowMouseButtonOn0)//マウスボタンを押し続けている間? { this.eventStr = "MouseButton";// 後で、クライアント側イベント情報の送信部になる this.mousePosition = Input.mousePosition; } this.prevMouseButton0 = nowMouseButtonOn0; // 伝達変数のイベント情報で、動作を進行させる(後で、サーバ側イベント受信部の処理になる) if (this.eventStr == "MouseButtonDown")//マウスボタンを押し込んだ瞬間? { this.prevMousePosition = this.mousePosition; } else if (this.eventStr == "MouseButton")//マウスボタンを押し続けている間? { Vector3 diff = mousePosition - prevMousePosition; diff *= 0.2f;// 回転速度を付加 mainCamera.transform.RotateAround(Center_position, Vector3.up, diff.x); mainCamera.transform.RotateAround(Center_position, mainCamera.transform.right, -diff.y); prevMousePosition = mousePosition; eventStr = ""; } } public void OnApplicationQuit()// プログラム終了時に、SerializeStrVector3オブジェクトをファイル化 { BinaryPack.Data data = SerializeCamera.getBytesByMyData(mainCamera);//シリアライズ byte[] buffer = BinaryPack.getBynary(data);//シリアライズのオブジェクト識別IDをセット using (FileStream stream = File.Open(filePath, FileMode.Create)) { stream.Write(buffer, 0, buffer.Length);// ファイルに書き込み } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DragRotateNet : MonoBehaviour { Vector3 Center_position;//ここを中心に回転 Camera mainCamera; Vector3 lastMousePosition;// (サーバ起動側だけが使う変数に取り扱いが変わる) bool lastMouseButton0 = false;// マウスボタン0が押されていればtrue // オペレータ操作によるイベント情報記憶用 string eventStr = ""; // イベント識別文字列 "MouseButtonDown" or "MouseButton" Vector3 mousePosition; // 以下がネットワーク用に追加した変数--------------- TcpCommunication tcpCommunication = new TcpCommunication(); // クライアント用 static bool serializeStrVector3 = SerializeStrVector3.Initialize(); static bool serializeCamera = SerializeCamera.Initialize(); bool flagServer = false;// サーバであればtrue float serverSendNextTiming; //サーバー側で、Time.timeが、この時間以上になったら情報を発信する。 void Start() { Center_position = new Vector3(0, 0, 0);//ここを中心に回転 GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);// 動的生成 Material mat = cube.GetComponent<Renderer>().material; mat.color = new Color(0.5f, 0.5f, 0.5f);//色設定 mainCamera = Camera.main; mainCamera.transform.position = new Vector3(0, 0, -3); GameObject canvas = GameObject.Find("Canvas"); GameObject panel = canvas.gameObject.transform.Find("Panel").gameObject; if (panel != null) panel.SetActive(true);// 無地のパネルを表示 BinPacket.topSize = 2; //一回の送信で使うBinPacketの先頭のパケットサイズの記憶バイトを4から2に変更 // ネットワーク サーバ用初期設定------------------------- Time.fixedDeltaTime = 0.02f;//Application.targetFrameRate = 50;に相当する固定フレーム間隔指定 TcpAppServer.onGUI_width = 400;//OnGUI()で使う表示幅変更 TcpAppServer.onGUI_stepY = 25; TcpAppServer.onGUI_height = 35; TcpAppServer.onGUI_TextFieldFontSize = 26;//OnGUI()で使う表示文字サイス変更 TcpAppServer.onGUI_LabelFontSize = 14; TcpAppServer.onGUI_ButtonFontSize = 16; TcpAppServer.onTcpServerStart += (TcpAppServer server) =>// サーバ起動イベントの処理 { // サーバが起動したら実行 tcpCommunication.ConnectTo();// static メンバtarget_IP, tcp_portが示すサーバーに接続(自身のクライアント機能起動) TcpAppServer.onGUI_flagServer = false;//onGUI用操作画面のサーバ起動部表示のみ消す flagServer = true;// サーバとして、起動したことを記憶! }; TcpAppServer.onReceive += (TcpCommunication com, BinPacket messaeg) =>// サーバの受信処理 { //受信したmessaegのパケットから、SerializeStrVector3を復元して変数にセット SerializeStrVector3 ssv3 = (SerializeStrVector3)BinaryPack.getObjectOfOne(messaeg.packet, BinPacket.topSize); eventStr = ssv3.str;// クライアントからのイベント情報で、操作("MouseButtonDown"か"MouseButton")を記憶 mousePosition = ssv3.v3;// クライアントからのイベント情報で、位置を記憶 TcpAppServer.onGUI_message = $"{com.messageObject}回目サーバ受信:{ssv3.str} 残りキューバッファ数{com.queueBuffer.number} "; if(com.messageObject == null) com.messageObject = 1;// 以下の2行は、この作品に必要ない処理で、 else com.messageObject = (int)com.messageObject + 1;// 各クライアントからの送信数を数える処理の例 }; // ネットワーククライアント用初期設定------------------------- TcpCommunication.onGUI_LabelFontSize = 14; TcpCommunication.tcpClientButton += () =>// ユーザの接続ボタンの処理 { tcpCommunication.ConnectTo();//TCPサーバに接続 }; tcpCommunication.onConnect += () => {// サーバの接続許可で実行するクライアント側のイベント処理 panel.SetActive(false);// パネルを消す //TcpAppServer.onGUI_flag = false;//onGUI用操作画面を消す TcpAppServer.onGUI_flagClient = false;//onGUI用操作画面のクライアントの接続部表示のみ消す TcpAppServer.onGUI_flagServer = false;//onGUI用操作画面のサーバ起動部表示のみ消す }; } public void FixedUpdate() { // サーバ側の処理 :ドラックイベント受信情報で、対象を回転動作を進行させる if (eventStr == "MouseButtonDown")//マウスボタンを押し込んだ瞬間? { lastMousePosition = mousePosition; } else if (eventStr == "MouseButton")//マウスボタンを押し続けている間? { Vector3 diff = mousePosition - lastMousePosition; diff *= 0.2f;// 回転速度を付加 mainCamera.transform.RotateAround(Center_position, Vector3.up, diff.x); mainCamera.transform.RotateAround(Center_position, mainCamera.transform.right, -diff.y); lastMousePosition = mousePosition; eventStr = ""; } // サーバ側の処理で、でカメラ位置と角度を、全てのクライアントに送信する処理 if (this.flagServer) { bool sendTiming = Time.time >= this.serverSendNextTiming; this.serverSendNextTiming = Time.time + 0.01f; // 10ミリ秒ごとに送信(送信し過ぎの制御) byte[] buffer = BinaryPack.getBynary(SerializeCamera.getBytesByMyData(mainCamera)); for (int i = 0; i < TcpAppServer.instance.clientlist.Count; i++) { TcpCommunication com = TcpAppServer.instance.clientlist[i]; if (com == null) continue; if (com.netRemoteString == this.tcpCommunication.netLocalString) continue;// 自身には送らない com.SendMessage(buffer); // クライアントに送信 } } //-------以下がクライアント側の処理------------------ if (this.tcpCommunication.isRecRunning == false) { return;//クライアントの受信スレッドが起動していないならreturn } // クライアントのオペレータ操作によるイベント情報の送信 bool mouseBtn0 = Input.GetMouseButton(0); Vector2 mousePos = Input.mousePosition;// マウス位置 if(this.lastMouseButton0 == false && mouseBtn0)//マウスボタンを押し込んだ瞬間? { SerializeStrVector3 obj = new SerializeStrVector3("MouseButtonDown", mousePos); byte[] buffer = BinaryPack.getBynary(SerializeStrVector3.getBytesByMyData(obj));// シリアライズ byte列取得 this.tcpCommunication.SendMessage(buffer);// パケットに入れて送信 } else if (mouseBtn0)//マウスボタンを押し続けている間? { SerializeStrVector3 obj = new SerializeStrVector3("MouseButton", mousePos); byte[] buffer = BinaryPack.getBynary(SerializeStrVector3.getBytesByMyData(obj)); this.tcpCommunication.SendMessage(buffer);// パケットに入れて送信 } this.lastMouseButton0 = mouseBtn0; // クライアント側の受信処理(受信バッファに存在すれば、最大3個まで取り出して処理) for (int n = 0; n < 3; n++) { BinPacket binPacket = QueueBuffer.GetBuff(tcpCommunication.queueBuffer); // 受信情報の取り出し if (binPacket == null) break;// 受信無しならリターン Debug.Log($"binPacket.packet:{binPacket.packet.Length} byteの受信"); SerializeCamera serializeCamera = (SerializeCamera)BinaryPack.getObjectOfOne(binPacket.packet, BinPacket.topSize); mainCamera.transform.position = serializeCamera.position;//カメラを受信情報で反映させる。 mainCamera.transform.rotation = serializeCamera.rotation; } } private void OnGUI()// (この情報表示は、無くても動作します) { GUI.backgroundColor = Color.cyan;// new Color(0.9f,0.9f,0.9f); GUIStyle lableStyle = GUI.skin.GetStyle("label"); // ---Labelスタイル設定 lableStyle.fontSize = 26; GUI.color = Color.black;//文字色設定 GUI.Label(new Rect(10, 400, 680, 500), TcpCommunication.onGUI_message); } }なおこのソース以外に、BinaryPack.cs、 シリアライスクラズのSerializeStrVector3と SerializeCamera.csが必要です。