more simplification and documentation, added networkserializedobject with fixed serialization rate and ez callbacks

handTracking
Anton Franzluebbers 2022-01-06 20:04:05 -05:00
parent 440b8e97ca
commit e8b500f478
15 changed files with 98 additions and 93 deletions

View File

@ -2,6 +2,7 @@ using System;
using Dissonance; using Dissonance;
using Dissonance.Networking; using Dissonance.Networking;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
namespace VelNetUnity namespace VelNetUnity
@ -25,7 +26,7 @@ namespace VelNetUnity
private ConnectionStatus _status = ConnectionStatus.Disconnected; private ConnectionStatus _status = ConnectionStatus.Disconnected;
private CodecSettings initSettings; private CodecSettings initSettings;
public string dissonanceId; public string dissonanceId;
public DissonanceComms comms; [FormerlySerializedAs("comms")] public DissonanceComms dissonanceComms;
private NetworkManager manager; private NetworkManager manager;
/// <summary> /// <summary>
@ -38,7 +39,7 @@ namespace VelNetUnity
private void Start() private void Start()
{ {
_status = ConnectionStatus.Connected; _status = ConnectionStatus.Connected;
comms = GetComponent<DissonanceComms>(); dissonanceComms = GetComponent<DissonanceComms>();
manager = NetworkManager.instance; manager = NetworkManager.instance;
} }
@ -46,7 +47,7 @@ namespace VelNetUnity
{ {
dissonanceId = playerName; dissonanceId = playerName;
initSettings = codecSettings; initSettings = codecSettings;
comms.ResetMicrophoneCapture(); dissonanceComms.ResetMicrophoneCapture();
} }
public void VoiceReceived(string sender, byte[] data) public void VoiceReceived(string sender, byte[] data)
@ -88,7 +89,8 @@ namespace VelNetUnity
PlayerName = id PlayerName = id
}; };
PlayerExitedRoom?.Invoke(re); PlayerExitedRoom?.Invoke(re);
PlayerLeft?.Invoke(id); // only send this event for non-local players
if (id != dissonanceId) PlayerLeft?.Invoke(id);
} }
public void SetPlayerStartedSpeaking(string id) public void SetPlayerStartedSpeaking(string id)

View File

@ -8,7 +8,9 @@ using UnityEngine;
namespace VelNetUnity namespace VelNetUnity
{ {
[RequireComponent(typeof(VelCommsNetwork))] /// <summary>
/// This should be added to your player object
/// </summary>
[AddComponentMenu("VelNetUnity/Dissonance/VelNet Dissonance Player")] [AddComponentMenu("VelNetUnity/Dissonance/VelNet Dissonance Player")]
public class VelNetDissonancePlayer : NetworkObject, IDissonancePlayer public class VelNetDissonancePlayer : NetworkObject, IDissonancePlayer
{ {
@ -16,6 +18,7 @@ namespace VelNetUnity
private bool isSpeaking; private bool isSpeaking;
private uint lastAudioId; private uint lastAudioId;
[Header("VelNet Dissonance Player Properties")]
public string dissonanceID = ""; public string dissonanceID = "";
//required by dissonance for spatial audio //required by dissonance for spatial audio
@ -28,7 +31,7 @@ namespace VelNetUnity
public Vector3 targetPosition; public Vector3 targetPosition;
public Quaternion targetRotation; public Quaternion targetRotation;
public List<VelNetDissonancePlayer> allPlayers = new List<VelNetDissonancePlayer>(); private static readonly List<VelNetDissonancePlayer> allPlayers = new List<VelNetDissonancePlayer>();
public List<int> closePlayers = new List<int>(); public List<int> closePlayers = new List<int>();
[Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")] [Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")]
@ -38,7 +41,13 @@ namespace VelNetUnity
private void Start() private void Start()
{ {
comms = FindObjectOfType<VelCommsNetwork>(); comms = FindObjectOfType<VelCommsNetwork>();
if (comms == null)
{
Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this);
return;
}
// add ourselves to the global list of all players in the scene
if (!allPlayers.Contains(this)) if (!allPlayers.Contains(this))
{ {
allPlayers.Add(this); allPlayers.Add(this);
@ -80,7 +89,7 @@ namespace VelNetUnity
dissonanceID = Encoding.UTF8.GetString(message); dissonanceID = Encoding.UTF8.GetString(message);
// tell the comms network that this player joined the channel // tell the comms network that this player joined the channel
comms.SetPlayerJoined(dissonanceID); // tell dissonance comms.SetPlayerJoined(dissonanceID); // tell dissonance
comms.comms.TrackPlayerPosition(this); // tell dissonance to track the remote player comms.dissonanceComms.TrackPlayerPosition(this); // tell dissonance to track the remote player
} }
break; break;
@ -125,7 +134,7 @@ namespace VelNetUnity
dissonanceID = id; dissonanceID = id;
byte[] b = Encoding.UTF8.GetBytes(dissonanceID); byte[] b = Encoding.UTF8.GetBytes(dissonanceID);
owner.SendMessage(this, "d", b); owner.SendMessage(this, "d", b);
comms.comms.TrackPlayerPosition(this); comms.dissonanceComms.TrackPlayerPosition(this);
} }
private void VoiceInitialized(string id) private void VoiceInitialized(string id)
@ -179,7 +188,7 @@ namespace VelNetUnity
//handle dissonance comms //handle dissonance comms
//if we're not speaking, and the comms say we are, send a speaking event, which will be received on other network players and sent to their comms accordingly //if we're not speaking, and the comms say we are, send a speaking event, which will be received on other network players and sent to their comms accordingly
if (comms.comms.FindPlayer(dissonanceID)?.IsSpeaking != isSpeaking) //unfortunately, there does not seem to be an event for this if (comms.dissonanceComms.FindPlayer(dissonanceID)?.IsSpeaking != isSpeaking) //unfortunately, there does not seem to be an event for this
{ {
isSpeaking = !isSpeaking; isSpeaking = !isSpeaking;
byte[] toSend = { isSpeaking ? (byte)1 : (byte)0 }; byte[] toSend = { isSpeaking ? (byte)1 : (byte)0 };

View File

@ -14,7 +14,6 @@ GameObject:
- component: {fileID: 5845716565458182149} - component: {fileID: 5845716565458182149}
- component: {fileID: 5713671764962751473} - component: {fileID: 5713671764962751473}
- component: {fileID: -4404668399269848200} - component: {fileID: -4404668399269848200}
- component: {fileID: 7065383111165629622}
- component: {fileID: 1181612843795795320} - component: {fileID: 1181612843795795320}
m_Layer: 0 m_Layer: 0
m_Name: PlayerPrefab m_Name: PlayerPrefab
@ -134,20 +133,6 @@ MonoBehaviour:
isSceneObject: 0 isSceneObject: 0
targetPosition: {x: 0, y: 0, z: 0} targetPosition: {x: 0, y: 0, z: 0}
targetRotation: {x: 0, y: 0, z: 0, w: 0} targetRotation: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &7065383111165629622
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6139051692386484099}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5d2009d8e264649749c0315d48765749, type: 3}
m_Name:
m_EditorClassIdentifier:
dissonanceId:
comms: {fileID: 0}
--- !u!114 &1181612843795795320 --- !u!114 &1181612843795795320
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -7,7 +7,9 @@ namespace VelNetUnity
/// </summary> /// </summary>
public abstract class NetworkObject : MonoBehaviour public abstract class NetworkObject : MonoBehaviour
{ {
[Header("NetworkObject properties")]
public NetworkPlayer owner; public NetworkPlayer owner;
public bool IsMine => owner !=null && owner.isLocal;
/// <summary> /// <summary>
/// This is forged from the combination of the creator's id (-1 in the case of a scene object) and an object id, so it's always unique for a room /// This is forged from the combination of the creator's id (-1 in the case of a scene object) and an object id, so it's always unique for a room
/// </summary> /// </summary>

View File

@ -0,0 +1,39 @@
using System;
using System.Timers;
using UnityEngine;
using UnityEngine.Serialization;
namespace VelNetUnity
{
public abstract class NetworkSerializedObject : NetworkObject
{
[FormerlySerializedAs("updateRateHz")] [Tooltip("Send rate of this object")] public float serializationRateHz = 30;
private void Start()
{
Timer timer = new Timer();
timer.Interval = serializationRateHz;
timer.Elapsed += SendMessageUpdate;
}
private void SendMessageUpdate(object sender, ElapsedEventArgs e)
{
if (owner != null && owner.isLocal)
{
owner.SendMessage(this, "s", SendState());
}
}
protected abstract byte[] SendState();
public override void HandleMessage(string identifier, byte[] message)
{
if (identifier == "s")
{
ReceiveState(message);
}
}
protected abstract void ReceiveState(byte[] message);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5af3d130144d49bf8dcd43824f5d618d
timeCreated: 1641514434

View File

@ -9,13 +9,12 @@ namespace VelNetUnity
/// A simple class that will sync the position and rotation of a network object /// A simple class that will sync the position and rotation of a network object
/// </summary> /// </summary>
[AddComponentMenu("VelNetUnity/VelNet Sync Transform")] [AddComponentMenu("VelNetUnity/VelNet Sync Transform")]
public class SyncTransform : NetworkObject public class SyncTransform : NetworkSerializedObject
{ {
public Vector3 targetPosition; public Vector3 targetPosition;
public Quaternion targetRotation; public Quaternion targetRotation;
protected override byte[] SendState()
public byte[] GetSyncMessage()
{ {
using MemoryStream mem = new MemoryStream(); using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem); using BinaryWriter writer = new BinaryWriter(mem);
@ -26,50 +25,20 @@ namespace VelNetUnity
return mem.ToArray(); return mem.ToArray();
} }
public override void HandleMessage(string identifier, byte[] message) protected override void ReceiveState(byte[] message)
{
switch (identifier)
{
case "s":
{ {
using MemoryStream mem = new MemoryStream(message); using MemoryStream mem = new MemoryStream(message);
using BinaryReader reader = new BinaryReader(mem); using BinaryReader reader = new BinaryReader(mem);
targetPosition = reader.ReadVector3(); targetPosition = reader.ReadVector3();
targetRotation = reader.ReadQuaternion(); targetRotation = reader.ReadQuaternion();
break;
}
}
} }
// Start is called before the first frame update
private void Start()
{
StartCoroutine(SyncBehavior());
}
private IEnumerator SyncBehavior()
{
while (true)
{
if (owner != null && owner.isLocal)
{
owner.SendMessage(this, "s", GetSyncMessage());
}
yield return new WaitForSeconds(.1f);
}
}
// Update is called once per frame
private void Update() private void Update()
{ {
if (owner != null && !owner.isLocal) if (owner == null || owner.isLocal) return;
{
transform.position = Vector3.Lerp(transform.position, targetPosition, .1f); transform.position = Vector3.Lerp(transform.position, targetPosition, .1f);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, .1f); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, .1f);
} }
} }
}
} }

View File

@ -2,6 +2,7 @@ using System;
using Dissonance; using Dissonance;
using Dissonance.Networking; using Dissonance.Networking;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
namespace VelNetUnity namespace VelNetUnity
@ -25,7 +26,7 @@ namespace VelNetUnity
private ConnectionStatus _status = ConnectionStatus.Disconnected; private ConnectionStatus _status = ConnectionStatus.Disconnected;
private CodecSettings initSettings; private CodecSettings initSettings;
public string dissonanceId; public string dissonanceId;
public DissonanceComms comms; [FormerlySerializedAs("comms")] public DissonanceComms dissonanceComms;
private NetworkManager manager; private NetworkManager manager;
/// <summary> /// <summary>
@ -38,7 +39,7 @@ namespace VelNetUnity
private void Start() private void Start()
{ {
_status = ConnectionStatus.Connected; _status = ConnectionStatus.Connected;
comms = GetComponent<DissonanceComms>(); dissonanceComms = GetComponent<DissonanceComms>();
manager = NetworkManager.instance; manager = NetworkManager.instance;
} }
@ -46,7 +47,7 @@ namespace VelNetUnity
{ {
dissonanceId = playerName; dissonanceId = playerName;
initSettings = codecSettings; initSettings = codecSettings;
comms.ResetMicrophoneCapture(); dissonanceComms.ResetMicrophoneCapture();
} }
public void VoiceReceived(string sender, byte[] data) public void VoiceReceived(string sender, byte[] data)
@ -88,7 +89,8 @@ namespace VelNetUnity
PlayerName = id PlayerName = id
}; };
PlayerExitedRoom?.Invoke(re); PlayerExitedRoom?.Invoke(re);
PlayerLeft?.Invoke(id); // only send this event for non-local players
if (id != dissonanceId) PlayerLeft?.Invoke(id);
} }
public void SetPlayerStartedSpeaking(string id) public void SetPlayerStartedSpeaking(string id)

View File

@ -8,7 +8,9 @@ using UnityEngine;
namespace VelNetUnity namespace VelNetUnity
{ {
[RequireComponent(typeof(VelCommsNetwork))] /// <summary>
/// This should be added to your player object
/// </summary>
[AddComponentMenu("VelNetUnity/Dissonance/VelNet Dissonance Player")] [AddComponentMenu("VelNetUnity/Dissonance/VelNet Dissonance Player")]
public class VelNetDissonancePlayer : NetworkObject, IDissonancePlayer public class VelNetDissonancePlayer : NetworkObject, IDissonancePlayer
{ {
@ -16,6 +18,7 @@ namespace VelNetUnity
private bool isSpeaking; private bool isSpeaking;
private uint lastAudioId; private uint lastAudioId;
[Header("VelNet Dissonance Player Properties")]
public string dissonanceID = ""; public string dissonanceID = "";
//required by dissonance for spatial audio //required by dissonance for spatial audio
@ -28,7 +31,7 @@ namespace VelNetUnity
public Vector3 targetPosition; public Vector3 targetPosition;
public Quaternion targetRotation; public Quaternion targetRotation;
public List<VelNetDissonancePlayer> allPlayers = new List<VelNetDissonancePlayer>(); private static readonly List<VelNetDissonancePlayer> allPlayers = new List<VelNetDissonancePlayer>();
public List<int> closePlayers = new List<int>(); public List<int> closePlayers = new List<int>();
[Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")] [Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")]
@ -38,7 +41,13 @@ namespace VelNetUnity
private void Start() private void Start()
{ {
comms = FindObjectOfType<VelCommsNetwork>(); comms = FindObjectOfType<VelCommsNetwork>();
if (comms == null)
{
Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this);
return;
}
// add ourselves to the global list of all players in the scene
if (!allPlayers.Contains(this)) if (!allPlayers.Contains(this))
{ {
allPlayers.Add(this); allPlayers.Add(this);
@ -80,7 +89,7 @@ namespace VelNetUnity
dissonanceID = Encoding.UTF8.GetString(message); dissonanceID = Encoding.UTF8.GetString(message);
// tell the comms network that this player joined the channel // tell the comms network that this player joined the channel
comms.SetPlayerJoined(dissonanceID); // tell dissonance comms.SetPlayerJoined(dissonanceID); // tell dissonance
comms.comms.TrackPlayerPosition(this); // tell dissonance to track the remote player comms.dissonanceComms.TrackPlayerPosition(this); // tell dissonance to track the remote player
} }
break; break;
@ -125,7 +134,7 @@ namespace VelNetUnity
dissonanceID = id; dissonanceID = id;
byte[] b = Encoding.UTF8.GetBytes(dissonanceID); byte[] b = Encoding.UTF8.GetBytes(dissonanceID);
owner.SendMessage(this, "d", b); owner.SendMessage(this, "d", b);
comms.comms.TrackPlayerPosition(this); comms.dissonanceComms.TrackPlayerPosition(this);
} }
private void VoiceInitialized(string id) private void VoiceInitialized(string id)
@ -179,7 +188,7 @@ namespace VelNetUnity
//handle dissonance comms //handle dissonance comms
//if we're not speaking, and the comms say we are, send a speaking event, which will be received on other network players and sent to their comms accordingly //if we're not speaking, and the comms say we are, send a speaking event, which will be received on other network players and sent to their comms accordingly
if (comms.comms.FindPlayer(dissonanceID)?.IsSpeaking != isSpeaking) //unfortunately, there does not seem to be an event for this if (comms.dissonanceComms.FindPlayer(dissonanceID)?.IsSpeaking != isSpeaking) //unfortunately, there does not seem to be an event for this
{ {
isSpeaking = !isSpeaking; isSpeaking = !isSpeaking;
byte[] toSend = { isSpeaking ? (byte)1 : (byte)0 }; byte[] toSend = { isSpeaking ? (byte)1 : (byte)0 };

View File

@ -14,7 +14,6 @@ GameObject:
- component: {fileID: 5845716565458182149} - component: {fileID: 5845716565458182149}
- component: {fileID: 5713671764962751473} - component: {fileID: 5713671764962751473}
- component: {fileID: -4404668399269848200} - component: {fileID: -4404668399269848200}
- component: {fileID: 7065383111165629622}
- component: {fileID: 1181612843795795320} - component: {fileID: 1181612843795795320}
m_Layer: 0 m_Layer: 0
m_Name: PlayerPrefab m_Name: PlayerPrefab
@ -134,20 +133,6 @@ MonoBehaviour:
isSceneObject: 0 isSceneObject: 0
targetPosition: {x: 0, y: 0, z: 0} targetPosition: {x: 0, y: 0, z: 0}
targetRotation: {x: 0, y: 0, z: 0, w: 0} targetRotation: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &7065383111165629622
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6139051692386484099}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5d2009d8e264649749c0315d48765749, type: 3}
m_Name:
m_EditorClassIdentifier:
dissonanceId:
comms: {fileID: 0}
--- !u!114 &1181612843795795320 --- !u!114 &1181612843795795320
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -1,7 +1,7 @@
{ {
"name": "edu.uga.engr.vel.velnetunity", "name": "edu.uga.engr.vel.velnetunity",
"displayName": "VelNetUnity", "displayName": "VelNetUnity",
"version": "1.0.1", "version": "1.0.2",
"unity": "2019.1", "unity": "2019.1",
"description": "A custom networking library for Unity.", "description": "A custom networking library for Unity.",
"keywords": [ "keywords": [
@ -17,7 +17,7 @@
{ {
"displayName": "Dissonance Integration", "displayName": "Dissonance Integration",
"description": "Includes support for Dissonance Voice, available separately from the Unity Asset Store.", "description": "Includes support for Dissonance Voice, available separately from the Unity Asset Store.",
"path": "Samples~/Dissonance Integration" "path": "Samples~/DissonanceIntegration"
}, },
{ {
"displayName": "Example", "displayName": "Example",