fixed group messages, fixed some errors with players leaving

handTracking
Anton Franzluebbers 2022-01-07 19:20:21 -05:00
parent c3e3169982
commit 20607ac1b5
15 changed files with 139 additions and 67 deletions

View File

@ -51,10 +51,7 @@ namespace VelNet
if (comms == null) if (comms == null)
{ {
Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this); Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this);
return;
} }
} }
private void OnEnable() private void OnEnable()
@ -93,7 +90,6 @@ namespace VelNet
writer.Write(dissonanceID); writer.Write(dissonanceID);
SendBytes(mem.ToArray()); SendBytes(mem.ToArray());
}; };
VelNetManager.instance.SetupMessageGroup("voice", closePlayers);
} }
} }
@ -108,9 +104,8 @@ namespace VelNet
writer.Write(lastAudioId++); writer.Write(lastAudioId++);
writer.Write(data.ToArray()); writer.Write(data.ToArray());
// send voice data unreliably // send voice data unreliably
SendBytes(mem.ToArray(), false); // SendBytes(mem.ToArray(), false);
// SendBytesToGroup("voice", mem.ToArray()); SendBytesToGroup("voice", mem.ToArray());
} }
/// <summary> /// <summary>
@ -176,7 +171,12 @@ namespace VelNet
} }
else else
{ {
closePlayers = allPlayers.Select(p => p.Owner.userid).ToList(); int lastLength = closePlayers.Count;
closePlayers = allPlayers.Where(p => p != this).Select(p => p.Owner.userid).ToList();
if (closePlayers.Count != lastLength)
{
VelNetManager.instance.SetupMessageGroup("voice", closePlayers);
}
} }
@ -232,7 +232,7 @@ namespace VelNet
} }
case 2: // speaking state case 2: // speaking state
{ {
if (message[0] == 0) if (message[1] == 0)
{ {
comms.SetPlayerStoppedSpeaking(dissonanceID); comms.SetPlayerStoppedSpeaking(dissonanceID);
isSpeaking = false; isSpeaking = false;

View File

@ -15,6 +15,7 @@ GameObject:
- component: {fileID: 9102273340480352682} - component: {fileID: 9102273340480352682}
- component: {fileID: -4404668399269848200} - component: {fileID: -4404668399269848200}
- component: {fileID: 1181612843795795320} - component: {fileID: 1181612843795795320}
- component: {fileID: 7564913803199044469}
m_Layer: 0 m_Layer: 0
m_Name: PlayerPrefab m_Name: PlayerPrefab
m_TagString: Untagged m_TagString: Untagged
@ -117,6 +118,7 @@ MonoBehaviour:
syncedComponents: syncedComponents:
- {fileID: -4404668399269848200} - {fileID: -4404668399269848200}
- {fileID: 1181612843795795320} - {fileID: 1181612843795795320}
- {fileID: 7564913803199044469}
--- !u!114 &-4404668399269848200 --- !u!114 &-4404668399269848200
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -148,3 +150,20 @@ MonoBehaviour:
dissonanceID: dissonanceID:
closePlayers: closePlayers:
maxDistance: 0 maxDistance: 0
--- !u!114 &7564913803199044469
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: 3f1f9b0bbd93a484a987c51f1107ebe5, type: 3}
m_Name:
m_EditorClassIdentifier:
networkObject: {fileID: 9102273340480352682}
serializationRateHz: 30
targetPosition: {x: 0, y: 0, z: 0}
targetRotation: {x: 0, y: 0, z: 0, w: 0}
smoothness: 0.1

View File

@ -58,7 +58,7 @@ MonoBehaviour:
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8565720275311462453} m_GameObject: {fileID: 8565720275311462453}
m_Enabled: 0 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3f1f9b0bbd93a484a987c51f1107ebe5, type: 3} m_Script: {fileID: 11500000, guid: 3f1f9b0bbd93a484a987c51f1107ebe5, type: 3}
m_Name: m_Name:

View File

@ -6,7 +6,7 @@ namespace VelNet
{ {
public NetworkObject networkObject; public NetworkObject networkObject;
protected bool IsMine => networkObject != null && networkObject.owner != null && networkObject.owner.isLocal; protected bool IsMine => networkObject != null && networkObject.owner != null && networkObject.owner.isLocal;
protected NetworkPlayer Owner => networkObject != null ? networkObject.owner : null; protected VelNetPlayer Owner => networkObject != null ? networkObject.owner : null;
/// <summary> /// <summary>
/// call this in child classes to send a message to other people /// call this in child classes to send a message to other people

View File

@ -10,7 +10,7 @@ namespace VelNet
public class NetworkObject : MonoBehaviour public class NetworkObject : MonoBehaviour
{ {
[Header("NetworkObject properties")] [Header("NetworkObject properties")]
public NetworkPlayer owner; public VelNetPlayer owner;
public bool ownershipLocked; public bool ownershipLocked;
public bool IsMine => owner != null && owner.isLocal; public bool IsMine => owner != null && owner.isLocal;

View File

@ -35,18 +35,18 @@ namespace VelNet
public string room; public string room;
private int messagesReceived = 0; private int messagesReceived = 0;
public readonly Dictionary<int, NetworkPlayer> players = new Dictionary<int, NetworkPlayer>(); public readonly Dictionary<int, VelNetPlayer> players = new Dictionary<int, VelNetPlayer>();
public Action<NetworkPlayer> OnJoinedRoom; public Action<VelNetPlayer> OnJoinedRoom;
public Action<NetworkPlayer> OnPlayerJoined; public Action<VelNetPlayer> OnPlayerJoined;
public Action<NetworkPlayer> OnPlayerLeft; public Action<VelNetPlayer> OnPlayerLeft;
public List<NetworkObject> prefabs = new List<NetworkObject>(); public List<NetworkObject> prefabs = new List<NetworkObject>();
public NetworkObject[] sceneObjects; public NetworkObject[] sceneObjects;
public List<string> deletedSceneObjects = new List<string>(); public List<string> deletedSceneObjects = new List<string>();
public readonly Dictionary<string, NetworkObject> objects = new Dictionary<string, NetworkObject>(); //maintains a list of all known objects on the server (ones that have ids) public readonly Dictionary<string, NetworkObject> objects = new Dictionary<string, NetworkObject>(); //maintains a list of all known objects on the server (ones that have ids)
private NetworkPlayer masterPlayer; private VelNetPlayer masterPlayer;
public static NetworkPlayer LocalPlayer => instance.players.Where(p => p.Value.isLocal).Select(p=>p.Value).FirstOrDefault(); public static VelNetPlayer LocalPlayer => instance.players.Where(p => p.Value.isLocal).Select(p=>p.Value).FirstOrDefault();
@ -115,7 +115,7 @@ namespace VelNet
if (m.text != "") if (m.text != "")
{ {
NetworkPlayer player = new NetworkPlayer VelNetPlayer player = new VelNetPlayer
{ {
isLocal = true, isLocal = true,
userid = m.sender, userid = m.sender,
@ -128,12 +128,13 @@ namespace VelNet
} }
else // not for me, a player is joining or leaving else // not for me, a player is joining or leaving
{ {
NetworkPlayer me = players[userid]; VelNetPlayer me = players[userid];
if (me.room != m.text) if (me.room != m.text)
{ {
// we got a left message, kill it // we got a left message, kill it
// change ownership of all objects to master // change ownership of all objects to master
List<string> deleteObjects = new List<string>();
foreach (KeyValuePair<string, NetworkObject> kvp in objects) foreach (KeyValuePair<string, NetworkObject> kvp in objects)
{ {
if (kvp.Value.owner == players[m.sender]) // the owner is the player that left if (kvp.Value.owner == players[m.sender]) // the owner is the player that left
@ -141,8 +142,7 @@ namespace VelNet
// if this object has locked ownership, delete it // if this object has locked ownership, delete it
if (kvp.Value.ownershipLocked) if (kvp.Value.ownershipLocked)
{ {
// TODO this may check for ownership in the future. We don't need ownership here deleteObjects.Add(kvp.Value.networkId);
DeleteNetworkObject(kvp.Value.networkId);
} }
// I'm the local master player, so can take ownership immediately // I'm the local master player, so can take ownership immediately
else if (me.isLocal && me == masterPlayer) else if (me.isLocal && me == masterPlayer)
@ -157,12 +157,15 @@ namespace VelNet
} }
} }
// TODO this may check for ownership in the future. We don't need ownership here
deleteObjects.ForEach(DeleteNetworkObject);
players.Remove(m.sender); players.Remove(m.sender);
} }
else else
{ {
// we got a join message, create it // we got a join message, create it
NetworkPlayer player = new NetworkPlayer VelNetPlayer player = new VelNetPlayer
{ {
isLocal = false, isLocal = false,
room = m.text, room = m.text,
@ -524,7 +527,7 @@ namespace VelNet
public static void InstantiateNetworkObject(string prefabName) public static void InstantiateNetworkObject(string prefabName)
{ {
NetworkPlayer localPlayer = LocalPlayer; VelNetPlayer localPlayer = LocalPlayer;
NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName); NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName);
if (prefab == null) if (prefab == null)
{ {
@ -541,7 +544,7 @@ namespace VelNet
instance.SendTo(MessageType.OTHERS, "7," + newObject.networkId + "," + prefabName); instance.SendTo(MessageType.OTHERS, "7," + newObject.networkId + "," + prefabName);
} }
public static void SomebodyInstantiatedNetworkObject(string networkId, string prefabName, NetworkPlayer owner) public static void SomebodyInstantiatedNetworkObject(string networkId, string prefabName, VelNetPlayer owner)
{ {
NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName); NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName);
if (prefab == null) return; if (prefab == null) return;

View File

@ -6,7 +6,7 @@ namespace VelNet
/// <summary> /// <summary>
/// Represents a network player /// Represents a network player
/// </summary> /// </summary>
public class NetworkPlayer public class VelNetPlayer
{ {
public int userid; public int userid;
public string username; public string username;
@ -26,13 +26,13 @@ namespace VelNet
private bool isMaster; private bool isMaster;
public NetworkPlayer() public VelNetPlayer()
{ {
manager = VelNetManager.instance; manager = VelNetManager.instance;
manager.OnPlayerJoined += HandlePlayerJoined; manager.OnPlayerJoined += HandlePlayerJoined;
} }
public void HandlePlayerJoined(NetworkPlayer player) public void HandlePlayerJoined(VelNetPlayer player)
{ {
//if this is the local player, go through the objects that I own, and send instantiation messages for the ones that have prefab names //if this is the local player, go through the objects that I own, and send instantiation messages for the ones that have prefab names
if (isLocal) if (isLocal)

View File

@ -28,6 +28,10 @@ namespace VelNet
public bool IsTracking => true; public bool IsTracking => true;
private static readonly List<VelNetDissonancePlayer> allPlayers = new List<VelNetDissonancePlayer>(); private static readonly List<VelNetDissonancePlayer> allPlayers = new List<VelNetDissonancePlayer>();
/// <summary>
/// Only sends voice data to players in this list
/// </summary>
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.")]
@ -47,15 +51,30 @@ namespace VelNet
if (comms == null) if (comms == null)
{ {
Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this); Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this);
return;
} }
}
private void OnEnable()
{
// add ourselves to the global list of all players in the scene // 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);
} }
else
{
Debug.LogError("We're already in the player list 🐭", this);
}
}
private void OnDisable()
{
// remove ourselves from the global list of all players in the scene
allPlayers.Remove(this);
}
private void Start()
{
if (IsMine) if (IsMine)
{ {
SetDissonanceID(comms.dissonanceId); SetDissonanceID(comms.dissonanceId);
@ -71,7 +90,6 @@ namespace VelNet
writer.Write(dissonanceID); writer.Write(dissonanceID);
SendBytes(mem.ToArray()); SendBytes(mem.ToArray());
}; };
VelNetManager.instance.SetupMessageGroup("close", closePlayers.ToArray());
} }
} }
@ -83,10 +101,11 @@ namespace VelNet
using MemoryStream mem = new MemoryStream(); using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem); using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.AudioData); writer.Write((byte)MessageType.AudioData);
writer.Write(BitConverter.GetBytes(lastAudioId++)); writer.Write(lastAudioId++);
writer.Write(data.ToArray()); writer.Write(data.ToArray());
// send voice data unreliably // send voice data unreliably
SendBytesToGroup("close", mem.ToArray(), false); // SendBytes(mem.ToArray(), false);
SendBytesToGroup("voice", mem.ToArray());
} }
/// <summary> /// <summary>
@ -147,12 +166,21 @@ namespace VelNet
if (closePlayerListChanged) if (closePlayerListChanged)
{ {
VelNetManager.instance.SetupMessageGroup("close", closePlayers); VelNetManager.instance.SetupMessageGroup("voice", closePlayers);
}
}
else
{
int lastLength = closePlayers.Count;
closePlayers = allPlayers.Where(p => p != this).Select(p => p.Owner.userid).ToList();
if (closePlayers.Count != lastLength)
{
VelNetManager.instance.SetupMessageGroup("voice", closePlayers);
} }
} }
//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.dissonanceComms.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
@ -194,6 +222,7 @@ namespace VelNet
if (dissonanceID == "") // I don't have this yet if (dissonanceID == "") // I don't have this yet
{ {
dissonanceID = reader.ReadString(); dissonanceID = reader.ReadString();
// 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.dissonanceComms.TrackPlayerPosition(this); // tell dissonance to track the remote player comms.dissonanceComms.TrackPlayerPosition(this); // tell dissonance to track the remote player
@ -203,7 +232,7 @@ namespace VelNet
} }
case 2: // speaking state case 2: // speaking state
{ {
if (message[0] == 0) if (message[1] == 0)
{ {
comms.SetPlayerStoppedSpeaking(dissonanceID); comms.SetPlayerStoppedSpeaking(dissonanceID);
isSpeaking = false; isSpeaking = false;

View File

@ -4,7 +4,7 @@ using UnityEngine;
namespace VelNet namespace VelNet
{ {
public class PlayerController : NetworkSerializedObject public class PlayerController : NetworkComponent
{ {
public Vector3 targetPosition; public Vector3 targetPosition;
public Quaternion targetRotation; public Quaternion targetRotation;
@ -13,12 +13,13 @@ namespace VelNet
// Update is called once per frame // Update is called once per frame
private void Update() private void Update()
{ {
if (!IsMine) // if (!IsMine)
{ // {
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);
} // }
else // else
if (IsMine)
{ {
Vector3 movement = new Vector3(); Vector3 movement = new Vector3();
movement.x += Input.GetAxis("Horizontal"); movement.x += Input.GetAxis("Horizontal");
@ -53,25 +54,29 @@ namespace VelNet
} }
} }
//
protected override byte[] SendState() // protected override byte[] SendState()
// {
// using MemoryStream mem = new MemoryStream();
// using BinaryWriter writer = new BinaryWriter(mem);
//
// writer.Write(transform.position);
// writer.Write(transform.rotation);
//
// return mem.ToArray();
// }
//
// protected override void ReceiveState(byte[] message)
// {
// using MemoryStream mem = new MemoryStream(message);
// using BinaryReader reader = new BinaryReader(mem);
//
// targetPosition = reader.ReadVector3();
// targetRotation = reader.ReadQuaternion();
// }
public override void ReceiveBytes(byte[] message)
{ {
using MemoryStream mem = new MemoryStream(); throw new System.NotImplementedException();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write(transform.position);
writer.Write(transform.rotation);
return mem.ToArray();
}
protected override void ReceiveState(byte[] message)
{
using MemoryStream mem = new MemoryStream(message);
using BinaryReader reader = new BinaryReader(mem);
targetPosition = reader.ReadVector3();
targetRotation = reader.ReadQuaternion();
} }
} }
} }

View File

@ -15,6 +15,7 @@ GameObject:
- component: {fileID: 9102273340480352682} - component: {fileID: 9102273340480352682}
- component: {fileID: -4404668399269848200} - component: {fileID: -4404668399269848200}
- component: {fileID: 1181612843795795320} - component: {fileID: 1181612843795795320}
- component: {fileID: 7564913803199044469}
m_Layer: 0 m_Layer: 0
m_Name: PlayerPrefab m_Name: PlayerPrefab
m_TagString: Untagged m_TagString: Untagged
@ -31,7 +32,7 @@ Transform:
m_GameObject: {fileID: 6139051692386484099} m_GameObject: {fileID: 6139051692386484099}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 0 m_RootOrder: 0
@ -117,6 +118,7 @@ MonoBehaviour:
syncedComponents: syncedComponents:
- {fileID: -4404668399269848200} - {fileID: -4404668399269848200}
- {fileID: 1181612843795795320} - {fileID: 1181612843795795320}
- {fileID: 7564913803199044469}
--- !u!114 &-4404668399269848200 --- !u!114 &-4404668399269848200
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -130,7 +132,6 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
networkObject: {fileID: 9102273340480352682} networkObject: {fileID: 9102273340480352682}
serializationRateHz: 30
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 &1181612843795795320 --- !u!114 &1181612843795795320
@ -147,7 +148,22 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
networkObject: {fileID: 9102273340480352682} networkObject: {fileID: 9102273340480352682}
dissonanceID: dissonanceID:
targetPosition: {x: 0, y: 0, z: 0}
targetRotation: {x: 0, y: 0, z: 0, w: 0}
closePlayers: closePlayers:
maxDistance: 0 maxDistance: 0
--- !u!114 &7564913803199044469
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: 3f1f9b0bbd93a484a987c51f1107ebe5, type: 3}
m_Name:
m_EditorClassIdentifier:
networkObject: {fileID: 9102273340480352682}
serializationRateHz: 30
targetPosition: {x: 0, y: 0, z: 0}
targetRotation: {x: 0, y: 0, z: 0, w: 0}
smoothness: 0.1

View File

@ -1834,7 +1834,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 03a4d4e1a7fd74c7ab2eccca4ce168db, type: 3} m_Script: {fileID: 11500000, guid: 03a4d4e1a7fd74c7ab2eccca4ce168db, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
host: neko.ugavel.com host: 129.159.107.234
port: 3290 port: 3290
udpConnected: 0 udpConnected: 0
userid: -1 userid: -1
@ -3406,7 +3406,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8565720275311462455, guid: 6e4a023f70e01405e8b249a4488fe319, type: 3} - target: {fileID: 8565720275311462455, guid: 6e4a023f70e01405e8b249a4488fe319, type: 3}
propertyPath: m_LocalPosition.y propertyPath: m_LocalPosition.y
value: 0 value: 2
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8565720275311462455, guid: 6e4a023f70e01405e8b249a4488fe319, type: 3} - target: {fileID: 8565720275311462455, guid: 6e4a023f70e01405e8b249a4488fe319, type: 3}
propertyPath: m_LocalPosition.z propertyPath: m_LocalPosition.z

View File

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