removed dissonance integration

handTracking
Anton Franzluebbers 2022-01-07 19:54:58 -05:00
parent 20607ac1b5
commit 7e90b6d8cc
36 changed files with 56 additions and 989 deletions

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 14a35ccfe945cc54292ca4e8940b53b9
guid: c95caefcc22a5ea43a1c879526e299b1
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 07900994db5c50c4794e338da120f31b
guid: f4838fd3ac54efa4c88253bb977c20c1
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Dissonance;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
@ -14,13 +15,13 @@ namespace VelNet
public Text messages;
public List<string> messageBuffer;
public Dropdown microphones;
Dissonance.DissonanceComms comms;
DissonanceComms comms;
public void HandleSend()
{
if (sendInput.text != "")
{
velNetManager.SendTo(VelNetManager.MessageType.OTHERS, sendInput.text);
VelNetManager.SendTo(VelNetManager.MessageType.OTHERS, sendInput.text);
}
}
@ -28,7 +29,7 @@ namespace VelNet
{
if (userInput.text != "")
{
velNetManager.Login(userInput.text, "nopass");
VelNetManager.Login(userInput.text, "nopass");
}
}
@ -36,14 +37,14 @@ namespace VelNet
{
if (roomInput.text != "")
{
velNetManager.Join(roomInput.text);
VelNetManager.Join(roomInput.text);
}
}
// Start is called before the first frame update
private void Start()
{
comms = FindObjectOfType<Dissonance.DissonanceComms>();
comms = FindObjectOfType<DissonanceComms>();
microphones.AddOptions(new List<string>(Microphone.devices));
velNetManager.MessageReceived += (m) =>
{

View File

@ -117,7 +117,7 @@ MonoBehaviour:
isSceneObject: 0
syncedComponents:
- {fileID: -4404668399269848200}
- {fileID: 1181612843795795320}
- {fileID: 0}
- {fileID: 7564913803199044469}
--- !u!114 &-4404668399269848200
MonoBehaviour:
@ -143,7 +143,7 @@ MonoBehaviour:
m_GameObject: {fileID: 6139051692386484099}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c773e094326d413bb1bca7f91cbf7f8c, type: 3}
m_Script: {fileID: 11500000, guid: 068080cf74f24b74caef652efb5bcfdc, type: 3}
m_Name:
m_EditorClassIdentifier:
networkObject: {fileID: 9102273340480352682}

View File

@ -2291,7 +2291,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1434745018}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5d2009d8e264649749c0315d48765749, type: 3}
m_Script: {fileID: 11500000, guid: 0b249e3fdf4af5d4d9d36b9222998afa, type: 3}
m_Name:
m_EditorClassIdentifier:
dissonanceId:

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: c506b9118efc2de4ea5f2b2f26a52b9d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,83 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!244 &-1719467165466355418
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 6362d3ceb713f4c3fa42448a3e29217e
m_EffectName: Dissonance Echo Cancellation
m_MixLevel: a240a2d1f057e4cf9bbc59f6cfbec367
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!241 &24100000
AudioMixerController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: VelAudioMixer
m_OutputGroup: {fileID: 0}
m_MasterGroup: {fileID: 24300002}
m_Snapshots:
- {fileID: 24500006}
m_StartSnapshot: {fileID: 24500006}
m_SuspendThreshold: -80
m_EnableSuspend: 1
m_UpdateMode: 1
m_ExposedParameters: []
m_AudioMixerGroupViews:
- guids:
- b8e40716c8c1442ab9ef14e149b2423c
name: View
m_CurrentViewIndex: 0
m_TargetSnapshot: {fileID: 24500006}
--- !u!243 &24300002
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Master
m_AudioMixer: {fileID: 24100000}
m_GroupID: b8e40716c8c1442ab9ef14e149b2423c
m_Children: []
m_Volume: 3d9590ea0314643bd94e1616b88508ef
m_Pitch: 31f1ddadf3a5d47caab0e64b81ced2ae
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 24400004}
- {fileID: -1719467165466355418}
m_UserColorIndex: 0
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &24400004
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: f79719d1f394d4b4783ede937d403602
m_EffectName: Attenuation
m_MixLevel: 8d97d9fd1e8d446eb9244b5dead78e90
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!245 &24500006
AudioMixerSnapshotController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Snapshot
m_AudioMixer: {fileID: 24100000}
m_SnapshotID: 86ea5b9fedb76448594a5ab2119e34a1
m_FloatValues: {}
m_TransitionOverrides: {}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: fa1da19d935e241119cdd522ceae772c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 24100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,110 +0,0 @@
using System;
using Dissonance;
using Dissonance.Networking;
using UnityEngine;
using UnityEngine.Serialization;
namespace VelNet
{
/// <summary>
/// Added to the same object as DissonanceComms component. Only one in the scene.
/// </summary>
[RequireComponent(typeof(DissonanceComms))]
[AddComponentMenu("VelNet/Dissonance/VelNet Comms Network")]
public class VelCommsNetwork : MonoBehaviour, ICommsNetwork
{
public ConnectionStatus Status => manager.connected ? ConnectionStatus.Connected : ConnectionStatus.Disconnected;
public NetworkMode Mode => NetworkMode.Client;
public event Action<NetworkMode> ModeChanged;
public event Action<string, CodecSettings> PlayerJoined;
public event Action<string> PlayerLeft;
public event Action<VoicePacket> VoicePacketReceived;
public event Action<TextMessage> TextPacketReceived;
public event Action<string> PlayerStartedSpeaking;
public event Action<string> PlayerStoppedSpeaking;
public event Action<RoomEvent> PlayerEnteredRoom;
public event Action<RoomEvent> PlayerExitedRoom;
private ConnectionStatus _status = ConnectionStatus.Disconnected;
private CodecSettings initSettings;
public string dissonanceId;
[HideInInspector] public DissonanceComms dissonanceComms;
private VelNetManager manager;
/// <summary>
/// listen to this if you want to send voice
/// </summary>
public Action<ArraySegment<byte>> VoiceQueued;
// Start is called before the first frame update
private void Start()
{
_status = ConnectionStatus.Connected;
dissonanceComms = GetComponent<DissonanceComms>();
manager = VelNetManager.instance;
}
public void Initialize(string playerName, Rooms rooms, PlayerChannels playerChannels, RoomChannels roomChannels, CodecSettings codecSettings)
{
dissonanceId = playerName;
initSettings = codecSettings;
dissonanceComms.ResetMicrophoneCapture();
}
public void VoiceReceived(string sender, byte[] data)
{
uint sequenceNumber = BitConverter.ToUInt32(data, 0);
VoicePacket vp = new VoicePacket(sender, ChannelPriority.Default, 1, true, new ArraySegment<byte>(data, 4, data.Length - 4), sequenceNumber);
VoicePacketReceived?.Invoke(vp);
}
public void SendText(string data, ChannelType recipientType, string recipientId)
{
Debug.Log("sending text");
}
public void SendVoice(ArraySegment<byte> data)
{
VoiceQueued?.Invoke(data);
}
public void SetPlayerJoined(string id)
{
Debug.Log("Dissonance player joined");
PlayerJoined?.Invoke(id, initSettings);
RoomEvent re = new RoomEvent
{
Joined = true,
Room = "Global",
PlayerName = id
};
PlayerEnteredRoom?.Invoke(re);
}
public void SetPlayerLeft(string id)
{
RoomEvent re = new RoomEvent
{
Joined = false,
Room = "Global",
PlayerName = id
};
PlayerExitedRoom?.Invoke(re);
// only send this event for non-local players
if (id != dissonanceId) PlayerLeft?.Invoke(id);
}
public void SetPlayerStartedSpeaking(string id)
{
PlayerStartedSpeaking?.Invoke(id);
}
public void SetPlayerStoppedSpeaking(string id)
{
PlayerStoppedSpeaking?.Invoke(id);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5d2009d8e264649749c0315d48765749
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,251 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dissonance;
using UnityEngine;
namespace VelNet
{
/// <summary>
/// This should be added to your player object
/// </summary>
[AddComponentMenu("VelNet/Dissonance/VelNet Dissonance Player")]
public class VelNetDissonancePlayer : NetworkComponent, IDissonancePlayer
{
private VelCommsNetwork comms;
private bool isSpeaking;
private uint lastAudioId;
[Header("VelNet Dissonance Player Properties")]
public string dissonanceID = "";
//required by dissonance for spatial audio
public string PlayerId => dissonanceID;
public Vector3 Position => transform.position;
public Quaternion Rotation => transform.rotation;
public NetworkPlayerType Type => IsMine ? NetworkPlayerType.Local : NetworkPlayerType.Remote;
public bool IsTracking => true;
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>();
[Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")]
public float maxDistance;
private enum MessageType : byte
{
AudioData,
DissonanceId,
SpeakingState
}
// This object should not be in the scene at the start.
private void Awake()
{
comms = FindObjectOfType<VelCommsNetwork>();
if (comms == null)
{
Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this);
}
}
private void OnEnable()
{
// add ourselves to the global list of all players in the scene
if (!allPlayers.Contains(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)
{
SetDissonanceID(comms.dissonanceId);
comms.VoiceQueued += SendVoiceData;
//we also need to know when other players join, so we can send the dissonance ID again
VelNetManager.instance.OnPlayerJoined += (player) =>
{
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.DissonanceId);
writer.Write(dissonanceID);
SendBytes(mem.ToArray());
};
}
}
private void SendVoiceData(ArraySegment<byte> data)
{
// need to send it
if (!IsMine) return;
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.AudioData);
writer.Write(lastAudioId++);
writer.Write(data.ToArray());
// send voice data unreliably
// SendBytes(mem.ToArray(), false);
SendBytesToGroup("voice", mem.ToArray());
}
/// <summary>
/// This sort of all initializes dissonance
/// </summary>
/// <param name="id">Dissonance ID</param>
public void SetDissonanceID(string id)
{
dissonanceID = id;
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.DissonanceId);
writer.Write(dissonanceID);
SendBytes(mem.ToArray());
comms.dissonanceComms.TrackPlayerPosition(this);
}
private void VoiceInitialized(string id)
{
dissonanceID = id;
}
private void OnDestroy()
{
comms.SetPlayerLeft(dissonanceID);
}
// Update is called once per frame
private void Update()
{
if (!IsMine) return;
// handle nearness cutoff
if (maxDistance > 0)
{
bool closePlayerListChanged = false;
foreach (VelNetDissonancePlayer p in allPlayers)
{
if (p == this)
{
continue;
}
float dist = Vector3.Distance(p.transform.position, transform.position);
if (dist < maxDistance && !closePlayers.Contains(p.Owner.userid))
{
closePlayers.Add(p.Owner.userid);
closePlayerListChanged = true;
}
else if (dist >= maxDistance && closePlayers.Contains(p.Owner.userid))
{
closePlayers.Remove(p.Owner.userid);
closePlayerListChanged = true;
}
}
if (closePlayerListChanged)
{
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
//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
{
isSpeaking = !isSpeaking;
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.SpeakingState);
writer.Write(isSpeaking ? (byte)1 : (byte)0);
SendBytes(mem.ToArray());
if (!isSpeaking)
{
lastAudioId = 0;
}
}
}
public override void ReceiveBytes(byte[] message)
{
using MemoryStream mem = new MemoryStream(message);
using BinaryReader reader = new BinaryReader(mem);
byte identifier = reader.ReadByte();
switch (identifier)
{
case 0: //audio data
{
if (isSpeaking)
{
comms.VoiceReceived(dissonanceID, message.Skip(1).ToArray());
}
break;
}
case 1: //dissonance id (player joined)
{
if (dissonanceID == "") // I don't have this yet
{
dissonanceID = reader.ReadString();
// tell the comms network that this player joined the channel
comms.SetPlayerJoined(dissonanceID); // tell dissonance
comms.dissonanceComms.TrackPlayerPosition(this); // tell dissonance to track the remote player
}
break;
}
case 2: // speaking state
{
if (message[1] == 0)
{
comms.SetPlayerStoppedSpeaking(dissonanceID);
isSpeaking = false;
}
else
{
comms.SetPlayerStartedSpeaking(dissonanceID);
isSpeaking = true;
}
break;
}
}
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: c773e094326d413bb1bca7f91cbf7f8c
timeCreated: 1641506874

View File

@ -11,6 +11,7 @@ namespace VelNet
{
[Header("NetworkObject properties")]
public VelNetPlayer owner;
[Tooltip("Whether this object's ownership is transferrable. Should be true for player objects.")]
public bool ownershipLocked;
public bool IsMine => owner != null && owner.isLocal;

View File

@ -46,8 +46,7 @@ namespace VelNet
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)
private VelNetPlayer masterPlayer;
public static VelNetPlayer 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();
// Use this for initialization
@ -436,24 +435,24 @@ namespace VelNet
}
}
private void SendUdpMessage(string message)
private static void SendUdpMessage(string message)
{
if (udpSocket == null || !udpConnected)
if (instance.udpSocket == null || !instance.udpConnected)
{
return;
}
byte[] data = Encoding.UTF8.GetBytes(message);
//Debug.Log("Attempting to send: " + message);
udpSocket.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
instance.udpSocket.SendTo(data, data.Length, SocketFlags.None, instance.RemoteEndPoint);
}
/// <summary>
/// Send message to server using socket connection.
/// </summary>
private void SendNetworkMessage(string clientMessage)
private static void SendNetworkMessage(string clientMessage)
{
if (socketConnection == null)
if (instance.socketConnection == null)
{
return;
}
@ -461,7 +460,7 @@ namespace VelNet
try
{
// Get a stream object for writing.
NetworkStream stream = socketConnection.GetStream();
NetworkStream stream = instance.socketConnection.GetStream();
if (stream.CanWrite)
{
// Convert string message to byte array.
@ -477,22 +476,22 @@ namespace VelNet
}
}
public void Login(string username, string password)
public static void Login(string username, string password)
{
SendNetworkMessage("0:" + username + ":" + password);
}
public void Join(string roomname)
public static void Join(string roomname)
{
SendNetworkMessage("2:" + roomname);
}
public void Leave()
public static void Leave()
{
SendNetworkMessage("2:-1");
}
public void SendTo(MessageType type, string message, bool reliable = true)
public static void SendTo(MessageType type, string message, bool reliable = true)
{
if (reliable)
{
@ -500,11 +499,11 @@ namespace VelNet
}
else
{
SendUdpMessage(userid + ":3:" + (int)type + ":" + message);
SendUdpMessage(instance.userid + ":3:" + (int)type + ":" + message);
}
}
public void SendToGroup(string group, string message, bool reliable = true)
public static void SendToGroup(string group, string message, bool reliable = true)
{
if (reliable)
{
@ -512,14 +511,14 @@ namespace VelNet
}
else
{
SendUdpMessage(userid + ":4:" + group + ":" + message);
SendUdpMessage(instance.userid + ":4:" + group + ":" + message);
}
}
/// <summary>
/// changes the designated group that sendto(4) will go to
/// </summary>
public void SetupMessageGroup(string groupName, IEnumerable<int> userIds)
public static void SetupMessageGroup(string groupName, IEnumerable<int> userIds)
{
SendNetworkMessage($"5:{groupName}:{string.Join(":", userIds)}");
}
@ -534,14 +533,15 @@ namespace VelNet
Debug.LogError("Couldn't find a prefab with that name: " + prefabName);
return;
}
NetworkObject newObject = Instantiate(prefab);
newObject.networkId = localPlayer.userid + "-" + localPlayer.lastObjectId++;;
newObject.networkId = localPlayer.userid + "-" + localPlayer.lastObjectId++;
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.
instance.SendTo(MessageType.OTHERS, "7," + newObject.networkId + "," + prefabName);
SendTo(MessageType.OTHERS, "7," + newObject.networkId + "," + prefabName);
}
public static void SomebodyInstantiatedNetworkObject(string networkId, string prefabName, VelNetPlayer owner)

View File

@ -41,7 +41,7 @@ namespace VelNet
{
if (kvp.Value.owner == this && kvp.Value.prefabName != "")
{
manager.SendTo(VelNetManager.MessageType.OTHERS, "7," + kvp.Value.networkId + "," + kvp.Value.prefabName);
VelNetManager.SendTo(VelNetManager.MessageType.OTHERS, "7," + kvp.Value.networkId + "," + kvp.Value.prefabName);
}
}
@ -138,12 +138,12 @@ namespace VelNet
public void SendGroupMessage(NetworkObject obj, string group, string identifier, byte[] data, bool reliable = true)
{
manager.SendToGroup(group, "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data), reliable);
VelNetManager.SendToGroup(group, "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data), reliable);
}
public void SendMessage(NetworkObject obj, string identifier, byte[] data, bool reliable = true)
{
manager.SendTo(VelNetManager.MessageType.OTHERS, "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data), reliable);
VelNetManager.SendTo(VelNetManager.MessageType.OTHERS, "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data), reliable);
}
/// <summary>
@ -155,7 +155,7 @@ namespace VelNet
if (!manager.objects.ContainsKey(networkId) || manager.objects[networkId].owner != this || !isLocal) return;
// send to all, which will make me delete as well
manager.SendTo(VelNetManager.MessageType.ALL_ORDERED, "8," + networkId);
VelNetManager.SendTo(VelNetManager.MessageType.ALL_ORDERED, "8," + networkId);
}
/// <summary>
@ -174,14 +174,14 @@ namespace VelNet
manager.objects[networkId].owner = this;
// must be ordered, so that ownership transfers are not confused. Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
manager.SendTo(VelNetManager.MessageType.ALL_ORDERED, "6," + networkId);
VelNetManager.SendTo(VelNetManager.MessageType.ALL_ORDERED, "6," + networkId);
return true;
}
public void SendSceneUpdate()
{
manager.SendTo(VelNetManager.MessageType.OTHERS, "9," + string.Join(",", manager.deletedSceneObjects));
VelNetManager.SendTo(VelNetManager.MessageType.OTHERS, "9," + string.Join(",", manager.deletedSceneObjects));
}
}
}

View File

@ -1,83 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!244 &-1719467165466355418
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 6362d3ceb713f4c3fa42448a3e29217e
m_EffectName: Dissonance Echo Cancellation
m_MixLevel: a240a2d1f057e4cf9bbc59f6cfbec367
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!241 &24100000
AudioMixerController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: VelAudioMixer
m_OutputGroup: {fileID: 0}
m_MasterGroup: {fileID: 24300002}
m_Snapshots:
- {fileID: 24500006}
m_StartSnapshot: {fileID: 24500006}
m_SuspendThreshold: -80
m_EnableSuspend: 1
m_UpdateMode: 1
m_ExposedParameters: []
m_AudioMixerGroupViews:
- guids:
- b8e40716c8c1442ab9ef14e149b2423c
name: View
m_CurrentViewIndex: 0
m_TargetSnapshot: {fileID: 24500006}
--- !u!243 &24300002
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Master
m_AudioMixer: {fileID: 24100000}
m_GroupID: b8e40716c8c1442ab9ef14e149b2423c
m_Children: []
m_Volume: 3d9590ea0314643bd94e1616b88508ef
m_Pitch: 31f1ddadf3a5d47caab0e64b81ced2ae
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 24400004}
- {fileID: -1719467165466355418}
m_UserColorIndex: 0
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &24400004
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: f79719d1f394d4b4783ede937d403602
m_EffectName: Attenuation
m_MixLevel: 8d97d9fd1e8d446eb9244b5dead78e90
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!245 &24500006
AudioMixerSnapshotController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Snapshot
m_AudioMixer: {fileID: 24100000}
m_SnapshotID: 86ea5b9fedb76448594a5ab2119e34a1
m_FloatValues: {}
m_TransitionOverrides: {}

View File

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: fa1da19d935e241119cdd522ceae772c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 24100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,110 +0,0 @@
using System;
using Dissonance;
using Dissonance.Networking;
using UnityEngine;
using UnityEngine.Serialization;
namespace VelNet
{
/// <summary>
/// Added to the same object as DissonanceComms component. Only one in the scene.
/// </summary>
[RequireComponent(typeof(DissonanceComms))]
[AddComponentMenu("VelNet/Dissonance/VelNet Comms Network")]
public class VelCommsNetwork : MonoBehaviour, ICommsNetwork
{
public ConnectionStatus Status => manager.connected ? ConnectionStatus.Connected : ConnectionStatus.Disconnected;
public NetworkMode Mode => NetworkMode.Client;
public event Action<NetworkMode> ModeChanged;
public event Action<string, CodecSettings> PlayerJoined;
public event Action<string> PlayerLeft;
public event Action<VoicePacket> VoicePacketReceived;
public event Action<TextMessage> TextPacketReceived;
public event Action<string> PlayerStartedSpeaking;
public event Action<string> PlayerStoppedSpeaking;
public event Action<RoomEvent> PlayerEnteredRoom;
public event Action<RoomEvent> PlayerExitedRoom;
private ConnectionStatus _status = ConnectionStatus.Disconnected;
private CodecSettings initSettings;
public string dissonanceId;
[HideInInspector] public DissonanceComms dissonanceComms;
private VelNetManager manager;
/// <summary>
/// listen to this if you want to send voice
/// </summary>
public Action<ArraySegment<byte>> VoiceQueued;
// Start is called before the first frame update
private void Start()
{
_status = ConnectionStatus.Connected;
dissonanceComms = GetComponent<DissonanceComms>();
manager = VelNetManager.instance;
}
public void Initialize(string playerName, Rooms rooms, PlayerChannels playerChannels, RoomChannels roomChannels, CodecSettings codecSettings)
{
dissonanceId = playerName;
initSettings = codecSettings;
dissonanceComms.ResetMicrophoneCapture();
}
public void VoiceReceived(string sender, byte[] data)
{
uint sequenceNumber = BitConverter.ToUInt32(data, 0);
VoicePacket vp = new VoicePacket(sender, ChannelPriority.Default, 1, true, new ArraySegment<byte>(data, 4, data.Length - 4), sequenceNumber);
VoicePacketReceived?.Invoke(vp);
}
public void SendText(string data, ChannelType recipientType, string recipientId)
{
Debug.Log("sending text");
}
public void SendVoice(ArraySegment<byte> data)
{
VoiceQueued?.Invoke(data);
}
public void SetPlayerJoined(string id)
{
Debug.Log("Dissonance player joined");
PlayerJoined?.Invoke(id, initSettings);
RoomEvent re = new RoomEvent
{
Joined = true,
Room = "Global",
PlayerName = id
};
PlayerEnteredRoom?.Invoke(re);
}
public void SetPlayerLeft(string id)
{
RoomEvent re = new RoomEvent
{
Joined = false,
Room = "Global",
PlayerName = id
};
PlayerExitedRoom?.Invoke(re);
// only send this event for non-local players
if (id != dissonanceId) PlayerLeft?.Invoke(id);
}
public void SetPlayerStartedSpeaking(string id)
{
PlayerStartedSpeaking?.Invoke(id);
}
public void SetPlayerStoppedSpeaking(string id)
{
PlayerStoppedSpeaking?.Invoke(id);
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5d2009d8e264649749c0315d48765749
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,251 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dissonance;
using UnityEngine;
namespace VelNet
{
/// <summary>
/// This should be added to your player object
/// </summary>
[AddComponentMenu("VelNet/Dissonance/VelNet Dissonance Player")]
public class VelNetDissonancePlayer : NetworkComponent, IDissonancePlayer
{
private VelCommsNetwork comms;
private bool isSpeaking;
private uint lastAudioId;
[Header("VelNet Dissonance Player Properties")]
public string dissonanceID = "";
//required by dissonance for spatial audio
public string PlayerId => dissonanceID;
public Vector3 Position => transform.position;
public Quaternion Rotation => transform.rotation;
public NetworkPlayerType Type => IsMine ? NetworkPlayerType.Local : NetworkPlayerType.Remote;
public bool IsTracking => true;
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>();
[Tooltip("Maximum distance to transmit voice data. 0 to always send voice to all players.")]
public float maxDistance;
private enum MessageType : byte
{
AudioData,
DissonanceId,
SpeakingState
}
// This object should not be in the scene at the start.
private void Awake()
{
comms = FindObjectOfType<VelCommsNetwork>();
if (comms == null)
{
Debug.LogError("No VelCommsNetwork found. Make sure there is one in your scene.", this);
}
}
private void OnEnable()
{
// add ourselves to the global list of all players in the scene
if (!allPlayers.Contains(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)
{
SetDissonanceID(comms.dissonanceId);
comms.VoiceQueued += SendVoiceData;
//we also need to know when other players join, so we can send the dissonance ID again
VelNetManager.instance.OnPlayerJoined += (player) =>
{
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.DissonanceId);
writer.Write(dissonanceID);
SendBytes(mem.ToArray());
};
}
}
private void SendVoiceData(ArraySegment<byte> data)
{
// need to send it
if (!IsMine) return;
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.AudioData);
writer.Write(lastAudioId++);
writer.Write(data.ToArray());
// send voice data unreliably
// SendBytes(mem.ToArray(), false);
SendBytesToGroup("voice", mem.ToArray());
}
/// <summary>
/// This sort of all initializes dissonance
/// </summary>
/// <param name="id">Dissonance ID</param>
public void SetDissonanceID(string id)
{
dissonanceID = id;
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.DissonanceId);
writer.Write(dissonanceID);
SendBytes(mem.ToArray());
comms.dissonanceComms.TrackPlayerPosition(this);
}
private void VoiceInitialized(string id)
{
dissonanceID = id;
}
private void OnDestroy()
{
comms.SetPlayerLeft(dissonanceID);
}
// Update is called once per frame
private void Update()
{
if (!IsMine) return;
// handle nearness cutoff
if (maxDistance > 0)
{
bool closePlayerListChanged = false;
foreach (VelNetDissonancePlayer p in allPlayers)
{
if (p == this)
{
continue;
}
float dist = Vector3.Distance(p.transform.position, transform.position);
if (dist < maxDistance && !closePlayers.Contains(p.Owner.userid))
{
closePlayers.Add(p.Owner.userid);
closePlayerListChanged = true;
}
else if (dist >= maxDistance && closePlayers.Contains(p.Owner.userid))
{
closePlayers.Remove(p.Owner.userid);
closePlayerListChanged = true;
}
}
if (closePlayerListChanged)
{
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
//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
{
isSpeaking = !isSpeaking;
using MemoryStream mem = new MemoryStream();
using BinaryWriter writer = new BinaryWriter(mem);
writer.Write((byte)MessageType.SpeakingState);
writer.Write(isSpeaking ? (byte)1 : (byte)0);
SendBytes(mem.ToArray());
if (!isSpeaking)
{
lastAudioId = 0;
}
}
}
public override void ReceiveBytes(byte[] message)
{
using MemoryStream mem = new MemoryStream(message);
using BinaryReader reader = new BinaryReader(mem);
byte identifier = reader.ReadByte();
switch (identifier)
{
case 0: //audio data
{
if (isSpeaking)
{
comms.VoiceReceived(dissonanceID, message.Skip(1).ToArray());
}
break;
}
case 1: //dissonance id (player joined)
{
if (dissonanceID == "") // I don't have this yet
{
dissonanceID = reader.ReadString();
// tell the comms network that this player joined the channel
comms.SetPlayerJoined(dissonanceID); // tell dissonance
comms.dissonanceComms.TrackPlayerPosition(this); // tell dissonance to track the remote player
}
break;
}
case 2: // speaking state
{
if (message[1] == 0)
{
comms.SetPlayerStoppedSpeaking(dissonanceID);
isSpeaking = false;
}
else
{
comms.SetPlayerStartedSpeaking(dissonanceID);
isSpeaking = true;
}
break;
}
}
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: c773e094326d413bb1bca7f91cbf7f8c
timeCreated: 1641506874

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Dissonance;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
@ -14,13 +15,13 @@ namespace VelNet
public Text messages;
public List<string> messageBuffer;
public Dropdown microphones;
Dissonance.DissonanceComms comms;
DissonanceComms comms;
public void HandleSend()
{
if (sendInput.text != "")
{
velNetManager.SendTo(VelNetManager.MessageType.OTHERS, sendInput.text);
VelNetManager.SendTo(VelNetManager.MessageType.OTHERS, sendInput.text);
}
}
@ -28,7 +29,7 @@ namespace VelNet
{
if (userInput.text != "")
{
velNetManager.Login(userInput.text, "nopass");
VelNetManager.Login(userInput.text, "nopass");
}
}
@ -36,14 +37,14 @@ namespace VelNet
{
if (roomInput.text != "")
{
velNetManager.Join(roomInput.text);
VelNetManager.Join(roomInput.text);
}
}
// Start is called before the first frame update
private void Start()
{
comms = FindObjectOfType<Dissonance.DissonanceComms>();
comms = FindObjectOfType<DissonanceComms>();
microphones.AddOptions(new List<string>(Microphone.devices));
velNetManager.MessageReceived += (m) =>
{

View File

@ -14,11 +14,6 @@
"url": "https://vel.engr.uga.edu"
},
"samples": [
{
"displayName": "Dissonance Integration",
"description": "Includes support for Dissonance Voice, available separately from the Unity Asset Store.",
"path": "Samples~/DissonanceIntegration"
},
{
"displayName": "Example",
"description": "Example Scene",

View File

@ -8,6 +8,7 @@
"com.unity.textmeshpro": "3.0.6",
"com.unity.timeline": "1.4.8",
"com.unity.ugui": "1.0.0",
"edu.uga.engr.vel.velnet.dissonance": "file:S:/git_repo/VelNetDissonanceIntegration",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",

View File

@ -105,6 +105,14 @@
"source": "embedded",
"dependencies": {}
},
"edu.uga.engr.vel.velnet.dissonance": {
"version": "file:S:/git_repo/VelNetDissonanceIntegration",
"depth": 0,
"source": "local",
"dependencies": {
"edu.uga.engr.vel.velnet": "1.0.4"
}
},
"com.unity.modules.ai": {
"version": "1.0.0",
"depth": 0,

View File

@ -6,6 +6,6 @@ EditorBuildSettings:
serializedVersion: 2
m_Scenes:
- enabled: 1
path: Assets/VelGameServer/Example/test.unity
path: Assets/Samples/VelNet/1.0.4/Example/test.unity
guid: e4e43899246c941c78acfc59ce2f664a
m_configObjects: {}