diff --git a/Runtime/NetworkObject.cs b/Runtime/NetworkObject.cs index aa39b78..b08e041 100644 --- a/Runtime/NetworkObject.cs +++ b/Runtime/NetworkObject.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; #if UNITY_EDITOR @@ -42,6 +43,12 @@ namespace VelNet } // send the message and an identifier for which component it belongs to + if (!syncedComponents.Contains(component)) + { + Debug.LogError("Can't send message if this component is not registered with the NetworkObject.", this); + return; + } + int index = syncedComponents.IndexOf(component); owner.SendMessage(this, index.ToString(), message, reliable); } @@ -62,7 +69,19 @@ namespace VelNet public void ReceiveBytes(string identifier, byte[] message) { // send the message to the right component - syncedComponents[int.Parse(identifier)].ReceiveBytes(message); + try + { + syncedComponents[int.Parse(identifier)].ReceiveBytes(message); + } + catch (Exception e) + { + Debug.LogError($"Error in handling message:\n{e}", this); + } + } + + public void TakeOwnership() + { + VelNetManager.TakeOwnership(networkId); } } diff --git a/Runtime/Util/NetworkSerializedObject.cs b/Runtime/Util/NetworkSerializedObject.cs index 13037d1..0569eed 100644 --- a/Runtime/Util/NetworkSerializedObject.cs +++ b/Runtime/Util/NetworkSerializedObject.cs @@ -9,7 +9,7 @@ namespace VelNet [Tooltip("Send rate of this object. This caps out at the framerate of the game.")] public float serializationRateHz = 30; - private void Awake() + protected virtual void Awake() { StartCoroutine(SendMessageUpdate()); } diff --git a/Runtime/Util/NetworkSerializedObjectStream.cs b/Runtime/Util/NetworkSerializedObjectStream.cs new file mode 100644 index 0000000..a6929f8 --- /dev/null +++ b/Runtime/Util/NetworkSerializedObjectStream.cs @@ -0,0 +1,47 @@ +using System.Collections; +using System.IO; +using UnityEngine; +using UnityEngine.Serialization; + +namespace VelNet +{ + public abstract class NetworkSerializedObjectStream : NetworkComponent + { + [Tooltip("Send rate of this object. This caps out at the framerate of the game.")] + public float serializationRateHz = 30; + + protected virtual void Awake() + { + StartCoroutine(SendMessageUpdate()); + } + + private IEnumerator SendMessageUpdate() + { + while (true) + { + if (IsMine) + { + using MemoryStream mem = new MemoryStream(); + using BinaryWriter writer = new BinaryWriter(mem); + SendState(writer); + SendBytes(mem.ToArray()); + } + + yield return new WaitForSeconds(1f / serializationRateHz); + } + // ReSharper disable once IteratorNeverReturns + } + + public override void ReceiveBytes(byte[] message) + { + using MemoryStream mem = new MemoryStream(message); + using BinaryReader reader = new BinaryReader(mem); + + ReceiveState(reader); + } + + protected abstract void SendState(BinaryWriter binaryWriter); + + protected abstract void ReceiveState(BinaryReader binaryReader); + } +} \ No newline at end of file diff --git a/Runtime/Util/NetworkSerializedObjectStream.cs.meta b/Runtime/Util/NetworkSerializedObjectStream.cs.meta new file mode 100644 index 0000000..6f4475e --- /dev/null +++ b/Runtime/Util/NetworkSerializedObjectStream.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7da4222cdb03a3e43aceb43ef1e28f7e +timeCreated: 1641514434 \ No newline at end of file diff --git a/Runtime/VelNetManager.cs b/Runtime/VelNetManager.cs index 7fe36d9..71ea086 100644 --- a/Runtime/VelNetManager.cs +++ b/Runtime/VelNetManager.cs @@ -208,6 +208,9 @@ namespace VelNet .Where(kvp => kvp.Value == null || !kvp.Value.isSceneObject) .Select(o => o.Key) .ToList().ForEach(NetworkDestroy); + + // then remove references to the ones that are left + objects.Clear(); // empty all the groups foreach (string group in instance.groups.Keys) @@ -217,7 +220,6 @@ namespace VelNet instance.groups.Clear(); - Debug.Log("Left VelNet Room: " + oldRoom); try { OnLeftRoom?.Invoke(oldRoom); @@ -328,13 +330,9 @@ namespace VelNet masterPlayer.SetAsMasterPlayer(); // master player should take over any objects that do not have an owner - foreach (KeyValuePair kvp in objects) { - if (kvp.Value.owner == null) - { - kvp.Value.owner = masterPlayer; - } + kvp.Value.owner ??= masterPlayer; } break; @@ -659,24 +657,32 @@ namespace VelNet } - public static void InstantiateNetworkObject(string prefabName) + public static NetworkObject InstantiateNetworkObject(string prefabName) { VelNetPlayer localPlayer = LocalPlayer; NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName); if (prefab == null) { Debug.LogError("Couldn't find a prefab with that name: " + prefabName); - return; + return null; } + string networkId = localPlayer.userid + "-" + localPlayer.lastObjectId++; + if (instance.objects.ContainsKey(networkId)) + { + Debug.LogError("Can't instantiate object. Obj with that network ID was already instantiated.", instance.objects[networkId]); + return null; + } NetworkObject newObject = Instantiate(prefab); - newObject.networkId = localPlayer.userid + "-" + localPlayer.lastObjectId++; + newObject.networkId = networkId; newObject.prefabName = prefabName; newObject.owner = localPlayer; instance.objects.Add(newObject.networkId, newObject); // only sent to others, as I already instantiated this. Nice that it happens immediately. SendTo(MessageType.OTHERS, "7," + newObject.networkId + "," + prefabName); + + return newObject; } public static void SomebodyInstantiatedNetworkObject(string networkId, string prefabName, VelNetPlayer owner) @@ -690,11 +696,20 @@ namespace VelNet instance.objects.Add(newObject.networkId, newObject); } + public static void NetworkDestroy(NetworkObject obj) + { + NetworkDestroy(obj.networkId); + } + public static void NetworkDestroy(string networkId) { if (!instance.objects.ContainsKey(networkId)) return; NetworkObject obj = instance.objects[networkId]; - if (obj == null) return; + if (obj == null) + { + instance.objects.Remove(networkId); + return; + } if (obj.isSceneObject) { instance.deletedSceneObjects.Add(networkId); diff --git a/package.json b/package.json index 4f2b772..b846be2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "edu.uga.engr.vel.velnet", "displayName": "VelNet", - "version": "1.0.5", + "version": "1.0.6", "unity": "2019.1", "description": "A custom networking library for Unity.", "keywords": [