Files
2026-02-21 16:45:37 +08:00

162 lines
4.7 KiB
C#

using System;
using Oculus.Platform.Models;
using UnityEngine;
namespace Oculus.Platform.Samples.VrVoiceChat
{
public class P2PManager
{
private static readonly float UPDATE_DELAY = 0.1f;
private ulong m_remoteID;
private PeerConnectionState m_state;
private float m_timeForNextUpdate;
private static readonly byte PACKET_SIZE = 29;
private static readonly byte PACKET_FORMAT;
private readonly byte[] sendTransformBuffer = new byte[PACKET_SIZE];
private readonly byte[] receiveTransformBuffer = new byte[PACKET_SIZE];
private Vector3 receivedPosition;
private Vector3 receivedPositionPrior;
private Quaternion receivedRotation;
private Quaternion receivedRotationPrior;
private float receivedTime;
public bool Connected
{
get
{
return m_state == PeerConnectionState.Connected;
}
}
public bool ShouldSendHeadUpdate
{
get
{
return Time.time >= m_timeForNextUpdate && m_state == PeerConnectionState.Connected;
}
}
public P2PManager(Transform initialHeadTransform)
{
receivedPositionPrior = (receivedPosition = initialHeadTransform.localPosition);
receivedRotationPrior = (receivedRotation = initialHeadTransform.localRotation);
Net.SetPeerConnectRequestCallback(PeerConnectRequestCallback);
Net.SetConnectionStateChangedCallback(ConnectionStateChangedCallback);
}
public void ConnectTo(ulong userID)
{
m_remoteID = userID;
if (PlatformManager.MyID < userID)
{
Net.Connect(userID);
}
}
public void Disconnect()
{
if (m_remoteID != 0)
{
Net.Close(m_remoteID);
m_remoteID = 0uL;
m_state = PeerConnectionState.Unknown;
}
}
private void PeerConnectRequestCallback(Message<Oculus.Platform.Models.NetworkingPeer> msg)
{
Debug.LogFormat("Connection request from {0}, authorized is {1}", msg.Data.ID, m_remoteID);
if (msg.Data.ID == m_remoteID)
{
Net.Accept(msg.Data.ID);
}
}
private void ConnectionStateChangedCallback(Message<Oculus.Platform.Models.NetworkingPeer> msg)
{
Debug.LogFormat("Connection state to {0} changed to {1}", msg.Data.ID, msg.Data.State);
if (msg.Data.ID == m_remoteID)
{
m_state = msg.Data.State;
if (m_state == PeerConnectionState.Timeout && PlatformManager.MyID < m_remoteID)
{
Net.Connect(m_remoteID);
}
}
PlatformManager.SetBackgroundColorForState();
}
public void SendHeadTransform(Transform headTransform)
{
m_timeForNextUpdate = Time.time + UPDATE_DELAY;
sendTransformBuffer[0] = PACKET_FORMAT;
int offset = 1;
PackFloat(headTransform.localPosition.x, sendTransformBuffer, ref offset);
PackFloat(headTransform.localPosition.y, sendTransformBuffer, ref offset);
PackFloat(headTransform.localPosition.z, sendTransformBuffer, ref offset);
PackFloat(headTransform.localRotation.x, sendTransformBuffer, ref offset);
PackFloat(headTransform.localRotation.y, sendTransformBuffer, ref offset);
PackFloat(headTransform.localRotation.z, sendTransformBuffer, ref offset);
PackFloat(headTransform.localRotation.w, sendTransformBuffer, ref offset);
Net.SendPacket(m_remoteID, sendTransformBuffer, SendPolicy.Unreliable);
}
private void PackFloat(float f, byte[] buf, ref int offset)
{
Buffer.BlockCopy(BitConverter.GetBytes(f), 0, buf, offset, 4);
offset += 4;
}
public void GetRemoteHeadTransform(Transform headTransform)
{
bool flag = false;
Packet packet;
while ((packet = Net.ReadPacket()) != null)
{
if (packet.Size != PACKET_SIZE)
{
Debug.Log("Invalid packet size: " + packet.Size);
continue;
}
packet.ReadBytes(receiveTransformBuffer);
if (receiveTransformBuffer[0] != PACKET_FORMAT)
{
Debug.Log("Invalid packet type: " + packet.Size);
}
else
{
flag = true;
}
}
if (flag)
{
receivedPositionPrior = receivedPosition;
receivedPosition.x = BitConverter.ToSingle(receiveTransformBuffer, 1);
receivedPosition.y = BitConverter.ToSingle(receiveTransformBuffer, 5);
receivedPosition.z = BitConverter.ToSingle(receiveTransformBuffer, 9);
receivedRotationPrior = receivedRotation;
receivedRotation.x = BitConverter.ToSingle(receiveTransformBuffer, 13);
receivedRotation.y = BitConverter.ToSingle(receiveTransformBuffer, 17) * -1f;
receivedRotation.z = BitConverter.ToSingle(receiveTransformBuffer, 21);
receivedRotation.w = BitConverter.ToSingle(receiveTransformBuffer, 25) * -1f;
receivedTime = Time.time;
}
float t = Math.Min(Time.time - receivedTime, UPDATE_DELAY) / UPDATE_DELAY;
headTransform.localPosition = Vector3.Lerp(receivedPositionPrior, receivedPosition, t);
headTransform.localRotation = Quaternion.Slerp(receivedRotationPrior, receivedRotation, t);
}
}
}