reorganized into a package, added a namespace, added an assemblydefinition, attempt at ci for upm branch creation
commit
887d310053
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 453f243ca8f3d8b4db4a1db0d9f9d300
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 63ae5231117a1484198ba0a8f681612b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,522 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace VelNetUnity
|
||||||
|
{
|
||||||
|
public class NetworkManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
public enum MessageType
|
||||||
|
{
|
||||||
|
OTHERS = 0,
|
||||||
|
ALL = 1,
|
||||||
|
OTHERS_ORDERED = 2,
|
||||||
|
ALL_ORDERED = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
public string host;
|
||||||
|
public int port;
|
||||||
|
|
||||||
|
#region private members
|
||||||
|
|
||||||
|
private TcpClient socketConnection;
|
||||||
|
private Socket udpSocket;
|
||||||
|
public bool udpConnected = false;
|
||||||
|
IPEndPoint RemoteEndPoint;
|
||||||
|
private Thread clientReceiveThread;
|
||||||
|
private Thread clientReceiveThreadUDP;
|
||||||
|
public int userid = -1;
|
||||||
|
public string room;
|
||||||
|
int messagesReceived = 0;
|
||||||
|
|
||||||
|
public GameObject playerPrefab;
|
||||||
|
public Dictionary<int, NetworkPlayer> players = new Dictionary<int, NetworkPlayer>();
|
||||||
|
|
||||||
|
public Action<NetworkPlayer> onJoinedRoom = delegate { };
|
||||||
|
public Action<NetworkPlayer> onPlayerJoined = delegate { };
|
||||||
|
public Action<NetworkPlayer> onPlayerLeft = delegate { };
|
||||||
|
|
||||||
|
public List<NetworkObject> prefabs = new List<NetworkObject>();
|
||||||
|
public NetworkObject[] sceneObjects;
|
||||||
|
public List<string> deletedSceneObjects = new List<string>();
|
||||||
|
public Dictionary<string, NetworkObject> objects = new Dictionary<string, NetworkObject>(); //maintains a list of all known objects on the server (ones that have ids)
|
||||||
|
NetworkPlayer masterPlayer = null;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// Use this for initialization
|
||||||
|
public class Message
|
||||||
|
{
|
||||||
|
public int type;
|
||||||
|
public string text;
|
||||||
|
public int sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Message> receivedMessages = new List<Message>();
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
ConnectToTcpServer();
|
||||||
|
sceneObjects = FindObjectsOfType<NetworkObject>(); //add all local network objects
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void addMessage(Message m)
|
||||||
|
{
|
||||||
|
lock (receivedMessages)
|
||||||
|
{
|
||||||
|
//Debug.Log(messagesReceived++);
|
||||||
|
receivedMessages.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
lock (receivedMessages)
|
||||||
|
{
|
||||||
|
//the main thread, which can do Unity stuff
|
||||||
|
foreach (Message m in receivedMessages)
|
||||||
|
{
|
||||||
|
if (m.type == 0) //when you join the server
|
||||||
|
{
|
||||||
|
userid = m.sender;
|
||||||
|
Debug.Log("joined server");
|
||||||
|
|
||||||
|
//start the udp thread
|
||||||
|
clientReceiveThreadUDP = new Thread(new ThreadStart(ListenForDataUDP));
|
||||||
|
clientReceiveThreadUDP.IsBackground = true;
|
||||||
|
clientReceiveThreadUDP.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.type == 2)
|
||||||
|
{
|
||||||
|
//if this message is for me, that means I joined a new room...
|
||||||
|
if (userid == m.sender)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<int, NetworkPlayer> kvp in players)
|
||||||
|
{
|
||||||
|
Destroy(kvp.Value.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
players.Clear(); //we clear the list, but will recreate as we get messages from people in our room
|
||||||
|
|
||||||
|
if (m.text != "")
|
||||||
|
{
|
||||||
|
NetworkPlayer player = Instantiate<GameObject>(playerPrefab).GetComponent<NetworkPlayer>();
|
||||||
|
|
||||||
|
player.isLocal = true;
|
||||||
|
player.userid = m.sender;
|
||||||
|
players.Add(userid, player);
|
||||||
|
player.room = m.text;
|
||||||
|
player.manager = this;
|
||||||
|
onJoinedRoom(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //not for me, a player is joining or leaving
|
||||||
|
{
|
||||||
|
NetworkPlayer me = players[userid];
|
||||||
|
|
||||||
|
if (me.room != m.text)
|
||||||
|
{
|
||||||
|
//we got a left message, kill it
|
||||||
|
//change ownership of all objects to master
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, NetworkObject> kvp in objects)
|
||||||
|
{
|
||||||
|
if (kvp.Value.owner == players[m.sender]) //the owner is the player that left
|
||||||
|
{
|
||||||
|
if (me.isLocal && me == masterPlayer) //I'm the local master player, so can take ownership immediately
|
||||||
|
{
|
||||||
|
me.takeOwnership(kvp.Key);
|
||||||
|
}
|
||||||
|
else if (players[m.sender] == masterPlayer) //the master player left, so everyone should set the owner null (we should get a new master shortly)
|
||||||
|
{
|
||||||
|
kvp.Value.owner = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Destroy(players[m.sender].gameObject);
|
||||||
|
players.Remove(m.sender);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//we got a join mesage, create it
|
||||||
|
NetworkPlayer player = Instantiate<GameObject>(playerPrefab).GetComponent<NetworkPlayer>();
|
||||||
|
player.isLocal = false;
|
||||||
|
player.room = m.text;
|
||||||
|
player.userid = m.sender;
|
||||||
|
player.manager = this;
|
||||||
|
players.Add(m.sender, player);
|
||||||
|
onPlayerJoined(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.type == 3) //generic message
|
||||||
|
{
|
||||||
|
players[m.sender]?.handleMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.type == 4) //change master player (this should only happen when the first player joins or if the master player leaves)
|
||||||
|
{
|
||||||
|
if (masterPlayer == null)
|
||||||
|
{
|
||||||
|
masterPlayer = players[m.sender];
|
||||||
|
|
||||||
|
//no master player yet, add the scene objects
|
||||||
|
|
||||||
|
for (int i = 0; i < sceneObjects.Length; i++)
|
||||||
|
{
|
||||||
|
sceneObjects[i].networkId = -1 + "-" + i;
|
||||||
|
sceneObjects[i].owner = masterPlayer;
|
||||||
|
sceneObjects[i].isSceneObject = true; //needed for special handling when deleted
|
||||||
|
objects.Add(sceneObjects[i].networkId, sceneObjects[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
masterPlayer = players[m.sender];
|
||||||
|
}
|
||||||
|
|
||||||
|
masterPlayer.setAsMasterPlayer();
|
||||||
|
|
||||||
|
//master player should take over any objects that do not have an owner
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, NetworkObject> kvp in objects)
|
||||||
|
{
|
||||||
|
if (kvp.Value.owner == null)
|
||||||
|
{
|
||||||
|
kvp.Value.owner = masterPlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageReceived(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
receivedMessages.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
socketConnection.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<string, int> joinedRoom = delegate { };
|
||||||
|
public Action<Message> messageReceived = delegate { };
|
||||||
|
public Action<string, int> loggedIn = delegate { };
|
||||||
|
public Action<string[], int> roomsReceived = delegate { };
|
||||||
|
|
||||||
|
public bool connected = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Setup socket connection.
|
||||||
|
/// </summary>
|
||||||
|
private void ConnectToTcpServer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientReceiveThread = new Thread(new ThreadStart(ListenForData));
|
||||||
|
clientReceiveThread.IsBackground = true;
|
||||||
|
clientReceiveThread.Start();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.Log("On client connect exception " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleMessage(string s) //this parses messages from the server, and adds them to a queue to be processed on the main thread
|
||||||
|
{
|
||||||
|
Message m = new Message();
|
||||||
|
string[] sections = s.Split(':');
|
||||||
|
if (sections.Length > 0)
|
||||||
|
{
|
||||||
|
int type = int.Parse(sections[0]);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 0: //logged in message
|
||||||
|
{
|
||||||
|
if (sections.Length > 1)
|
||||||
|
{
|
||||||
|
m.type = type;
|
||||||
|
m.sender = int.Parse(sections[1]);
|
||||||
|
m.text = "";
|
||||||
|
addMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: //room info message
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: //joined room message
|
||||||
|
{
|
||||||
|
if (sections.Length > 2)
|
||||||
|
{
|
||||||
|
m.type = 2;
|
||||||
|
int user_id = int.Parse(sections[1]);
|
||||||
|
m.sender = user_id;
|
||||||
|
string new_room = sections[2];
|
||||||
|
m.text = new_room;
|
||||||
|
|
||||||
|
addMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: //text message
|
||||||
|
{
|
||||||
|
if (sections.Length > 2)
|
||||||
|
{
|
||||||
|
m.type = 3;
|
||||||
|
m.sender = int.Parse(sections[1]);
|
||||||
|
m.text = sections[2];
|
||||||
|
addMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: //change master client
|
||||||
|
{
|
||||||
|
if (sections.Length > 1)
|
||||||
|
{
|
||||||
|
m.type = 4;
|
||||||
|
m.sender = int.Parse(sections[1]);
|
||||||
|
addMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs in background clientReceiveThread; Listens for incomming data.
|
||||||
|
/// </summary>
|
||||||
|
private void ListenForData()
|
||||||
|
{
|
||||||
|
connected = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
socketConnection = new TcpClient(host, port);
|
||||||
|
socketConnection.NoDelay = true;
|
||||||
|
Byte[] bytes = new Byte[1024];
|
||||||
|
string partialMessage = "";
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Get a stream object for reading
|
||||||
|
using (NetworkStream stream = socketConnection.GetStream())
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
// Read incomming stream into byte arrary.
|
||||||
|
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
|
||||||
|
{
|
||||||
|
var incommingData = new byte[length];
|
||||||
|
Array.Copy(bytes, 0, incommingData, 0, length);
|
||||||
|
// Convert byte array to string message.
|
||||||
|
string serverMessage = Encoding.ASCII.GetString(incommingData);
|
||||||
|
string[] sections = serverMessage.Split('\n');
|
||||||
|
if (sections.Length > 1)
|
||||||
|
{
|
||||||
|
lock (receivedMessages)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sections.Length - 1; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
handleMessage(partialMessage + sections[0]);
|
||||||
|
partialMessage = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handleMessage(sections[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partialMessage = partialMessage + sections[sections.Length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
catch (Exception socketException)
|
||||||
|
{
|
||||||
|
Debug.Log("Socket exception: " + socketException);
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ListenForDataUDP()
|
||||||
|
{
|
||||||
|
//I don't yet have a UDP connection
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var addresses = Dns.GetHostAddresses(host);
|
||||||
|
Debug.Assert(addresses.Length > 0);
|
||||||
|
RemoteEndPoint = new IPEndPoint(addresses[0], port);
|
||||||
|
|
||||||
|
|
||||||
|
udpSocket = new Socket(AddressFamily.InterNetwork,
|
||||||
|
SocketType.Dgram, ProtocolType.Udp);
|
||||||
|
|
||||||
|
|
||||||
|
udpConnected = false;
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
string welcome = userid + ":0:Hello";
|
||||||
|
byte[] data = Encoding.ASCII.GetBytes(welcome);
|
||||||
|
udpSocket.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
|
||||||
|
|
||||||
|
if (udpSocket.Available == 0)
|
||||||
|
{
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Debug.Log("Waiting for UDP response");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
udpConnected = true;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int numReceived = udpSocket.Receive(buffer);
|
||||||
|
|
||||||
|
string message = Encoding.UTF8.GetString(buffer, 0, numReceived);
|
||||||
|
|
||||||
|
string[] sections = message.Split(':');
|
||||||
|
if (sections[0] == "0")
|
||||||
|
{
|
||||||
|
Debug.Log("UDP connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sections[0] == "3")
|
||||||
|
{
|
||||||
|
handleMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception socketException)
|
||||||
|
{
|
||||||
|
Debug.Log("Socket exception: " + socketException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendUdpMessage(string message)
|
||||||
|
{
|
||||||
|
if (udpSocket == null || !udpConnected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = Encoding.UTF8.GetBytes(message);
|
||||||
|
//Debug.Log("Attempting to send: " + message);
|
||||||
|
udpSocket.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send message to server using socket connection.
|
||||||
|
/// </summary>
|
||||||
|
private void SendNetworkMessage(string clientMessage)
|
||||||
|
{
|
||||||
|
if (socketConnection == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Get a stream object for writing.
|
||||||
|
NetworkStream stream = socketConnection.GetStream();
|
||||||
|
if (stream.CanWrite)
|
||||||
|
{
|
||||||
|
// Convert string message to byte array.
|
||||||
|
clientMessage = clientMessage + "\n"; //append a new line to delineate the message
|
||||||
|
byte[] clientMessageAsByteArray = Encoding.ASCII.GetBytes(clientMessage);
|
||||||
|
// Write byte array to socketConnection stream.
|
||||||
|
stream.Write(clientMessageAsByteArray, 0, clientMessageAsByteArray.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SocketException socketException)
|
||||||
|
{
|
||||||
|
Debug.Log("Socket exception: " + socketException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void login(string username, string password)
|
||||||
|
{
|
||||||
|
SendNetworkMessage("0:" + username + ":" + password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void join(string roomname)
|
||||||
|
{
|
||||||
|
SendNetworkMessage("2:" + roomname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void leave()
|
||||||
|
{
|
||||||
|
SendNetworkMessage("2:-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendTo(MessageType type, string message, bool reliable = true)
|
||||||
|
{
|
||||||
|
if (reliable)
|
||||||
|
{
|
||||||
|
SendNetworkMessage("3:" + (int)type + ":" + message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendUdpMessage(userid + ":3:" + (int)type + ":" + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendToGroup(string group, string message, bool reliable = true)
|
||||||
|
{
|
||||||
|
if (reliable)
|
||||||
|
{
|
||||||
|
SendNetworkMessage("4:" + group + ":" + message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendUdpMessage(userid + ":4:" + group + ":" + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//changes the designated group that sendto(4) will go to
|
||||||
|
public void setupMessageGroup(string groupname, int[] userids)
|
||||||
|
{
|
||||||
|
SendNetworkMessage("5:" + groupname + ":" + String.Join(":", userids));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteNetworkObject(string networkId)
|
||||||
|
{
|
||||||
|
if (objects.ContainsKey(networkId))
|
||||||
|
{
|
||||||
|
NetworkObject obj = objects[networkId];
|
||||||
|
if (obj.isSceneObject)
|
||||||
|
{
|
||||||
|
deletedSceneObjects.Add(networkId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Destroy(obj.gameObject);
|
||||||
|
objects.Remove(networkId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 03a4d4e1a7fd74c7ab2eccca4ce168db
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace VelNetUnity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is a base class for all objects that a player can instantiated/owned
|
||||||
|
/// </summary>
|
||||||
|
public abstract class NetworkObject : MonoBehaviour
|
||||||
|
{
|
||||||
|
public NetworkPlayer owner;
|
||||||
|
public string networkId; //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
|
||||||
|
public string prefabName; //this may be empty if it's not a prefab (scene object)
|
||||||
|
public bool isSceneObject = false;
|
||||||
|
public abstract void handleMessage(string identifier, byte[] message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dd77ffdf919cc444f863d7bf0cda29ea
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
namespace VelNetUnity
|
||||||
|
{
|
||||||
|
[RequireComponent(typeof(NetworkObject))]
|
||||||
|
public class NetworkPlayer : MonoBehaviour
|
||||||
|
{
|
||||||
|
public NetworkObject myObject;
|
||||||
|
public int userid;
|
||||||
|
public string username;
|
||||||
|
|
||||||
|
public string room;
|
||||||
|
public NetworkManager manager;
|
||||||
|
|
||||||
|
public bool isLocal = false;
|
||||||
|
|
||||||
|
public int lastObjectId = 0; //for instantiation
|
||||||
|
|
||||||
|
|
||||||
|
private bool isMaster = false;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
myObject.owner = this;
|
||||||
|
manager = FindObjectOfType<NetworkManager>();
|
||||||
|
manager.onPlayerJoined += handlePlayerJoined;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handlePlayerJoined(NetworkPlayer 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 (isLocal)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, NetworkObject> kvp in manager.objects)
|
||||||
|
{
|
||||||
|
if (kvp.Value.owner == this && kvp.Value.prefabName != "")
|
||||||
|
{
|
||||||
|
manager.sendTo(NetworkManager.MessageType.OTHERS, "7," + kvp.Value.networkId + "," + kvp.Value.prefabName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMaster)
|
||||||
|
{
|
||||||
|
//send a list of scene object ids when someone joins
|
||||||
|
sendSceneUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handleMessage(NetworkManager.Message m)
|
||||||
|
{
|
||||||
|
//these are generally things that come from the "owner" and should be enacted locally, where appropriate
|
||||||
|
//we need to parse the message
|
||||||
|
|
||||||
|
//types of messages
|
||||||
|
string[] messages = m.text.Split(';'); //messages are split by ;
|
||||||
|
for (int i = 0; i < messages.Length; i++)
|
||||||
|
{
|
||||||
|
//individual message parameters separated by comma
|
||||||
|
string[] sections = messages[i].Split(',');
|
||||||
|
|
||||||
|
switch (sections[0])
|
||||||
|
{
|
||||||
|
case "1": //update my object's data
|
||||||
|
{
|
||||||
|
string identifier = sections[1];
|
||||||
|
byte[] message = Convert.FromBase64String(sections[2]);
|
||||||
|
myObject.handleMessage(identifier, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "5": //sync update for an object I may own
|
||||||
|
{
|
||||||
|
string objectKey = sections[1];
|
||||||
|
string identifier = sections[2];
|
||||||
|
string syncMessage = sections[3];
|
||||||
|
byte[] messageBytes = Convert.FromBase64String(syncMessage);
|
||||||
|
if (manager.objects.ContainsKey(objectKey))
|
||||||
|
{
|
||||||
|
if (manager.objects[objectKey].owner == this)
|
||||||
|
{
|
||||||
|
manager.objects[objectKey].handleMessage(identifier, messageBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "6": //I'm trying to take ownership of an object
|
||||||
|
{
|
||||||
|
string networkId = sections[1];
|
||||||
|
|
||||||
|
if (manager.objects.ContainsKey(networkId))
|
||||||
|
{
|
||||||
|
manager.objects[networkId].owner = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "7": //I'm trying to instantiate an object
|
||||||
|
{
|
||||||
|
string networkId = sections[1];
|
||||||
|
string prefabName = sections[2];
|
||||||
|
if (manager.objects.ContainsKey(networkId))
|
||||||
|
{
|
||||||
|
break; //we already have this one, ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkObject temp = manager.prefabs.Find((prefab) => prefab.name == prefabName);
|
||||||
|
if (temp != null)
|
||||||
|
{
|
||||||
|
NetworkObject instance = Instantiate<NetworkObject>(temp);
|
||||||
|
instance.networkId = networkId;
|
||||||
|
instance.prefabName = prefabName;
|
||||||
|
instance.owner = this;
|
||||||
|
manager.objects.Add(instance.networkId, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "8": //I'm trying to destroy a gameobject I own
|
||||||
|
{
|
||||||
|
string networkId = sections[1];
|
||||||
|
|
||||||
|
manager.deleteNetworkObject(networkId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "9": //deleted scene objects
|
||||||
|
{
|
||||||
|
for (int k = 1; k < sections.Length; k++)
|
||||||
|
{
|
||||||
|
manager.deleteNetworkObject(sections[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsMasterPlayer()
|
||||||
|
{
|
||||||
|
isMaster = true;
|
||||||
|
//if I'm master, I'm now responsible for updating all scene objects
|
||||||
|
//FindObjectsOfType<NetworkObject>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendGroupMessage(NetworkObject obj, string group, string identifier, byte[] data, bool reliable = true)
|
||||||
|
{
|
||||||
|
if (obj == myObject)
|
||||||
|
{
|
||||||
|
manager.sendToGroup(group, "1," + identifier + "," + Convert.ToBase64String(data), reliable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
manager.sendToGroup(group, "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data), reliable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMessage(NetworkObject obj, string identifier, byte[] data, bool reliable = true)
|
||||||
|
{
|
||||||
|
if (obj == myObject)
|
||||||
|
{
|
||||||
|
manager.sendTo(NetworkManager.MessageType.OTHERS, "1," + identifier + "," + Convert.ToBase64String(data), reliable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
manager.sendTo(NetworkManager.MessageType.OTHERS, "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data), reliable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkObject networkInstantiate(string prefabName)
|
||||||
|
{
|
||||||
|
if (!isLocal)
|
||||||
|
{
|
||||||
|
return null; //must be the local player to call instantiate
|
||||||
|
}
|
||||||
|
|
||||||
|
string networkId = userid + "-" + lastObjectId++;
|
||||||
|
|
||||||
|
|
||||||
|
NetworkObject temp = manager.prefabs.Find((prefab) => prefab.name == prefabName);
|
||||||
|
if (temp != null)
|
||||||
|
{
|
||||||
|
NetworkObject instance = Instantiate<NetworkObject>(temp);
|
||||||
|
instance.networkId = networkId;
|
||||||
|
instance.prefabName = prefabName;
|
||||||
|
instance.owner = this;
|
||||||
|
manager.objects.Add(instance.networkId, instance);
|
||||||
|
|
||||||
|
manager.sendTo(NetworkManager.MessageType.OTHERS, "7," + networkId + "," + prefabName); //only sent to others, as I already instantiated this. Nice that it happens immediately.
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void networkDestroy(string networkId)
|
||||||
|
{
|
||||||
|
if (!manager.objects.ContainsKey(networkId) || manager.objects[networkId].owner != this || !isLocal) return; //must be the local owner of the object to destroy it
|
||||||
|
manager.sendTo(NetworkManager.MessageType.ALL_ORDERED, "8," + networkId); //send to all, which will make me delete as well
|
||||||
|
}
|
||||||
|
|
||||||
|
public void takeOwnership(string networkId)
|
||||||
|
{
|
||||||
|
if (!manager.objects.ContainsKey(networkId) || !isLocal) return; //must exist and be the the local player
|
||||||
|
|
||||||
|
manager.objects[networkId].owner = this; //immediately successful
|
||||||
|
manager.sendTo(NetworkManager.MessageType.ALL_ORDERED, "6," + networkId); //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.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendSceneUpdate()
|
||||||
|
{
|
||||||
|
manager.sendTo(NetworkManager.MessageType.OTHERS, "9," + string.Join(",", manager.deletedSceneObjects));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d8d3b6de660834e3e898725928251405
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cd6bc3db2c19417498a737fbb79e8c7d
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
|
namespace VelNetUnity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A simple class that will sync the position and rotation of a network object
|
||||||
|
/// </summary>
|
||||||
|
public class SyncTransform : NetworkObject
|
||||||
|
{
|
||||||
|
public Vector3 targetPosition;
|
||||||
|
public Quaternion targetRotation;
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] getSyncMessage()
|
||||||
|
{
|
||||||
|
float[] data = new float[7];
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
data[i] = transform.position[i];
|
||||||
|
data[i + 3] = transform.rotation[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
data[6] = transform.rotation[3];
|
||||||
|
|
||||||
|
byte[] toReturn = new byte[sizeof(float) * data.Length];
|
||||||
|
Buffer.BlockCopy(data, 0, toReturn, 0, toReturn.Length);
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void handleMessage(string identifier, byte[] message)
|
||||||
|
{
|
||||||
|
switch (identifier)
|
||||||
|
{
|
||||||
|
case "s":
|
||||||
|
float[] data = new float[7];
|
||||||
|
Buffer.BlockCopy(message, 0, data, 0, message.Length);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
targetPosition[i] = data[i];
|
||||||
|
targetRotation[i] = data[i + 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
targetRotation[3] = data[6];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is called before the first frame update
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
StartCoroutine(syncBehavior());
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f1f9b0bbd93a484a987c51f1107ebe5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
%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: {}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fa1da19d935e241119cdd522ceae772c
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 24100000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dissonance;
|
||||||
|
using Dissonance.Extensions;
|
||||||
|
using Dissonance.Networking;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
|
public class VelCommsNetwork : MonoBehaviour, ICommsNetwork
|
||||||
|
{
|
||||||
|
public ConnectionStatus Status
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return manager.connected?ConnectionStatus.Connected:ConnectionStatus.Disconnected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkMode Mode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 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;
|
||||||
|
|
||||||
|
ConnectionStatus _status = ConnectionStatus.Disconnected;
|
||||||
|
CodecSettings initSettings;
|
||||||
|
public string dissonanceId;
|
||||||
|
public DissonanceComms comms;
|
||||||
|
public NetworkManager manager;
|
||||||
|
|
||||||
|
public Action<ArraySegment<byte>> voiceQueued = delegate { }; //listen to this if you want to send voice
|
||||||
|
|
||||||
|
public void Initialize(string playerName, Rooms rooms, PlayerChannels playerChannels, RoomChannels roomChannels, CodecSettings codecSettings)
|
||||||
|
{
|
||||||
|
dissonanceId = playerName;
|
||||||
|
initSettings = codecSettings;
|
||||||
|
comms.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(vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendText(string data, ChannelType recipientType, string recipientId)
|
||||||
|
{
|
||||||
|
Debug.Log("sending text");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendVoice(ArraySegment<byte> data)
|
||||||
|
{
|
||||||
|
voiceQueued(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is called before the first frame update
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
_status = ConnectionStatus.Connected;
|
||||||
|
comms = GetComponent<DissonanceComms>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playerJoined(string id)
|
||||||
|
{
|
||||||
|
Debug.Log("dissonance player joined");
|
||||||
|
PlayerJoined(id, initSettings);
|
||||||
|
RoomEvent re = new RoomEvent();
|
||||||
|
re.Joined = true;
|
||||||
|
re.Room = "Global";
|
||||||
|
re.PlayerName = id;
|
||||||
|
PlayerEnteredRoom(re);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playerLeft(string id)
|
||||||
|
{
|
||||||
|
RoomEvent re = new RoomEvent();
|
||||||
|
re.Joined = false;
|
||||||
|
re.Room = "Global";
|
||||||
|
re.PlayerName = id;
|
||||||
|
PlayerExitedRoom(re);
|
||||||
|
PlayerLeft(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playerStartedSpeaking(string id)
|
||||||
|
{
|
||||||
|
PlayerStartedSpeaking(id);
|
||||||
|
}
|
||||||
|
public void playerStoppedSpeaking(string id)
|
||||||
|
{
|
||||||
|
PlayerStoppedSpeaking(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5d2009d8e264649749c0315d48765749
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
public class NetworkGUI : MonoBehaviour
|
||||||
|
{
|
||||||
|
public NetworkManager networkManager;
|
||||||
|
public InputField userInput;
|
||||||
|
public InputField sendInput;
|
||||||
|
public InputField roomInput;
|
||||||
|
public Text messages;
|
||||||
|
public List<string> messageBuffer;
|
||||||
|
public Dropdown microphones;
|
||||||
|
Dissonance.DissonanceComms comms;
|
||||||
|
public void handleSend()
|
||||||
|
{
|
||||||
|
if(sendInput.text != "")
|
||||||
|
{
|
||||||
|
networkManager.sendTo(NetworkManager.MessageType.OTHERS,sendInput.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void handleLogin()
|
||||||
|
{
|
||||||
|
if(userInput.text != "")
|
||||||
|
{
|
||||||
|
networkManager.login(userInput.text, "nopass");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void handleJoin()
|
||||||
|
{
|
||||||
|
if(roomInput.text != "")
|
||||||
|
{
|
||||||
|
|
||||||
|
networkManager.join(roomInput.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is called before the first frame update
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
comms = GameObject.FindObjectOfType<Dissonance.DissonanceComms>();
|
||||||
|
microphones.AddOptions(new List<string>(Microphone.devices));
|
||||||
|
networkManager.messageReceived += (m) => {
|
||||||
|
string s = m.type + ":" + m.sender +":" + m.text;
|
||||||
|
messageBuffer.Add(s);
|
||||||
|
messages.text = "";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(messageBuffer.Count > 10)
|
||||||
|
{
|
||||||
|
messageBuffer.RemoveAt(0);
|
||||||
|
}
|
||||||
|
for(int i = 0; i < messageBuffer.Count; i++)
|
||||||
|
{
|
||||||
|
messages.text = messages.text + messageBuffer[i] + "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleMicrophoneSelection()
|
||||||
|
{
|
||||||
|
comms.MicrophoneName = microphones.options[microphones.value].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7a7db5bc792cd471dbd8039664359eee
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using Dissonance;
|
||||||
|
using System.Text;
|
||||||
|
public class PlayerController : NetworkObject, Dissonance.IDissonancePlayer
|
||||||
|
{
|
||||||
|
VelCommsNetwork comms;
|
||||||
|
bool isSpeaking = false;
|
||||||
|
uint lastAudioId = 0;
|
||||||
|
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 => this.owner.isLocal ? NetworkPlayerType.Local : NetworkPlayerType.Remote;
|
||||||
|
public bool IsTracking => true;
|
||||||
|
|
||||||
|
public Vector3 targetPosition;
|
||||||
|
public Quaternion targetRotation;
|
||||||
|
|
||||||
|
public List<int> closePlayers = new List<int>();
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] getSyncMessage()
|
||||||
|
{
|
||||||
|
float[] data = new float[7];
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
data[i] = transform.position[i];
|
||||||
|
data[i + 3] = transform.rotation[i];
|
||||||
|
}
|
||||||
|
data[6] = transform.rotation[3];
|
||||||
|
|
||||||
|
byte[] toReturn = new byte[sizeof(float) * data.Length];
|
||||||
|
Buffer.BlockCopy(data, 0, toReturn, 0, toReturn.Length);
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void handleMessage(string identifier, byte[] message)
|
||||||
|
{
|
||||||
|
switch (identifier)
|
||||||
|
{
|
||||||
|
case "s": //sync message
|
||||||
|
float[] data = new float[7];
|
||||||
|
Buffer.BlockCopy(message, 0, data, 0, message.Length);
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
targetPosition[i] = data[i];
|
||||||
|
targetRotation[i] = data[i + 3];
|
||||||
|
}
|
||||||
|
targetRotation[3] = data[6];
|
||||||
|
break;
|
||||||
|
case "a": //audio data
|
||||||
|
{
|
||||||
|
if (isSpeaking)
|
||||||
|
{
|
||||||
|
comms.voiceReceived(dissonanceID, message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "d": //dissonance id (player joined)
|
||||||
|
{
|
||||||
|
if (dissonanceID == "") //I don't have this yet
|
||||||
|
{
|
||||||
|
dissonanceID = Encoding.UTF8.GetString(message);
|
||||||
|
//tell the comms network that this player joined the channel
|
||||||
|
comms.playerJoined(dissonanceID); //tell dissonance
|
||||||
|
comms.comms.TrackPlayerPosition(this); //tell dissonance to track the remote player
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "x": //speaking state
|
||||||
|
{
|
||||||
|
if (message[0]==0)
|
||||||
|
{
|
||||||
|
comms.playerStoppedSpeaking(dissonanceID);
|
||||||
|
isSpeaking = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
comms.playerStartedSpeaking(dissonanceID);
|
||||||
|
isSpeaking = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is called before the first frame update
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
//handle dissonance stuff
|
||||||
|
comms = GameObject.FindObjectOfType<VelCommsNetwork>();
|
||||||
|
if(comms != null)
|
||||||
|
{
|
||||||
|
if (owner.isLocal)
|
||||||
|
{
|
||||||
|
setDissonanceID(comms.dissonanceId);
|
||||||
|
comms.voiceQueued += sendVoiceData;
|
||||||
|
|
||||||
|
//we also need to know when other players join, so we can send the dissonance ID again
|
||||||
|
|
||||||
|
owner.manager.onPlayerJoined += (player) =>
|
||||||
|
{
|
||||||
|
byte[] b = Encoding.UTF8.GetBytes(dissonanceID);
|
||||||
|
owner.sendMessage(this, "d", b);
|
||||||
|
};
|
||||||
|
owner.manager.setupMessageGroup("close", closePlayers.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (owner.isLocal)
|
||||||
|
{
|
||||||
|
StartCoroutine(syncBehavior());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendVoiceData(ArraySegment<byte> data)
|
||||||
|
{
|
||||||
|
//need to send it
|
||||||
|
if(owner != null && owner.isLocal)
|
||||||
|
{
|
||||||
|
byte[] toSend = new byte[data.Count+4];
|
||||||
|
byte[] lastAudioIdBytes = BitConverter.GetBytes(lastAudioId++);
|
||||||
|
Buffer.BlockCopy(lastAudioIdBytes, 0, toSend, 0, 4);
|
||||||
|
Buffer.BlockCopy(data.Array, data.Offset, toSend, 4, data.Count);
|
||||||
|
owner.sendGroupMessage(this,"close", "a", toSend, false); //send voice data unreliably
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDissonanceID(string id) //this sort of all initializes dissonance
|
||||||
|
{
|
||||||
|
dissonanceID = id;
|
||||||
|
byte[] b = Encoding.UTF8.GetBytes(dissonanceID);
|
||||||
|
owner.sendMessage(this, "d", b);
|
||||||
|
comms.comms.TrackPlayerPosition(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void voiceInitialized(string id)
|
||||||
|
{
|
||||||
|
dissonanceID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
comms.playerLeft(dissonanceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IEnumerator syncBehavior()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
owner.sendMessage(this, "s", getSyncMessage());
|
||||||
|
yield return new WaitForSeconds(.1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (owner != null && owner.isLocal) {
|
||||||
|
|
||||||
|
PlayerController[] players = GameObject.FindObjectsOfType<PlayerController>();
|
||||||
|
bool shouldUpdate = false;
|
||||||
|
for (int i = 0; i < players.Length; i++)
|
||||||
|
{
|
||||||
|
if (players[i] == this) { continue; }
|
||||||
|
float dist = Vector3.Distance(players[i].transform.position, this.transform.position);
|
||||||
|
if (dist < 2 && !closePlayers.Contains(players[i].owner.userid))
|
||||||
|
{
|
||||||
|
closePlayers.Add(players[i].owner.userid);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
else if(dist >=2 && closePlayers.Contains(players[i].owner.userid))
|
||||||
|
{
|
||||||
|
closePlayers.Remove(players[i].owner.userid);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldUpdate)
|
||||||
|
{
|
||||||
|
owner.manager.setupMessageGroup("close", closePlayers.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (owner != null && !owner.isLocal)
|
||||||
|
{
|
||||||
|
transform.position = Vector3.Lerp(transform.position, targetPosition, .1f);
|
||||||
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, .1f);
|
||||||
|
}
|
||||||
|
else if(owner != null && owner.isLocal)
|
||||||
|
{
|
||||||
|
|
||||||
|
//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
|
||||||
|
{
|
||||||
|
isSpeaking = !isSpeaking;
|
||||||
|
byte[] toSend = new byte[1];
|
||||||
|
toSend[0] = isSpeaking ? (byte)1 : (byte)0;
|
||||||
|
owner.sendMessage(this, "x", toSend);
|
||||||
|
|
||||||
|
if (!isSpeaking)
|
||||||
|
{
|
||||||
|
lastAudioId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Vector3 movement = new Vector3();
|
||||||
|
movement.x += Input.GetAxis("Horizontal");
|
||||||
|
movement.y += Input.GetAxis("Vertical");
|
||||||
|
movement.z = 0;
|
||||||
|
transform.Translate(movement * Time.deltaTime);
|
||||||
|
|
||||||
|
if (Input.GetKeyDown(KeyCode.Space))
|
||||||
|
{
|
||||||
|
owner.networkInstantiate("TestNetworkedGameObject");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKeyDown(KeyCode.BackQuote))
|
||||||
|
{
|
||||||
|
foreach(KeyValuePair<string,NetworkObject> kvp in owner.manager.objects)
|
||||||
|
{
|
||||||
|
owner.takeOwnership(kvp.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Input.GetKeyDown(KeyCode.Backspace))
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, NetworkObject> kvp in owner.manager.objects)
|
||||||
|
{
|
||||||
|
owner.networkDestroy(kvp.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 89e3af759df774692a566a166b4bf69b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &6139051692386484099
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 3076416102083120807}
|
||||||
|
- component: {fileID: 8527011532923434593}
|
||||||
|
- component: {fileID: 6854617867369839}
|
||||||
|
- component: {fileID: 5845716565458182149}
|
||||||
|
- component: {fileID: 5713671764962751473}
|
||||||
|
- component: {fileID: -4404668399269848200}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: PlayerPrefab
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &3076416102083120807
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6139051692386484099}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!33 &8527011532923434593
|
||||||
|
MeshFilter:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6139051692386484099}
|
||||||
|
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
--- !u!23 &6854617867369839
|
||||||
|
MeshRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6139051692386484099}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_CastShadows: 1
|
||||||
|
m_ReceiveShadows: 1
|
||||||
|
m_DynamicOccludee: 1
|
||||||
|
m_MotionVectors: 1
|
||||||
|
m_LightProbeUsage: 1
|
||||||
|
m_ReflectionProbeUsage: 1
|
||||||
|
m_RayTracingMode: 2
|
||||||
|
m_RayTraceProcedural: 0
|
||||||
|
m_RenderingLayerMask: 1
|
||||||
|
m_RendererPriority: 0
|
||||||
|
m_Materials:
|
||||||
|
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
||||||
|
m_StaticBatchInfo:
|
||||||
|
firstSubMesh: 0
|
||||||
|
subMeshCount: 0
|
||||||
|
m_StaticBatchRoot: {fileID: 0}
|
||||||
|
m_ProbeAnchor: {fileID: 0}
|
||||||
|
m_LightProbeVolumeOverride: {fileID: 0}
|
||||||
|
m_ScaleInLightmap: 1
|
||||||
|
m_ReceiveGI: 1
|
||||||
|
m_PreserveUVs: 0
|
||||||
|
m_IgnoreNormalsForChartDetection: 0
|
||||||
|
m_ImportantGI: 0
|
||||||
|
m_StitchLightmapSeams: 1
|
||||||
|
m_SelectedEditorRenderState: 3
|
||||||
|
m_MinimumChartSize: 4
|
||||||
|
m_AutoUVMaxDistance: 0.5
|
||||||
|
m_AutoUVMaxAngle: 89
|
||||||
|
m_LightmapParameters: {fileID: 0}
|
||||||
|
m_SortingLayerID: 0
|
||||||
|
m_SortingLayer: 0
|
||||||
|
m_SortingOrder: 0
|
||||||
|
m_AdditionalVertexStreams: {fileID: 0}
|
||||||
|
--- !u!65 &5845716565458182149
|
||||||
|
BoxCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 6139051692386484099}
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_IsTrigger: 0
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Size: {x: 1, y: 1, z: 1}
|
||||||
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &5713671764962751473
|
||||||
|
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: d8d3b6de660834e3e898725928251405, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
myObject: {fileID: -4404668399269848200}
|
||||||
|
userid: 0
|
||||||
|
username:
|
||||||
|
room:
|
||||||
|
manager: {fileID: 0}
|
||||||
|
isLocal: 0
|
||||||
|
lastObjectId: 0
|
||||||
|
commsNetwork: {fileID: 0}
|
||||||
|
dissonanceID:
|
||||||
|
--- !u!114 &-4404668399269848200
|
||||||
|
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: 89e3af759df774692a566a166b4bf69b, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
owner: {fileID: 5713671764962751473}
|
||||||
|
networkId:
|
||||||
|
targetPosition: {x: 0, y: 0, z: 0}
|
||||||
|
targetRotation: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d4158ab9c4a204cdbba28d3273fc1fb3
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &8565720275311462453
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 8565720275311462455}
|
||||||
|
- component: {fileID: 8565720275311462452}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: TestNetworkedGameObject
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &8565720275311462455
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8565720275311462453}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 8565720276181857624}
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &8565720275311462452
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8565720275311462453}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 3f1f9b0bbd93a484a987c51f1107ebe5, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
owner: {fileID: 0}
|
||||||
|
networkId:
|
||||||
|
targetPosition: {x: 0, y: 0, z: 0}
|
||||||
|
targetRotation: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
--- !u!1 &8565720276181857625
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 8565720276181857624}
|
||||||
|
- component: {fileID: 8565720276181857605}
|
||||||
|
- component: {fileID: 8565720276181857626}
|
||||||
|
- component: {fileID: 8565720276181857627}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Sphere
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &8565720276181857624
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8565720276181857625}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 8565720275311462455}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!33 &8565720276181857605
|
||||||
|
MeshFilter:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8565720276181857625}
|
||||||
|
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
--- !u!23 &8565720276181857626
|
||||||
|
MeshRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8565720276181857625}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_CastShadows: 1
|
||||||
|
m_ReceiveShadows: 1
|
||||||
|
m_DynamicOccludee: 1
|
||||||
|
m_MotionVectors: 1
|
||||||
|
m_LightProbeUsage: 1
|
||||||
|
m_ReflectionProbeUsage: 1
|
||||||
|
m_RayTracingMode: 2
|
||||||
|
m_RayTraceProcedural: 0
|
||||||
|
m_RenderingLayerMask: 1
|
||||||
|
m_RendererPriority: 0
|
||||||
|
m_Materials:
|
||||||
|
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
|
||||||
|
m_StaticBatchInfo:
|
||||||
|
firstSubMesh: 0
|
||||||
|
subMeshCount: 0
|
||||||
|
m_StaticBatchRoot: {fileID: 0}
|
||||||
|
m_ProbeAnchor: {fileID: 0}
|
||||||
|
m_LightProbeVolumeOverride: {fileID: 0}
|
||||||
|
m_ScaleInLightmap: 1
|
||||||
|
m_ReceiveGI: 1
|
||||||
|
m_PreserveUVs: 0
|
||||||
|
m_IgnoreNormalsForChartDetection: 0
|
||||||
|
m_ImportantGI: 0
|
||||||
|
m_StitchLightmapSeams: 1
|
||||||
|
m_SelectedEditorRenderState: 3
|
||||||
|
m_MinimumChartSize: 4
|
||||||
|
m_AutoUVMaxDistance: 0.5
|
||||||
|
m_AutoUVMaxAngle: 89
|
||||||
|
m_LightmapParameters: {fileID: 0}
|
||||||
|
m_SortingLayerID: 0
|
||||||
|
m_SortingLayer: 0
|
||||||
|
m_SortingOrder: 0
|
||||||
|
m_AdditionalVertexStreams: {fileID: 0}
|
||||||
|
--- !u!135 &8565720276181857627
|
||||||
|
SphereCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 8565720276181857625}
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_IsTrigger: 0
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Radius: 0.5
|
||||||
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6e4a023f70e01405e8b249a4488fe319
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e4e43899246c941c78acfc59ce2f664a
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "VelNetUnity",
|
||||||
|
"rootNamespace": "VelNetUnity",
|
||||||
|
"references": [],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1e55e2c4387020247a1ae212bbcbd381
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "edu.uga.engr.vel.velnetunity",
|
||||||
|
"displayName": "VelNetUnity",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"unity": "2019.1",
|
||||||
|
"description": "A custom networking library for Unity.",
|
||||||
|
"keywords": [
|
||||||
|
"networking",
|
||||||
|
"self-hosted"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Kyle Johnsen",
|
||||||
|
"email": "kjohnsen@uga.edu",
|
||||||
|
"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",
|
||||||
|
"path": "Samples~/Example"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 525b0bfd38079f24f86b406a8da0b3c7
|
||||||
|
PackageManifestImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Loading…
Reference in New Issue