send optional position data with an instantiation event to spawn in a known location, consolidate code for local instantiation

upm
Anton Franzluebbers 2023-01-26 16:53:23 -05:00
parent 14b897807b
commit 424c9c85a6
4 changed files with 142 additions and 42 deletions

View File

@ -27,7 +27,15 @@ namespace VelNet
public string networkId;
/// <summary>
/// This is generated at editor time and used to generated the network id at runtime.
/// This is used internally to handle spawning of objects for players that joined late.
/// This way objects can be spawned in a static location
/// </summary>
internal bool instantiatedWithTransform = false;
internal Vector3 initialPosition;
internal Quaternion initialRotation;
/// <summary>
/// This is generated at editor time and used to generate the network id at runtime.
/// This is needed because finding all objects of type at runtime doesn't have a guaranteed order.
/// </summary>
public int sceneNetworkId;

View File

@ -51,6 +51,7 @@ namespace VelNet
ObjectSync,
TakeOwnership,
Instantiate,
InstantiateWithTransform,
Destroy,
DeleteSceneObjects,
Custom
@ -1089,6 +1090,7 @@ namespace VelNet
Debug.LogError("Joining room before logging in.", instance);
return;
}
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
@ -1235,36 +1237,15 @@ namespace VelNet
/// <returns>The NetworkObject for the instantiated object.</returns>
public static NetworkObject NetworkInstantiate(string prefabName)
{
VelNetPlayer localPlayer = LocalPlayer;
NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName);
if (prefab == null)
{
VelNetLogger.Error("Couldn't find a prefab with that name: " + prefabName + "\nMake sure to add the prefab to list of prefabs in VelNetManager");
return null;
}
string networkId = localPlayer.userid + "-" + localPlayer.lastObjectId++;
VelNetPlayer owner = LocalPlayer;
string networkId = AllocateNetworkId();
if (instance.objects.ContainsKey(networkId))
{
VelNetLogger.Error("Can't instantiate object. Obj with that network ID was already instantiated.", instance.objects[networkId]);
return null;
}
NetworkObject newObject = Instantiate(prefab);
newObject.networkId = networkId;
newObject.prefabName = prefabName;
newObject.owner = localPlayer;
try
{
newObject.OwnershipChanged?.Invoke(localPlayer);
}
catch (Exception e)
{
VelNetLogger.Error("Error in event handling.\n" + e);
}
instance.objects.Add(newObject.networkId, newObject);
NetworkObject newObject = ActuallyInstantiate(networkId, prefabName, owner);
// only sent to others, as I already instantiated this. Nice that it happens immediately.
using MemoryStream mem = new MemoryStream();
@ -1277,10 +1258,54 @@ namespace VelNet
return newObject;
}
public static void SomebodyInstantiatedNetworkObject(string networkId, string prefabName, VelNetPlayer owner)
/// <summary>
/// Instantiates a prefab for all players at a specific location
/// </summary>
/// <param name="prefabName">This prefab *must* by added to the list of prefabs in the scene's VelNetManager for all players.</param>
/// <param name="position"></param>
/// <param name="rotation"></param>
/// <returns>The NetworkObject for the instantiated object.</returns>
public static NetworkObject NetworkInstantiate(string prefabName, Vector3 position, Quaternion rotation)
{
VelNetPlayer owner = LocalPlayer;
string networkId = AllocateNetworkId();
if (instance.objects.ContainsKey(networkId))
{
VelNetLogger.Error("Can't instantiate object. Obj with that network ID was already instantiated.", instance.objects[networkId]);
return null;
}
NetworkObject newObject = ActuallyInstantiate(networkId, prefabName, owner, position, rotation);
// only sent to others, as I already instantiated this. Nice that it happens immediately.
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.InstantiateWithTransform);
writer.Write(newObject.networkId);
writer.Write(prefabName);
writer.Write(position);
writer.Write(rotation);
SendToRoom(mem.ToArray(), include_self: false, reliable: true);
return newObject;
}
/// <summary>
/// This happens locally on all clients
/// </summary>
/// <param name="networkId"></param>
/// <param name="prefabName"></param>
/// <param name="owner"></param>
/// <returns></returns>
internal static NetworkObject ActuallyInstantiate(string networkId, string prefabName, VelNetPlayer owner)
{
NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName);
if (prefab == null) return;
if (prefab == null)
{
VelNetLogger.Error("Couldn't find a prefab with that name: " + prefabName + "\nMake sure to add the prefab to list of prefabs in VelNetManager");
return null;
}
NetworkObject newObject = Instantiate(prefab);
newObject.networkId = networkId;
newObject.prefabName = prefabName;
@ -1295,6 +1320,42 @@ namespace VelNet
}
instance.objects.Add(newObject.networkId, newObject);
return newObject;
}
internal static NetworkObject ActuallyInstantiate(string networkId, string prefabName, VelNetPlayer owner, Vector3 position, Quaternion rotation)
{
NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName);
if (prefab == null)
{
VelNetLogger.Error("Couldn't find a prefab with that name: " + prefabName + "\nMake sure to add the prefab to list of prefabs in VelNetManager");
return null;
}
NetworkObject newObject = Instantiate(prefab, position, rotation);
newObject.instantiatedWithTransform = true;
newObject.initialPosition = position;
newObject.initialRotation = rotation;
newObject.networkId = networkId;
newObject.prefabName = prefabName;
newObject.owner = owner;
try
{
newObject.OwnershipChanged?.Invoke(owner);
}
catch (Exception e)
{
VelNetLogger.Error("Error in event handling.\n" + e);
}
instance.objects.Add(newObject.networkId, newObject);
return newObject;
}
private static string AllocateNetworkId()
{
return LocalPlayer.userid + "-" + LocalPlayer.lastObjectId++;
}
public static void NetworkDestroy(NetworkObject obj)

View File

@ -18,7 +18,7 @@ namespace VelNet
private VelNetManager manager;
/// <summary>
/// For instantiation
/// For instantiation. This is not synced across the network
/// </summary>
internal int lastObjectId;
@ -40,6 +40,19 @@ namespace VelNet
foreach (KeyValuePair<string, NetworkObject> kvp in manager.objects)
{
if (kvp.Value.owner == this && kvp.Value.prefabName != "")
{
if (kvp.Value.instantiatedWithTransform)
{
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)VelNetManager.MessageType.InstantiateWithTransform);
writer.Write(kvp.Value.networkId);
writer.Write(kvp.Value.prefabName);
writer.Write(kvp.Value.initialPosition);
writer.Write(kvp.Value.initialRotation);
VelNetManager.SendToRoom(mem.ToArray(), false, true);
}
else
{
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
@ -48,6 +61,8 @@ namespace VelNet
writer.Write(kvp.Value.prefabName);
VelNetManager.SendToRoom(mem.ToArray(), false, true);
}
}
}
if (IsMaster)
@ -75,7 +90,7 @@ namespace VelNet
//individual message parameters separated by comma
VelNetManager.MessageType messageType = (VelNetManager.MessageType)reader.ReadByte();
if(messageType == VelNetManager.MessageType.Custom)
if (messageType == VelNetManager.MessageType.Custom)
{
// Custom packets. These are global data that can be sent from anywhere.
// Any script can subscribe to the callback to receive the message data.
@ -90,6 +105,7 @@ namespace VelNet
{
VelNetLogger.Error(e.ToString());
}
return;
}
@ -151,7 +167,22 @@ namespace VelNet
break; //we already have this one, ignore
}
VelNetManager.SomebodyInstantiatedNetworkObject(networkId, prefabName, this);
VelNetManager.ActuallyInstantiate(networkId, prefabName, this);
break;
}
case VelNetManager.MessageType.InstantiateWithTransform: // I'm trying to instantiate an object
{
string networkId = reader.ReadString();
string prefabName = reader.ReadString();
Vector3 position = reader.ReadVector3();
Quaternion rotation = reader.ReadQuaternion();
if (manager.objects.ContainsKey(networkId))
{
break; //we already have this one, ignore
}
VelNetManager.ActuallyInstantiate(networkId, prefabName, this, position, rotation);
break;
}

View File

@ -1,7 +1,7 @@
{
"name": "edu.uga.engr.vel.velnet",
"displayName": "VelNet",
"version": "1.1.7",
"version": "1.1.8",
"unity": "2019.1",
"description": "A custom networking library for Unity.",
"keywords": [