934 lines
29 KiB
C#
934 lines
29 KiB
C#
using BigSpace.Logic;
|
||
using BigSpace.XRCore.Event;
|
||
using Netly;
|
||
using Netly.Core;
|
||
using Newtonsoft.Json;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using Unity.VisualScripting;
|
||
using UnityEngine;
|
||
using UnityEngine.Events;
|
||
using UnityEngine.SceneManagement;
|
||
using UnityEngine.UIElements;
|
||
using UnityEngine.XR;
|
||
|
||
public class VR2 : MonoBehaviour
|
||
{
|
||
public static VR2 Instance;
|
||
//public Game
|
||
|
||
TcpClient client;
|
||
|
||
bool isConnecting;
|
||
uint wearingState;
|
||
|
||
DateTime connTime, dateTime, posTime, allinfoTime;
|
||
|
||
Register register = new();
|
||
Logout logout = new();
|
||
VRInfo vrinfo = new();
|
||
VRPos vrpos = new();//自己的位置
|
||
ObjPos gPos = new();
|
||
Ask ask = new();
|
||
Inform inform = new();
|
||
BackInfo backInfo = new();
|
||
float statHight = 0; //开始的高度
|
||
Vector3 lastPos; //最后的位置
|
||
float distance = 0; //最后的位置和最新位置的距离
|
||
Vector3 myPositionChang; //这个是自己修改过的高度,要传给服务器
|
||
|
||
Vector3 db_myPosition; //自己对比距离的位置
|
||
Vector3 db_otherPosition; //别人对比距离的位置
|
||
float db_distance = 0; //对比的距离
|
||
//TimelineProgress timelineProgress = new();
|
||
|
||
string user = "u";
|
||
|
||
Transform cameraTran;
|
||
|
||
public Transform otherPlayers;
|
||
|
||
float quitTimers;
|
||
|
||
uint human;
|
||
|
||
private Dictionary<int, Action<string>> _messageHandlers = new();
|
||
|
||
public GameObject cubeObj;
|
||
|
||
internal UnityEvent<uint, int> OnTimelineProgress = new();
|
||
// 存储所有Good对象的字典
|
||
private Dictionary<string, Good> goodsDictionary = new Dictionary<string, Good>();
|
||
|
||
int erorrCount;
|
||
private Memory<byte> _receiveMemory = Memory<byte>.Empty; //缓冲区
|
||
|
||
private void Awake()
|
||
{
|
||
if (Instance == null)
|
||
{
|
||
Instance = this;
|
||
}
|
||
}
|
||
void Start()
|
||
{
|
||
//PicoAPI._Instance.OpenTouPing();
|
||
//PicoAPI._Instance.KillAppsByPidOrPackageName("com.pvr.picocast");
|
||
Initialize();
|
||
Invoke("Init", 0.5f);
|
||
|
||
GlobalEventMgr.Listen<int>(GameEvent.EventAnimalSend, GameDataManage_EventAnimalSend);
|
||
|
||
// MyLoadSceneAsync(1);//加载第一个内容场景
|
||
}
|
||
void ReadConfig()
|
||
{
|
||
if (File.Exists(Config.IpConfig))
|
||
{
|
||
string[] str = File.ReadAllText(Config.IpConfig).Split('\n');
|
||
Config.TcpHost = str[0];
|
||
WebNet.webIp = str[1];
|
||
|
||
WebNet.assetsUrl = $"{WebNet.webIp}/api/dev/login";
|
||
WebNet.DownAssetsUrl = $"{WebNet.webIp}/storage/resource";
|
||
WebNet.UploadInfoUrl = $"{WebNet.webIp}/api/dev/uploadUsageInfo";
|
||
WebNet.getDeviceList = $"{WebNet.webIp}/api/tablet/getDeviceList";
|
||
WebNet.uploadEQ = $"{WebNet.webIp}/api/dev/uploadEQ";
|
||
}
|
||
else
|
||
{
|
||
string str = $"{Config.TcpHost}\n{WebNet.webIp}";
|
||
File.WriteAllText(Config.IpConfig, str);
|
||
}
|
||
}
|
||
void Init()
|
||
{
|
||
ReadConfig();
|
||
|
||
|
||
cameraTran = Camera.main.transform;
|
||
statHight = Camera.main.transform.position.y;
|
||
connTime = DateTime.Now;
|
||
dateTime = DateTime.Now.AddSeconds(-25);
|
||
posTime = DateTime.Now;
|
||
allinfoTime = DateTime.Now.AddSeconds(-45);
|
||
|
||
if (Application.isEditor)
|
||
Config.SN = "PA9412MGJC120200G";
|
||
else
|
||
Config.SN = PicoAPI._Instance.PicoSN();
|
||
|
||
client = new TcpClient(framing: false);
|
||
client.OnOpen(open);
|
||
client.OnClose(close);
|
||
client.OnError(error);
|
||
client.OnEvent(msgEvent);
|
||
client.OnData(msgData);
|
||
}
|
||
void Initialize()
|
||
{
|
||
_messageHandlers[7] = HandleAllIfo;
|
||
_messageHandlers[8] = HandleGood;
|
||
_messageHandlers[4] = HandleVRPosition;
|
||
_messageHandlers[6] = HandleLogout;
|
||
_messageHandlers[12] = HandleVRControl;
|
||
_messageHandlers[13] = HandleInform;
|
||
_messageHandlers[21] = HandleTimeLineProgress;
|
||
}
|
||
|
||
//发送创建动物事件
|
||
void GameDataManage_EventAnimalSend(int animalType)
|
||
{
|
||
sendCom(3, animalType, 0);
|
||
}
|
||
|
||
void Update()
|
||
{
|
||
//测试
|
||
if (Input.GetKeyDown(KeyCode.Space))
|
||
{
|
||
//Logout logout = new Logout();
|
||
//logout.group = 8;
|
||
//logout.sn = "PA9410MGJ9280275G";
|
||
//sendMessage(6, logout);
|
||
//logout.group = 8;
|
||
//logout.sn = "PA9410PGJ6170013H";
|
||
//sendMessage(6, logout);
|
||
//sendCom(1, 0, 0);
|
||
MyLoadSceneAsync(2);
|
||
|
||
}
|
||
else if(Input.GetKeyDown(KeyCode.Q))
|
||
{
|
||
MyLoadSceneAsync(1);
|
||
}
|
||
|
||
//退出游戏
|
||
if (Input.GetKey(KeyCode.JoystickButton0))
|
||
{
|
||
quitTimers += Time.deltaTime;
|
||
if (quitTimers > 3f)
|
||
{
|
||
quitTimers = 0f;
|
||
sendLogout();
|
||
Invoke("Quit", 2f);
|
||
}
|
||
}
|
||
if (InputDevices.GetDeviceAtXRNode(XRNode.RightHand).TryGetFeatureValue(CommonUsages.primaryButton, out bool islogout))
|
||
{
|
||
if (islogout)
|
||
{
|
||
quitTimers += Time.deltaTime;
|
||
if (quitTimers > 3f)
|
||
{
|
||
quitTimers = 0f;
|
||
sendLogout();
|
||
Quit();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
quitTimers = 0f;
|
||
}
|
||
}
|
||
if (InputDevices.GetDeviceAtXRNode(XRNode.RightHand).TryGetFeatureValue(CommonUsages.primaryButton, out bool isshow))
|
||
{
|
||
if (isshow)
|
||
{
|
||
sendCom(1, 0, 0);
|
||
}
|
||
}
|
||
if (InputDevices.GetDeviceAtXRNode(XRNode.RightHand).TryGetFeatureValue(CommonUsages.secondaryButton, out bool ishide))
|
||
{
|
||
if (ishide)
|
||
{
|
||
sendCom(2, 0, 0);
|
||
}
|
||
}
|
||
|
||
//头盔变化
|
||
if (Application.platform == RuntimePlatform.Android)
|
||
{
|
||
if (InputDevices.GetDeviceAtXRNode(XRNode.Head).TryGetFeatureValue(CommonUsages.userPresence, out bool userPresence))
|
||
{
|
||
if (userPresence)
|
||
{
|
||
wearingState = 1;
|
||
}
|
||
else
|
||
{
|
||
wearingState = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//连接服务器
|
||
if (client != null)
|
||
{
|
||
if (!isConnecting)
|
||
{
|
||
if (DateTime.Now > connTime.AddSeconds(2))
|
||
{
|
||
connTime = DateTime.Now;
|
||
Debug.Log($"连接中。。。ip:{Config.TcpHost}");
|
||
client.Open(new Host(Config.TcpHost, Config.TcpPort));
|
||
Invoke("sendRegister", 1f);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (DateTime.Now > dateTime.AddSeconds(2))
|
||
{
|
||
dateTime = DateTime.Now;
|
||
//sendvrInfo(Config.SN, user, uint.Parse(PicoAPI._Instance.PicoPower()), 2, wearingState);
|
||
//sendvrInfo(Config.SN, user, 100, 1, 1);
|
||
}
|
||
|
||
if (DateTime.Now > posTime.AddSeconds(0.5f))
|
||
{
|
||
posTime = DateTime.Now;
|
||
if (cameraTran.position.y < (statHight * 0.7f)) //这个是自己判断自己的状态后加的 蹲着
|
||
{
|
||
myPositionChang = new Vector3(cameraTran.position.x, 3, cameraTran.position.z);
|
||
//cameraTran.position = new Vector3(cameraTran.position.x, 3, cameraTran.position.z);
|
||
}
|
||
else
|
||
{
|
||
distance = Vector3.Distance(lastPos, cameraTran.position);
|
||
//Debug.Log("最后的位置:" + lastPos + "||" + cameraTran.position+"||"+ distance);
|
||
if (distance <= 0.1f)
|
||
{
|
||
myPositionChang = new Vector3(cameraTran.position.x, 1, cameraTran.position.z);
|
||
//cameraTran.position = new Vector3(cameraTran.position.x, 1, cameraTran.position.z); //站立
|
||
}
|
||
else
|
||
{
|
||
myPositionChang = new Vector3(cameraTran.position.x, 2, cameraTran.position.z);
|
||
//cameraTran.position = new Vector3(cameraTran.position.x, 2, cameraTran.position.z); //行走
|
||
}
|
||
}
|
||
lastPos = cameraTran.position;
|
||
//Debug.Log("自己传的是什么状态:" + myPositionChang.y);
|
||
sendvrPos(Config.SN, user, Config.Group, myPositionChang, cameraTran.rotation);
|
||
}
|
||
|
||
if (DateTime.Now > allinfoTime.AddSeconds(50))
|
||
{
|
||
allinfoTime = DateTime.Now;
|
||
sendAskInfo();
|
||
//sendGoodAskInfo();
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
//Position GetPosition()
|
||
//{
|
||
// position.Pos = Vec3ToPos(nowObj.transform.position);
|
||
// position.Dir = Vec3ToDir(nowObj.transform.eulerAngles);
|
||
// position.State = GetMyState(nowObj.transform.position);
|
||
// return position;
|
||
//}
|
||
|
||
|
||
/// <summary>
|
||
/// 注册Good对象
|
||
/// </summary>
|
||
/// <param name="good">要注册的Good对象</param>
|
||
public void RegisterGood(Good good)
|
||
{
|
||
if (good == null) return;
|
||
|
||
string key = good.gameObject.name; // 使用物体名作为键
|
||
|
||
if (!goodsDictionary.ContainsKey(key))
|
||
{
|
||
goodsDictionary.Add(key, good);
|
||
}
|
||
else
|
||
{
|
||
// 已存在同名对象,可以选择替换或忽略
|
||
goodsDictionary[key] = good;
|
||
Debug.LogWarning($"已存在同名Good对象: {key}, 已替换为新对象");
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 注销Good对象
|
||
/// </summary>
|
||
/// <param name="good">要注销的Good对象</param>
|
||
public void UnregisterGood(Good good)
|
||
{
|
||
if (good == null) return;
|
||
|
||
string key = good.gameObject.name;
|
||
|
||
if (goodsDictionary.ContainsKey(key))
|
||
{
|
||
// 确保移除的是同一个对象
|
||
if (goodsDictionary[key] == good)
|
||
{
|
||
goodsDictionary.Remove(key);
|
||
}
|
||
}
|
||
}
|
||
|
||
#region 网络
|
||
void sendMessage<T>(uint type, T msg)
|
||
{
|
||
try
|
||
{
|
||
// 序列化消息
|
||
string json = JsonConvert.SerializeObject(msg);
|
||
Debug.Log($"发送的json: {json}");
|
||
byte[] msgBytes = NE.GetBytes(json);
|
||
|
||
// 计算总长度(消息类型 + 消息内容 + 结尾的0)
|
||
int totalLength = sizeof(uint) + msgBytes.Length + 1; // 类型长度 + 消息长度 + 1(结尾的0)
|
||
|
||
// 使用 MemoryStream 和 BinaryWriter 构建字节数组
|
||
using (var stream = new MemoryStream())
|
||
using (var writer = new BinaryWriter(stream))
|
||
{
|
||
writer.Write(totalLength); // 写入总长度
|
||
writer.Write(type); // 写入消息类型
|
||
writer.Write(msgBytes); // 写入消息内容
|
||
writer.Write((byte)0); // 写入结尾的0
|
||
|
||
// 发送数据
|
||
client.ToData(stream.ToArray());
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError("发送消息失败: " + ex.Message);
|
||
}
|
||
}
|
||
//
|
||
void open()
|
||
{
|
||
isConnecting = true;
|
||
}
|
||
void close()
|
||
{
|
||
isConnecting = false;
|
||
}
|
||
void error(Exception e)
|
||
{
|
||
Debug.LogError($"连接错误:{e.Message}");
|
||
}
|
||
void msgEvent(string name, byte[] bytes)
|
||
{
|
||
string msg = NE.GetString(bytes);
|
||
|
||
}
|
||
void msgData(byte[] bytes)
|
||
{
|
||
if (bytes == null || bytes.Length == 0)
|
||
{
|
||
Debug.LogError("无效数据包:空数据");
|
||
return;
|
||
}
|
||
//string hexResult = "";
|
||
//foreach (byte b in bytes)
|
||
//{
|
||
// hexResult += b.ToString("X2") + " ";
|
||
//}
|
||
//Debug.Log($"消息字节: {hexResult}");
|
||
|
||
#region Memory缓冲区
|
||
// 将新数据追加到缓冲区
|
||
_receiveMemory = CombineMemory(_receiveMemory, bytes.AsMemory());
|
||
|
||
try
|
||
{
|
||
while (_receiveMemory.Length >= 8)
|
||
{
|
||
var bufferSpan = _receiveMemory.Span;
|
||
int contentLength = BitConverter.ToInt32(bufferSpan.Slice(0, 4));//数据长度
|
||
int type = BitConverter.ToInt32(bufferSpan.Slice(4, 4));// 数据类型
|
||
if (type > 100)
|
||
{
|
||
// 找到第一个 0 字节的位置
|
||
int zeroIndex = _receiveMemory.Span.IndexOf((byte)0);
|
||
if (zeroIndex >= 0)
|
||
{
|
||
_receiveMemory = _receiveMemory.Slice(zeroIndex + 1); // 移除到 0 字节之后
|
||
Debug.LogError($"数据包类型错误: {type},移除到 0 字节之后");
|
||
}
|
||
else
|
||
{
|
||
_receiveMemory = Memory<byte>.Empty; // 如果没有 0 字节,清空缓冲区
|
||
Debug.LogError($"数据包类型错误: {type},没有 0 字节,清空缓冲区");
|
||
}
|
||
break;
|
||
}
|
||
int totalPacketLength = 4 + contentLength;
|
||
int msgLength = contentLength - 5;//(减4减1)
|
||
try
|
||
{
|
||
//检查是否收到完整的数据包
|
||
if (_receiveMemory.Length >= totalPacketLength)
|
||
{
|
||
// 验证结尾字节是否为0
|
||
if (bufferSpan[totalPacketLength - 1] != 0)
|
||
{
|
||
_receiveMemory = Memory<byte>.Empty;
|
||
Debug.LogError("清除缓冲区,数据包格式错误: 缺少结尾0字节");
|
||
break;
|
||
}
|
||
|
||
var msgMemory = _receiveMemory.Slice(8, msgLength);
|
||
string msg = Encoding.UTF8.GetString(msgMemory.Span);
|
||
Debug.Log($"收到的消息:{msg}");
|
||
if (_messageHandlers.TryGetValue(type, out var handler))
|
||
{
|
||
try
|
||
{
|
||
handler(msg);//业务处理
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"业务逻辑处理报错:{e.Message}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//Debug.LogError($"未知的消息类型: {type}");
|
||
}
|
||
//Debug.Log("从缓冲区移除已处理的数据");
|
||
_receiveMemory = _receiveMemory.Slice(totalPacketLength);
|
||
erorrCount = 0;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"数据不完整,类型:{type},预期长度: {totalPacketLength}, 实际长度: {_receiveMemory.Length}");
|
||
erorrCount++;
|
||
if (erorrCount >= 10)
|
||
{
|
||
erorrCount = 0;
|
||
_receiveMemory = Memory<byte>.Empty;
|
||
Debug.LogError("清除缓冲区,数据不完整超过10次");
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"清除缓冲区,处理数据包时出错: {e.Message}");
|
||
_receiveMemory = Memory<byte>.Empty;
|
||
}
|
||
}
|
||
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"清除缓冲区,消息处理异常: {e.Message}");
|
||
_receiveMemory = Memory<byte>.Empty;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载更新玩家位置
|
||
/// </summary>
|
||
void LoadPlayer(VRPos vrpos, ref Player player)
|
||
{
|
||
if (!string.Equals(vrpos.sn, Config.SN))
|
||
{
|
||
if (!otherPlayers.Find(vrpos.sn))
|
||
{
|
||
player = GameTools.LoadPrefab<Player>("Player", otherPlayers);
|
||
}
|
||
else
|
||
{
|
||
player = otherPlayers.Find(vrpos.sn).GetComponent<Player>();
|
||
}
|
||
player.isOtherPlayer = true;
|
||
player.transform.name = vrpos.sn;
|
||
player.sn = vrpos.sn;
|
||
if (player.user)
|
||
{
|
||
player.user.text = vrpos.user;
|
||
if (vrpos.human > 1)
|
||
{
|
||
player.human = 0;
|
||
}
|
||
else
|
||
{
|
||
player.human = vrpos.human;
|
||
}
|
||
|
||
}
|
||
player.group = vrpos.group;
|
||
player.x = vrpos.x;
|
||
player.y = vrpos.y;
|
||
player.z = vrpos.z;
|
||
player.q = vrpos.q;
|
||
player.w = vrpos.w;
|
||
player.e = vrpos.e;
|
||
player.r = vrpos.r;
|
||
player.LastTime = Time.time;
|
||
|
||
if (Config.Group == player.group) //同组
|
||
{
|
||
player.gameObject.SetActive(true);
|
||
}
|
||
else //不同组
|
||
{
|
||
db_myPosition.x = lastPos.x;
|
||
db_myPosition.y = 0;
|
||
db_myPosition.z = lastPos.z;
|
||
db_otherPosition.x = player.x/ Config.times;
|
||
db_otherPosition.y = 0;
|
||
db_otherPosition.z = player.z/ Config.times;
|
||
db_distance = Vector3.Distance(db_myPosition, db_otherPosition);
|
||
//Debug.Log("多少米:"+ db_distance);
|
||
if (db_distance < 5)
|
||
player.gameObject.SetActive(true);
|
||
else
|
||
player.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载更新物体位置
|
||
/// </summary>
|
||
void LoadGood(Good good, ObjPos gPos)
|
||
{
|
||
good.sn = gPos.sn;
|
||
good.user.text = gPos.user;
|
||
good.x = gPos.x;
|
||
good.y = gPos.y;
|
||
good.z = gPos.z;
|
||
good.q = gPos.q;
|
||
good.w = gPos.w;
|
||
good.e = gPos.e;
|
||
good.r = gPos.r;
|
||
good.isExistServer = true;
|
||
}
|
||
#endregion
|
||
|
||
#region 消息
|
||
|
||
/// <summary>
|
||
/// 发送时间轴进度
|
||
/// </summary>
|
||
public void sendTimeLineProgress(uint scene, int progress)
|
||
{
|
||
//timelineProgress.sn = Config.SN;
|
||
//timelineProgress.group = Config.Group;
|
||
//timelineProgress.scene = scene;
|
||
//timelineProgress.progress = progress;
|
||
//sendMessage(16, timelineProgress);
|
||
//Debug.Log($"发送时间轴消息: {timelineProgress.scene}+++++{timelineProgress.progress}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送vr设备信息
|
||
/// </summary>
|
||
void sendvrInfo(string sn, string name, uint power, uint status, uint wear)
|
||
{
|
||
vrinfo.sn = sn;
|
||
vrinfo.user = name;
|
||
vrinfo.human = human;
|
||
//vrinfo.power = power;
|
||
//vrinfo.status = status;
|
||
//vrinfo.wear = wear;
|
||
sendMessage(2, vrinfo);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送vr位置
|
||
/// </summary>
|
||
void sendvrPos(string sn, string name, uint group, Vector3 v3, Quaternion qua)
|
||
{
|
||
vrpos.sn = sn;
|
||
vrpos.user = name;
|
||
vrpos.human = human;
|
||
vrpos.group = group;
|
||
vrpos.x = (int)(v3.x * Config.times);
|
||
vrpos.y = (int)(v3.y * Config.times);
|
||
vrpos.z = (int)(v3.z * Config.times);
|
||
vrpos.q = (int)(qua.x * Config.times);
|
||
vrpos.w = (int)(qua.y * Config.times);
|
||
vrpos.e = (int)(qua.z * Config.times);
|
||
vrpos.r = (int)(qua.w * Config.times);
|
||
sendMessage(4, vrpos);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送物体位置
|
||
/// </summary>
|
||
public void sendGoodPos(string objname, Vector3 v3, Quaternion qua)
|
||
{
|
||
gPos.sn = Config.SN;
|
||
gPos.user = user;
|
||
gPos.name = objname;
|
||
gPos.group = Config.Group;
|
||
gPos.x = (int)(v3.x * Config.times);
|
||
gPos.y = (int)(v3.y * Config.times);
|
||
gPos.z = (int)(v3.z * Config.times);
|
||
gPos.q = (int)(qua.x * Config.times);
|
||
gPos.w = (int)(qua.y * Config.times);
|
||
gPos.e = (int)(qua.z * Config.times);
|
||
gPos.r = (int)(qua.w * Config.times);
|
||
sendMessage(8, gPos);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册
|
||
/// </summary>
|
||
void sendRegister()
|
||
{
|
||
register.type = 2;
|
||
register.user = "VR2";
|
||
register.sn = Config.SN;
|
||
sendMessage(1, register);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注销
|
||
/// </summary>
|
||
public void sendLogout()
|
||
{
|
||
Logout logout = new Logout();
|
||
logout.group = Config.Group;
|
||
logout.sn = Config.SN;
|
||
sendMessage(6, logout);
|
||
}
|
||
void Quit()
|
||
{
|
||
Application.Quit();
|
||
}
|
||
/// <summary>
|
||
/// 请求人物全量数据
|
||
/// </summary>
|
||
void sendAskInfo()
|
||
{
|
||
ask.type = 1;
|
||
sendMessage(5, ask);
|
||
}
|
||
/// <summary>
|
||
/// 请求物品全量数据
|
||
/// </summary>
|
||
void sendGoodAskInfo()
|
||
{
|
||
ask.type = 10;
|
||
sendMessage(9, ask);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送通知
|
||
/// </summary>
|
||
void sendCom(uint com, int value, float f)
|
||
{
|
||
inform.sn = Config.SN;
|
||
inform.user = user;
|
||
inform.group = Config.Group;
|
||
inform.com = com;
|
||
inform.value = value;
|
||
inform.f = f;
|
||
sendMessage(13, inform);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回给平板消息
|
||
/// </summary>
|
||
void sendBackInfo()
|
||
{
|
||
backInfo.sn = Config.SN;
|
||
backInfo.url = PicoAPI._Instance.GetCastUrl();
|
||
sendMessage(14, backInfo);
|
||
}
|
||
#endregion
|
||
|
||
#region 收到消息执行
|
||
private void HandleTimeLineProgress(string msg)
|
||
{
|
||
try
|
||
{
|
||
//TimelineProgress timelineProgress = JsonConvert.DeserializeObject<TimelineProgress>(msg);
|
||
//Debug.Log($"解析时间轴消息: {msg}");
|
||
//if (Config.Group == timelineProgress.group)
|
||
//{
|
||
// OnTimelineProgress.Invoke(timelineProgress.scene, timelineProgress.progress);
|
||
//}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"解析时间轴时遇到错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void HandleInform(string msg)
|
||
{
|
||
//try
|
||
//{
|
||
// Inform inform = JsonConvert.DeserializeObject<Inform>(msg);
|
||
// switch (inform.com)
|
||
// {
|
||
// case 1:
|
||
// cubeObj.SetActive(true);
|
||
// break;
|
||
// case 2:
|
||
// cubeObj.SetActive(false);
|
||
// break;
|
||
// case 3:
|
||
// if (Config.SN != inform.sn)
|
||
// {
|
||
// Player player = otherPlayers.Find(inform.sn).GetComponent<Player>();
|
||
// GlobalEventMgr.Dispatch(GameEvent.EventAnimalSync, inform.value, player.transform.position); //收到同组玩家创建动物
|
||
// }
|
||
// break;
|
||
// default:
|
||
// break;
|
||
// }
|
||
//}
|
||
//catch (Exception ex)
|
||
//{
|
||
// Debug.LogError($"解析玩家通知时遇到错误: {ex.Message}");
|
||
//}
|
||
}
|
||
private void HandleVRControl(string msg)
|
||
{
|
||
try
|
||
{
|
||
VRControl vrControl = JsonConvert.DeserializeObject<VRControl>(msg);
|
||
if (string.Equals(vrControl.sn, Config.SN))
|
||
{
|
||
switch (vrControl.com)
|
||
{
|
||
case 1:
|
||
PicoAPI._Instance.ShutDown();
|
||
break;
|
||
case 2:
|
||
PicoAPI._Instance.Reboot();
|
||
break;
|
||
case 3:
|
||
PicoAPI._Instance.SetVolumeNum(vrControl.volume);
|
||
break;
|
||
case 4:
|
||
float ipd = (float)vrControl.volume / 100;
|
||
PicoAPI._Instance.SetIpd(ipd);
|
||
break;
|
||
case 5:
|
||
sendBackInfo();
|
||
break;
|
||
case 6:
|
||
switch (vrControl.volume)
|
||
{
|
||
case 0://启动
|
||
|
||
break;
|
||
case 1://暂停
|
||
|
||
break;
|
||
case 2://关闭
|
||
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"解析控制设备时遇到错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private HashSet<string> _previousSNs = new HashSet<string>();
|
||
void HandleAllIfo(string msg)
|
||
{
|
||
try
|
||
{
|
||
var allIfo = JsonConvert.DeserializeObject<AllIfo>(msg);
|
||
var currentSNs = new HashSet<string>(); // 当前帧的 SN 集合
|
||
foreach (var vrGroupInfo in allIfo.all)
|
||
{
|
||
foreach (var vrpos in vrGroupInfo.vrs)
|
||
{
|
||
// 记录所有 vrpos.sn
|
||
currentSNs.Add(vrpos.sn);
|
||
|
||
Player p;
|
||
if (string.Equals(vrpos.sn, Config.SN))//如果是自己,则获得组名,获得体验者昵称
|
||
{
|
||
p = cameraTran.Find("Player").GetComponent<Player>();
|
||
p.group = Config.Group = vrpos.group;
|
||
p.user.text = user = vrpos.user;
|
||
p.human = human = vrpos.human;
|
||
}
|
||
else
|
||
{
|
||
p = null;
|
||
}
|
||
LoadPlayer(vrpos, ref p);
|
||
}
|
||
}
|
||
|
||
// 对比差异并隐藏消失的 SN
|
||
var missingSNs = _previousSNs.Except(currentSNs);
|
||
foreach (var sn in missingSNs)
|
||
{
|
||
otherPlayers.Find(sn).gameObject.SetActive(false);
|
||
}
|
||
|
||
// 更新缓存
|
||
_previousSNs = currentSNs;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"解析所有玩家信息时遇到错误: {ex.Message}");
|
||
}
|
||
|
||
}
|
||
void HandleGood(string msg)
|
||
{
|
||
try
|
||
{
|
||
var gpos = JsonConvert.DeserializeObject<ObjPos>(msg);
|
||
if (gpos.group == Config.Group && goodsDictionary.TryGetValue(gpos.name, out Good good))
|
||
{
|
||
LoadGood(good, gpos);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"解析物体位置时遇到错误: {ex.Message}");
|
||
}
|
||
}
|
||
void HandleVRPosition(string msg)
|
||
{
|
||
try
|
||
{
|
||
var pos = JsonConvert.DeserializeObject<VRPos>(msg);
|
||
Player player = null;
|
||
LoadPlayer(pos, ref player);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"解析玩家位置时遇到错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
void HandleLogout(string msg)
|
||
{
|
||
try
|
||
{
|
||
logout = JsonConvert.DeserializeObject<Logout>(msg);
|
||
if (otherPlayers.Find(logout.sn))
|
||
otherPlayers.Find(logout.sn).gameObject.SetActive(false);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"解析玩家注销时遇到错误: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
int lastSceneIndex;//上次场景索引
|
||
IEnumerator loadSceneAsync(int index)
|
||
{
|
||
if (lastSceneIndex > 0)
|
||
{
|
||
SceneManager.UnloadSceneAsync(lastSceneIndex);
|
||
}
|
||
|
||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(index, LoadSceneMode.Additive);
|
||
while (!asyncLoad.isDone)
|
||
{
|
||
yield return null;
|
||
}
|
||
lastSceneIndex = index;
|
||
}
|
||
/// <summary>
|
||
/// 卸载旧场景再加载新场景
|
||
/// </summary>
|
||
public void MyLoadSceneAsync(int index)
|
||
{
|
||
StartCoroutine(loadSceneAsync(index));
|
||
}
|
||
|
||
// 合并两个 Memory<byte>(模拟 List<byte>.AddRange)
|
||
private Memory<byte> CombineMemory(Memory<byte> a, Memory<byte> b)
|
||
{
|
||
if (a.IsEmpty) return b;
|
||
if (b.IsEmpty) return a;
|
||
|
||
var newBuffer = new byte[a.Length + b.Length];
|
||
a.CopyTo(newBuffer.AsMemory(0, a.Length));
|
||
b.CopyTo(newBuffer.AsMemory(a.Length, b.Length));
|
||
return newBuffer;
|
||
}
|
||
} |