diff --git a/Runtime/NetworkObject.cs b/Runtime/NetworkObject.cs index 8742189..ce0520a 100644 --- a/Runtime/NetworkObject.cs +++ b/Runtime/NetworkObject.cs @@ -7,7 +7,9 @@ namespace VelNetUnity /// public abstract class NetworkObject : MonoBehaviour { + [Header("NetworkObject properties")] public NetworkPlayer owner; + public bool IsMine => owner !=null && owner.isLocal; /// /// 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 /// diff --git a/Runtime/NetworkSerializedObject.cs b/Runtime/NetworkSerializedObject.cs new file mode 100644 index 0000000..18ac263 --- /dev/null +++ b/Runtime/NetworkSerializedObject.cs @@ -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); + } +} \ No newline at end of file diff --git a/Runtime/NetworkSerializedObject.cs.meta b/Runtime/NetworkSerializedObject.cs.meta new file mode 100644 index 0000000..eff71d8 --- /dev/null +++ b/Runtime/NetworkSerializedObject.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5af3d130144d49bf8dcd43824f5d618d +timeCreated: 1641514434 \ No newline at end of file diff --git a/Runtime/Util/SyncTransform.cs b/Runtime/Util/SyncTransform.cs index fae5396..fe8cbc4 100644 --- a/Runtime/Util/SyncTransform.cs +++ b/Runtime/Util/SyncTransform.cs @@ -9,13 +9,12 @@ namespace VelNetUnity /// A simple class that will sync the position and rotation of a network object /// [AddComponentMenu("VelNetUnity/VelNet Sync Transform")] - public class SyncTransform : NetworkObject + public class SyncTransform : NetworkSerializedObject { public Vector3 targetPosition; public Quaternion targetRotation; - - public byte[] GetSyncMessage() + protected override byte[] SendState() { using MemoryStream mem = new MemoryStream(); using BinaryWriter writer = new BinaryWriter(mem); @@ -26,50 +25,20 @@ namespace VelNetUnity 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 BinaryReader reader = new BinaryReader(mem); + using MemoryStream mem = new MemoryStream(message); + using BinaryReader reader = new BinaryReader(mem); - targetPosition = reader.ReadVector3(); - targetRotation = reader.ReadQuaternion(); - - break; - } - } + targetPosition = reader.ReadVector3(); + targetRotation = reader.ReadQuaternion(); } - // 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() { - if (owner != null && !owner.isLocal) - { - transform.position = Vector3.Lerp(transform.position, targetPosition, .1f); - transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, .1f); - } + if (owner == null || owner.isLocal) return; + transform.position = Vector3.Lerp(transform.position, targetPosition, .1f); + transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, .1f); } } } \ No newline at end of file diff --git a/Samples~/Dissonance Integration/VelAudioMixer.mixer b/Samples~/DissonanceIntegration/VelAudioMixer.mixer similarity index 100% rename from Samples~/Dissonance Integration/VelAudioMixer.mixer rename to Samples~/DissonanceIntegration/VelAudioMixer.mixer diff --git a/Samples~/Dissonance Integration/VelAudioMixer.mixer.meta b/Samples~/DissonanceIntegration/VelAudioMixer.mixer.meta similarity index 100% rename from Samples~/Dissonance Integration/VelAudioMixer.mixer.meta rename to Samples~/DissonanceIntegration/VelAudioMixer.mixer.meta diff --git a/Samples~/Dissonance Integration/VelCommsNetwork.cs b/Samples~/DissonanceIntegration/VelCommsNetwork.cs similarity index 89% rename from Samples~/Dissonance Integration/VelCommsNetwork.cs rename to Samples~/DissonanceIntegration/VelCommsNetwork.cs index e5af2f8..b1defa8 100644 --- a/Samples~/Dissonance Integration/VelCommsNetwork.cs +++ b/Samples~/DissonanceIntegration/VelCommsNetwork.cs @@ -2,6 +2,7 @@ using System; using Dissonance; using Dissonance.Networking; using UnityEngine; +using UnityEngine.Serialization; namespace VelNetUnity @@ -25,7 +26,7 @@ namespace VelNetUnity private ConnectionStatus _status = ConnectionStatus.Disconnected; private CodecSettings initSettings; public string dissonanceId; - public DissonanceComms comms; + [FormerlySerializedAs("comms")] public DissonanceComms dissonanceComms; private NetworkManager manager; /// @@ -33,12 +34,12 @@ namespace VelNetUnity /// public Action> VoiceQueued; - + // Start is called before the first frame update private void Start() { _status = ConnectionStatus.Connected; - comms = GetComponent(); + dissonanceComms = GetComponent(); manager = NetworkManager.instance; } @@ -46,7 +47,7 @@ namespace VelNetUnity { dissonanceId = playerName; initSettings = codecSettings; - comms.ResetMicrophoneCapture(); + dissonanceComms.ResetMicrophoneCapture(); } public void VoiceReceived(string sender, byte[] data) @@ -88,7 +89,8 @@ namespace VelNetUnity PlayerName = id }; 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) diff --git a/Samples~/Dissonance Integration/VelCommsNetwork.cs.meta b/Samples~/DissonanceIntegration/VelCommsNetwork.cs.meta similarity index 100% rename from Samples~/Dissonance Integration/VelCommsNetwork.cs.meta rename to Samples~/DissonanceIntegration/VelCommsNetwork.cs.meta diff --git a/Samples~/Dissonance Integration/VelNetDissonancePlayer.cs b/Samples~/DissonanceIntegration/VelNetDissonancePlayer.cs similarity index 86% rename from Samples~/Dissonance Integration/VelNetDissonancePlayer.cs rename to Samples~/DissonanceIntegration/VelNetDissonancePlayer.cs index 9caf58a..9bf72c0 100644 --- a/Samples~/Dissonance Integration/VelNetDissonancePlayer.cs +++ b/Samples~/DissonanceIntegration/VelNetDissonancePlayer.cs @@ -8,7 +8,9 @@ using UnityEngine; namespace VelNetUnity { - [RequireComponent(typeof(VelCommsNetwork))] + /// + /// This should be added to your player object + /// [AddComponentMenu("VelNetUnity/Dissonance/VelNet Dissonance Player")] public class VelNetDissonancePlayer : NetworkObject, IDissonancePlayer { @@ -16,6 +18,7 @@ namespace VelNetUnity private bool isSpeaking; private uint lastAudioId; + [Header("VelNet Dissonance Player Properties")] public string dissonanceID = ""; //required by dissonance for spatial audio @@ -28,7 +31,7 @@ namespace VelNetUnity public Vector3 targetPosition; public Quaternion targetRotation; - public List allPlayers = new List(); + private static readonly List allPlayers = new List(); public List closePlayers = new List(); [Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")] @@ -38,7 +41,13 @@ namespace VelNetUnity private void Start() { comms = FindObjectOfType(); + 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)) { allPlayers.Add(this); @@ -80,7 +89,7 @@ namespace VelNetUnity dissonanceID = Encoding.UTF8.GetString(message); // tell the comms network that this player joined the channel 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; @@ -125,7 +134,7 @@ namespace VelNetUnity dissonanceID = id; byte[] b = Encoding.UTF8.GetBytes(dissonanceID); owner.SendMessage(this, "d", b); - comms.comms.TrackPlayerPosition(this); + comms.dissonanceComms.TrackPlayerPosition(this); } private void VoiceInitialized(string id) @@ -179,7 +188,7 @@ namespace VelNetUnity //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 (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; byte[] toSend = { isSpeaking ? (byte)1 : (byte)0 }; diff --git a/Samples~/Dissonance Integration/VelNetDissonancePlayer.cs.meta b/Samples~/DissonanceIntegration/VelNetDissonancePlayer.cs.meta similarity index 100% rename from Samples~/Dissonance Integration/VelNetDissonancePlayer.cs.meta rename to Samples~/DissonanceIntegration/VelNetDissonancePlayer.cs.meta diff --git a/Samples~/Example/PlayerPrefab.prefab b/Samples~/Example/PlayerPrefab.prefab index 5bee352..d590dc3 100644 --- a/Samples~/Example/PlayerPrefab.prefab +++ b/Samples~/Example/PlayerPrefab.prefab @@ -14,7 +14,6 @@ GameObject: - component: {fileID: 5845716565458182149} - component: {fileID: 5713671764962751473} - component: {fileID: -4404668399269848200} - - component: {fileID: 7065383111165629622} - component: {fileID: 1181612843795795320} m_Layer: 0 m_Name: PlayerPrefab @@ -134,20 +133,6 @@ MonoBehaviour: isSceneObject: 0 targetPosition: {x: 0, y: 0, z: 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 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/package.json b/package.json index 57f4990..50f6464 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "edu.uga.engr.vel.velnetunity", "displayName": "VelNetUnity", - "version": "1.0.1", + "version": "1.0.2", "unity": "2019.1", "description": "A custom networking library for Unity.", "keywords": [ @@ -17,7 +17,7 @@ { "displayName": "Dissonance Integration", "description": "Includes support for Dissonance Voice, available separately from the Unity Asset Store.", - "path": "Samples~/Dissonance Integration" + "path": "Samples~/DissonanceIntegration" }, { "displayName": "Example",