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 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 { Debug.Log("here"); comms.playerStartedSpeaking(dissonanceID); isSpeaking = true; } break; } } } // Start is called before the first frame update void Start() { //handle dissonance stuff comms = GameObject.FindObjectOfType(); 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); }; } } if (owner.isLocal) { StartCoroutine(syncBehavior()); } } void sendVoiceData(ArraySegment 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.sendMessage(this, "a", toSend); } } 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) { 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 kvp in owner.manager.objects) { owner.takeOwnership(kvp.Key); } } if (Input.GetKeyDown(KeyCode.Backspace)) { foreach (KeyValuePair kvp in owner.manager.objects) { owner.networkDestroy(kvp.Key); } } } } }