ここで、紹介する作品は、ドラックによるカメラの回転を、全てのクライアントで行えて、その画面を共有する作品です。
この作品では、以下の2つの自作モジュール群の利用例として作ったものです。
このページの例は、サーバーとクライアント機能をまとめた1つの作品例ですが、
サーバー用の作品とクライアント用作品が別々になっている2つの作品例は、別途こちらのページで紹介しています。
各モジュール詳細は、下記表のリンクをが参照ください。
| TCP通信用モジュール | TcpCommunication.cs TcpAppServer.cs |
TCPのバイナリや文字列通信を容易にするモージュールです。 |
| シリアライズ用モジュール | BinaryPack.cs | 汎用的なバイナリのシリアライズ・デシリアライズ モジュールで上記の通信用データを対象に使っています。 |
次の3つの作品が各フォルダに入っています。それぞれのフォルダ内のSceneを開いて実行できます。
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が必要です。