From 0d6446ae18f611265dce1671b4994139d02dbbde Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Mon, 27 Nov 2023 15:29:38 +0100 Subject: [PATCH] Added PhotonPUN support --- .../Extensions/UnityXR/UnityXR_Editor.cs | 2 +- .../HumanoidControl/Networking/PhotonPun.meta | 8 + .../PhotonPun/HumanoidPun_Editor.cs | 143 ++++ .../PhotonPun/HumanoidPun_Editor.cs.meta | 11 + .../Networking/PhotonPun/PunStarter_Editor.cs | 108 +++ .../PhotonPun/PunStarter_Editor.cs.meta | 11 + .../Networking/PhotonPun/HumanoidPlayerPun.cs | 669 ++++++++++++++++++ .../PhotonPun/HumanoidPlayerPun.cs.meta | 12 + .../PhotonPun/HumanoidPlayerPunVoice.cs | 72 ++ .../PhotonPun/HumanoidPlayerPunVoice.cs.meta | 11 + .../Networking/PhotonPun/PunStarter.cs | 97 +++ .../Networking/PhotonPun/PunStarter.cs.meta | 12 + 12 files changed, 1155 insertions(+), 1 deletion(-) create mode 100644 Editor/HumanoidControl/Networking/PhotonPun.meta create mode 100644 Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs create mode 100644 Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs.meta create mode 100644 Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs create mode 100644 Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs.meta create mode 100644 Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs create mode 100644 Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs.meta create mode 100644 Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs create mode 100644 Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs.meta create mode 100644 Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs create mode 100644 Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs.meta diff --git a/Editor/HumanoidControl/Extensions/UnityXR/UnityXR_Editor.cs b/Editor/HumanoidControl/Extensions/UnityXR/UnityXR_Editor.cs index 3075c69..ed9a0a1 100644 --- a/Editor/HumanoidControl/Extensions/UnityXR/UnityXR_Editor.cs +++ b/Editor/HumanoidControl/Extensions/UnityXR/UnityXR_Editor.cs @@ -76,7 +76,7 @@ namespace Passer.Humanoid { Debug.Log(questManifestPath); File.Copy(questManifestPath, manifestPath); } - catch (System.Exception _) { + catch (System.Exception ) { return; } } diff --git a/Editor/HumanoidControl/Networking/PhotonPun.meta b/Editor/HumanoidControl/Networking/PhotonPun.meta new file mode 100644 index 0000000..d048983 --- /dev/null +++ b/Editor/HumanoidControl/Networking/PhotonPun.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 875a66c1e6398184192242a8674906b3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs b/Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs new file mode 100644 index 0000000..ddadef9 --- /dev/null +++ b/Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs @@ -0,0 +1,143 @@ +using UnityEngine; +#if hPHOTON2 +using Photon.Pun; +#if hPUNVOICE2 && !UNITY_WEBGL +using Photon.Voice.PUN; +using Photon.Voice.Unity; +#endif +#endif +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace Passer.Humanoid { + + [InitializeOnLoad] + public class OnLoadHumanoidPlayerPun { + static OnLoadHumanoidPlayerPun() { + CheckHumanoidPlayer(); + } + + protected static void CheckHumanoidPlayerVoice() { +#if hPUNVOICE2 + string prefabPath = OnLoadHumanoidPlayer.GetHumanoidPlayerPrefabPath(); + prefabPath = prefabPath.Substring(0, prefabPath.Length - 21) + "HumanoidPlayerVoice.prefab"; + GameObject playerVoicePrefab = OnLoadHumanoidPlayer.GetHumanoidPlayerPrefab(prefabPath); + if (playerVoicePrefab == null) + return; + + bool hasChanged = false; +#if UNITY_WEBGL + PhotonView photonView = playerVoicePrefab.GetComponent(); + if (photonView == null) { + photonView = playerVoicePrefab.AddComponent(); + hasChanged = true; + } +#else + PhotonVoiceView photonVoiceView = playerVoicePrefab.GetComponent(); + if (photonVoiceView == null) { + photonVoiceView = playerVoicePrefab.AddComponent(); + hasChanged = true; + } + if (photonVoiceView.UsePrimaryRecorder == false) { + photonVoiceView.UsePrimaryRecorder = true; + hasChanged = true; + } + PhotonTransformView photonTransformView = playerVoicePrefab.GetComponent(); + if (photonTransformView == null) { + photonTransformView = playerVoicePrefab.AddComponent(); + hasChanged = true; + } + PhotonView photonView = playerVoicePrefab.GetComponent(); + if (photonView != null) { + // should always be there because of the photonVoiceView + if (photonView.ObservedComponents == null) { + photonView.ObservedComponents = new System.Collections.Generic.List(); + photonView.ObservedComponents.Add(photonTransformView); + photonView.Synchronization = ViewSynchronization.UnreliableOnChange; + hasChanged = true; + } + } + //Speaker speaker = playerVoicePrefab.GetComponent(); + //if (speaker == null) { + // speaker = playerVoicePrefab.AddComponent(); + // photonVoiceView.SpeakerInUse = speaker; + // hasChanged = true; + + // AudioSource audioSource = playerVoicePrefab.GetComponent(); + // if (audioSource != null) { + // Debug.Log("adjust rolloff"); + // // default logaritmic only work when people are closer than 0.5m... + // audioSource.maxDistance = 5; + // } + //} +#endif + if (hasChanged) + OnLoadHumanoidPlayer.UpdateHumanoidPrefab(playerVoicePrefab, prefabPath); +#if !UNITY_WEBGL + CheckVoiceNetwork(); +#endif +#endif + } + +#if hPUNVOICE2 && !UNITY_WEBGL + protected static void CheckVoiceNetwork() { + NetworkingStarter networkingStarter = Object.FindObjectOfType(); + if (networkingStarter == null) + return; + + PhotonVoiceNetwork voiceNetwork = Object.FindObjectOfType(); + if (voiceNetwork != null) + return; + + GameObject voiceNetworkObject = new GameObject("Voice Network"); + voiceNetwork = voiceNetworkObject.AddComponent(); + + Recorder voiceRecorder = voiceNetworkObject.AddComponent(); + voiceRecorder.ReactOnSystemChanges = true; + voiceRecorder.TransmitEnabled = true; + voiceRecorder.SamplingRate = POpusCodec.Enums.SamplingRate.Sampling48000; + + voiceNetwork.PrimaryRecorder = voiceRecorder; + } +#endif + + public static void CheckHumanoidPlayer() { +#if hPHOTON1 || hPHOTON2 + string prefabPath = OnLoadHumanoidPlayer.GetHumanoidPlayerPrefabPath(); + GameObject playerPrefab = OnLoadHumanoidPlayer.GetHumanoidPlayerPrefab(prefabPath); + + bool hasChanged = false; +#if hNW_PHOTON + if (playerPrefab != null) { + PhotonView photonView = playerPrefab.GetComponent(); + if (photonView == null) { + photonView = playerPrefab.AddComponent(); + photonView.ObservedComponents = new System.Collections.Generic.List(); +#if hPHOTON2 + photonView.Synchronization = ViewSynchronization.UnreliableOnChange; +#else + photonView.synchronization = ViewSynchronization.UnreliableOnChange; +#endif + + HumanoidPlayer humanoidPun = playerPrefab.GetComponent(); + if (humanoidPun != null) + photonView.ObservedComponents.Add(humanoidPun); + hasChanged = true; + } + } +#else + if (playerPrefab != null) { + PhotonView photonView = playerPrefab.GetComponent(); + if (photonView != null) + Object.DestroyImmediate(photonView, true); + } +#endif + if (hasChanged) + OnLoadHumanoidPlayer.UpdateHumanoidPrefab(playerPrefab, prefabPath); +#endif + CheckHumanoidPlayerVoice(); + } + } + +} \ No newline at end of file diff --git a/Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs.meta b/Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs.meta new file mode 100644 index 0000000..b3c6beb --- /dev/null +++ b/Editor/HumanoidControl/Networking/PhotonPun/HumanoidPun_Editor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 185ec4e1799d1ac4d867b69454f1cd0f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs b/Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs new file mode 100644 index 0000000..b322d5f --- /dev/null +++ b/Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs @@ -0,0 +1,108 @@ +/* +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; +#if hNW_PHOTON +#if hPHOTON2 +using Photon.Pun; +#endif + +namespace Passer { + + [CustomEditor(typeof(PhotonStarter))] + public class PunStarter_Editor : Editor { + + public override void OnInspectorGUI() { + base.OnInspectorGUI(); + + HumanoidControl[] humanoids = FindObjectsOfType(); + if (humanoids.Length != 1) + // We only support sitatuation with one humanoid in the scene + return; + + //HumanoidControl humanoid = humanoids[0]; + + if (Application.isPlaying) + return; + + //GameObject humanoidPrefab = CheckHumanoidPrefab(humanoid); + //NetworkingComponentsInspectorPun(humanoid, humanoidPrefab); + } + + //private GameObject CheckHumanoidPrefab(HumanoidControl humanoid) { + // GameObject humanoidPrefab = Resources.Load(humanoid.gameObject.name + "_generated"); + // if (humanoidPrefab == null) { + // humanoidPrefab = PrefabUtility.CreatePrefab("Assets/Humanoid/Prefabs/Networking/Resources/" + humanoid.gameObject.name + "_generated.prefab", humanoid.gameObject); + // humanoidPrefab.gameObject.SetActive(true); + // } + // return humanoidPrefab; + //} + + //private void UpdateHumanoidPrefab(HumanoidControl humanoid) { + // if (humanoid != null) { + // GameObject humanoidPrefab = Resources.Load(humanoid.gameObject.name + "_generated"); + // if (humanoidPrefab != null && humanoid.gameObject != humanoidPrefab) + // PrefabUtility.ReplacePrefab(humanoid.gameObject, humanoidPrefab, ReplacePrefabOptions.ConnectToPrefab); + // } + //} + +// private void NetworkingComponentsInspectorPun(HumanoidControl humanoid, GameObject humanoidPrefab) { +//#if hPHOTON1 || hPHOTON2 +//#if hNW_PHOTON +// CheckPunStarter(humanoid, humanoidPrefab); +// PhotonView photonView = humanoid.GetComponent(); +// if (photonView == null) +// photonView = humanoid.gameObject.AddComponent(); +// photonView.ObservedComponents = new System.Collections.Generic.List(); +// photonView.ObservedComponents.Add(humanoid); +//#else +// cleanupPhotonView = humanoid.GetComponent(); +//#endif +//#endif +// } + +// private void CheckPunStarter(HumanoidControl humanoid, GameObject humanoidPrefab) { +// if (Application.isPlaying) +// return; + +//#if hNW_PHOTON +// PhotonStarter photonStarter = FindObjectOfType(); +// if (photonStarter != null && humanoidPrefab != null && photonStarter.playerPrefab != humanoidPrefab) { +// Undo.RecordObject(photonStarter, "Updated Player Prefab"); +// photonStarter.playerPrefab = humanoidPrefab; +// } +//#endif +// } + public void OnDisable() { + Cleanup(); + } + +#if hNW_UNET + private NetworkIdentity cleanupNetworkIdentity; +#endif +#if hPHOTON1 || hPHOTON2 + private PhotonView cleanupPhotonView; +#endif + private GameObject cleanupPunStarter; + private void Cleanup() { +#if hNW_UNET + if (cleanupNetworkIdentity) { + DestroyImmediate(cleanupNetworkIdentity, true); + cleanupNetworkIdentity = null; + } +#endif +#if hPHOTON1 || hPHOTON2 + if (cleanupPhotonView) { + DestroyImmediate(cleanupPhotonView, true); + cleanupPhotonView = null; + } +#endif + if (cleanupPunStarter) { + DestroyImmediate(cleanupPunStarter, true); + cleanupPunStarter = null; + } + } + } +} +#endif +*/ \ No newline at end of file diff --git a/Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs.meta b/Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs.meta new file mode 100644 index 0000000..c589c24 --- /dev/null +++ b/Editor/HumanoidControl/Networking/PhotonPun/PunStarter_Editor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e86563dd015c559479420645216c4a70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs new file mode 100644 index 0000000..6a92302 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs @@ -0,0 +1,669 @@ +using UnityEngine; +#if hNW_PHOTON +using System.Collections.Generic; +#endif +#if hPHOTON2 +using Photon.Realtime; +using Photon.Pun; +#endif + +namespace Passer.Humanoid { + using Pawn; + +#if hNW_PHOTON + [RequireComponent(typeof(PhotonView))] +#if hPHOTON2 + public partial class HumanoidPlayer : MonoBehaviourPunCallbacks, IHumanoidNetworking, IPunInstantiateMagicCallback, IPunObservable { +#else + public partial class HumanoidPlayer : Photon.MonoBehaviour, IHumanoidNetworking { +#endif + + public ulong nwId { +#if hPHOTON2 + get { return (ulong)photonView.ViewID; } +#else + get { return (ulong)photonView.viewID; } +#endif + } + + [SerializeField] + protected float _sendRate = 25; + public float sendRate { + get { return _sendRate; } + } + + //[SerializeField] + //protected HumanoidNetworking.DebugLevel _debug = HumanoidNetworking.DebugLevel.Error; + //public HumanoidNetworking.DebugLevel debug { + // get { return _debug; } + //} + + [SerializeField] + protected HumanoidNetworking.Smoothing _smoothing = HumanoidNetworking.Smoothing.None; + public HumanoidNetworking.Smoothing smoothing { + get { return _smoothing; } + } + + [SerializeField] + protected bool _createLocalRemotes = false; + public bool createLocalRemotes { + get { return _createLocalRemotes; } + set { _createLocalRemotes = value; } + } + + public bool isLocal { get; set; } + + public List humanoids { get; set; } + + public ulong GetObjectIdentity(GameObject obj) { + PhotonView photonView = obj.GetComponent(); + if (photonView == null) + return 0; + +#if hPHOTON2 + return (ulong)photonView.ViewID; +#else + return (ulong)photonView.viewID; +#endif + } + + public GameObject GetGameObject(ulong objIdentity) { + PhotonView objView = PhotonView.Find((int)objIdentity); + if (objView == null) + return this.gameObject; + + return objView.gameObject; + } + + #region Init +#if hPHOTON2 + public override void OnEnable() { + base.OnEnable(); + PhotonNetwork.AddCallbackTarget(this); + } + + public override void OnDisable() { + base.OnDisable(); + PhotonNetwork.RemoveCallbackTarget(this); + } +#endif + public void Awake() { + mInstance = this; + + GameObject.DontDestroyOnLoad(this.gameObject); + humanoids = HumanoidNetworking.FindLocalHumanoids(); + + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Found " + humanoids.Count + " Humanoids"); + + for (int i = 0; i < humanoids.Count; i++) { + HumanoidControl humanoid = humanoids[i]; + if (humanoid.isRemote || createLocalRemotes == false) + continue; + + humanoid.humanoidNetworking = this; + ((IHumanoidNetworking)this).InstantiateHumanoid(humanoid); + } + } + + #endregion + + #region Start + public void OnPhotonInstantiate(PhotonMessageInfo info) { +#if hPHOTON2 + if (photonView.IsMine) { +#else + if (photonView.isMine) { +#endif + isLocal = true; + name = "HumanoidPun(Local)"; + + humanoids = HumanoidNetworking.FindLocalHumanoids(); + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Found " + humanoids.Count + " Humanoids"); + + for (int i = 0; i < humanoids.Count; i++) { + HumanoidControl humanoid = humanoids[i]; + if (humanoid.isRemote) + continue; +#if hPHOTON2 + humanoid.nwId = (ulong)photonView.ViewID; +#else + humanoid.nwId = nwId; // photonView.viewID; +#endif + humanoid.humanoidNetworking = this; + + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Send Start Humanoid " + humanoid.humanoidId); + + ((IHumanoidNetworking)this).InstantiateHumanoid(humanoid); + +#if hPUNVOICE2 && !UNITY_WEBGL + InstantiatePlayerVoice(humanoid); +#endif + HumanoidNetworking.Connected(humanoid); + } + + NetworkingSpawner spawner = FindObjectOfType(); + if (spawner != null) + spawner.OnNetworkingStarted(); + + } + else { + humanoids = HumanoidNetworking.FindLocalHumanoids(); + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Found " + humanoids.Count + " Humanoids"); + } + } + +#if hPHOTON2 + public override void OnPlayerEnteredRoom(Player newPlayer) { +#else + public void OnPhotonPlayerConnected(PhotonPlayer player) { +#endif + List humanoids = HumanoidNetworking.FindLocalHumanoids(); + if (humanoids.Count <= 0) + return; + + foreach (HumanoidControl humanoid in humanoids) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log(humanoid.nwId + ": (Re)Send Instantiate Humanoid " + humanoid.humanoidId); + + // Notify new player about my humanoid + ((IHumanoidNetworking)this).InstantiateHumanoid(humanoid); + + if (humanoid.leftHandTarget.grabbedObject != null) + humanoid.humanoidNetworking.Grab(humanoid.leftHandTarget, humanoid.leftHandTarget.grabbedObject, false); + if (humanoid.rightHandTarget.grabbedObject != null) + humanoid.humanoidNetworking.Grab(humanoid.rightHandTarget, humanoid.rightHandTarget.grabbedObject, false); + + } + } + #endregion + + #region Update + PhotonStream stream; + + float lastSend; + + // The number of received messages processed in this frame + private int processedThisFrame = 0; + private enum MessageType { + Pose, + Grab, + LetGo + } + private struct QueuedMessage { + public MessageType messageType; + public byte[] data; + } + private Queue messageQueue = new Queue(); + + protected virtual void LateUpdate() { + processedThisFrame = 0; + if (messageQueue.Count > 0) { + ProcessMessageFromQueue(); + Debug.Log("----Processed messages = " + messageQueue.Count); + } + + if (!createLocalRemotes) + return; + + if (Time.time > lastSend + 1 / sendRate) { + if (humanoids != null) { + foreach (HumanoidControl humanoid in humanoids) { + if (!humanoid.isRemote) { + UpdateHumanoidPose(humanoid); + if (syncTracking) + SyncTrackingSpace(humanoid); + } + } + } + lastSend = Time.time; + } + } + + private float lastPoseTime; + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { + this.stream = stream; +#if hPHOTON2 + if (stream.IsWriting) { +#else + if (stream.isWriting) { +#endif + foreach (HumanoidControl humanoid in humanoids) { + if (!humanoid.isRemote) { + UpdateHumanoidPose(humanoid); + if (syncTracking) + SyncTrackingSpace(humanoid); + } + } + } + else { + ReceiveAvatarPose(stream); + } + } + + private void ProcessMessageFromQueue() { + QueuedMessage msg = messageQueue.Dequeue(); + switch (msg.messageType) { + case MessageType.Pose: + this.ReceiveHumanoidPose(msg.data); + break; + case MessageType.Grab: + Debug.Log("Processing Queued Grab " + Time.time); + this.ReceiveGrab(msg.data); + break; + case MessageType.LetGo: + Debug.Log("Processsing Queueud Let Go " + Time.time); + this.ReceiveLetGo(msg.data); + break; + } + } + #endregion + + #region Stop + private void OnDestroy() { + if (humanoids == null) + return; + + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Destroy Remote Humanoids"); + + foreach (HumanoidControl humanoid in humanoids) { + if (humanoid == null) + continue; + + if (humanoid.isRemote) { + if (humanoid.gameObject != null) + Destroy(humanoid.gameObject); + } + } + } + #endregion + + #region Instantiate Humanoid + + void IHumanoidNetworking.InstantiateHumanoid(HumanoidControl humanoid) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Send Instantiate Humanoid " + humanoid.humanoidId); + + HumanoidNetworking.InstantiateHumanoid instantiateHumanoid = new HumanoidNetworking.InstantiateHumanoid(humanoid); + if (createLocalRemotes) { + this.Receive(instantiateHumanoid); + } + + byte[] data = instantiateHumanoid.Serialize(); +#if hPHOTON2 + photonView.RPC("RpcInstantiateHumanoid", RpcTarget.Others, data); +#else + photonView.RPC("RpcInstantiateHumanoid", PhotonTargets.Others, data); +#endif + } + + [PunRPC] + protected virtual void RpcInstantiateHumanoid(byte[] data) { + this.ReceiveInstantiate(data); + } + +#if hPUNVOICE2 && !UNITY_WEBGL + protected virtual void InstantiatePlayerVoice(HumanoidControl humanoid) { + GameObject playerVoiceGameObject = PhotonNetwork.Instantiate("HumanoidPlayerVoice", humanoid.headTarget.transform.position, humanoid.headTarget.transform.rotation); + HumanoidPlayerPunVoice playerVoice = playerVoiceGameObject.GetComponent(); + if (playerVoice != null) + playerVoice.humanoid = humanoid; + Debug.Log("created voice for " + humanoid); + } +#endif + #endregion + + #region Destroy Humanoid + + void IHumanoidNetworking.DestroyHumanoid(HumanoidControl humanoid) { + if (humanoid == null) + return; + + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Destroy Humanoid " + humanoid.humanoidId); + + HumanoidNetworking.DestroyHumanoid destroyHumanoid = new HumanoidNetworking.DestroyHumanoid(humanoid); + if (createLocalRemotes) + this.Receive(destroyHumanoid); + + byte[] data = destroyHumanoid.Serialize(); +#if hPHOTON2 + if (PhotonNetwork.IsConnected) + photonView.RPC("RpcDestroyHumanoid", RpcTarget.Others, data); +#else + if (PhotonNetwork.connected) + photonView.RPC("RpcDestroyHumanoid", PhotonTargets.Others, data); +#endif + } + + [PunRPC] + public void RpcDestroyHumanoid(byte[] data) { + this.ReceiveDestroy(data); + } + #endregion + + #region Pose + + public HumanoidNetworking.HumanoidPose lastHumanoidPose { get; set; } + + public virtual void UpdateHumanoidPose(HumanoidControl humanoid) { + if (debug <= HumanoidNetworking.DebugLevel.Debug) + DebugLog("Send Pose Humanoid " + humanoid.humanoidId + " nwId: " + humanoid.nwId); + + HumanoidNetworking.HumanoidPose humanoidPose = new HumanoidNetworking.HumanoidPose(humanoid, Time.time); + if (createLocalRemotes) + this.Receive(humanoidPose); + + if (stream != null) { + byte[] data = humanoidPose.Serialize(); + stream.SendNext(data); + } + } + + PhotonStream reader; + + private void ReceiveAvatarPose(PhotonStream reader) { + this.reader = reader; + + byte[] data = (byte[])reader.ReceiveNext(); + this.ReceiveHumanoidPose(data); + } + + #endregion + + #region Grab + + void IHumanoidNetworking.Grab(HandTarget handTarget, GameObject obj, bool rangeCheck, HandTarget.GrabType grabType) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Grab " + obj + " " + grabType); + + ulong objIdentity = GetObjectIdentity(obj); + if (objIdentity == 0) { + if (debug <= HumanoidNetworking.DebugLevel.Warning) + Debug.LogError("Photon Grab: Grabbed object does not have a PhotonView"); + return; + } + + HumanoidNetworking.Grab grab = new HumanoidNetworking.Grab(handTarget, objIdentity, rangeCheck, grabType); + if (createLocalRemotes) + // Does this make sense? + this.Receive(grab); + + byte[] data = grab.Serialize(); + +#if hPHOTON2 + photonView.RPC("RpcGrab", RpcTarget.Others, data); +#else + photonView.RPC("RpcGrab", PhotonTargets.Others, data); +#endif + } + + [PunRPC] + public void RpcGrab(byte[] data) { + if (processedThisFrame > 0 || messageQueue.Count > 0) { + QueuedMessage msg = new QueuedMessage() { + messageType = MessageType.Grab, + data = data + }; + messageQueue.Enqueue(msg); + Debug.Log("++++Buffered Grab message = " + messageQueue.Count + " " + Time.time); + return; + } + + this.ReceiveGrab(data); + processedThisFrame++; + } + + #endregion + + #region Let Go + + void IHumanoidNetworking.LetGo(HandTarget handTarget) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("LetGo"); + + HumanoidNetworking.LetGo letGo = new HumanoidNetworking.LetGo(handTarget); + if (createLocalRemotes) + this.Receive(letGo); + + byte[] data = letGo.Serialize(); +#if hPHOTON2 + photonView.RPC("RpcLetGo", RpcTarget.Others, data); +#else + photonView.RPC("RpcLetGo", PhotonTargets.Others, data); +#endif + } + + [PunRPC] + public void RpcLetGo(byte[] data) { + if (processedThisFrame > 0 || messageQueue.Count > 0) { + QueuedMessage msg = new QueuedMessage() { + messageType = MessageType.LetGo, + data = data + }; + messageQueue.Enqueue(msg); + Debug.Log("++++Buffered Let Go message = " + messageQueue.Count + " " + Time.time); + return; + } + + this.ReceiveLetGo(data); + processedThisFrame++; + } + + #endregion + + #region Change Avatar + void IHumanoidNetworking.ChangeAvatar(HumanoidControl humanoid, string avatarPrefabName, string possessionLocation) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log(humanoid.nwId + ": Change Avatar: " + avatarPrefabName); + + HumanoidNetworking.ChangeAvatar changeAvatar = new HumanoidNetworking.ChangeAvatar(humanoid, avatarPrefabName, possessionLocation); + if (createLocalRemotes) + this.Receive(changeAvatar); + + byte[] data = changeAvatar.Serialize(); +#if hPHOTON2 + photonView.RPC("RpcChangeAvatar", RpcTarget.Others, data); // humanoid.humanoidId, avatarPrefabName); +#else + photonView.RPC("RpcChangeAvatar", PhotonTargets.Others, data); // humanoid.humanoidId, avatarPrefabName); +#endif + } + + [PunRPC] + protected virtual void RpcChangeAvatar(byte[] data) { + this.ReceiveChangeAvatar(data); + } + + #endregion + + #region Tracking + + private Transform GetTrackingTransform(HumanoidControl humanoid) { +#if hANTILATENCY + if (humanoid.antilatency != null) + return humanoid.antilatency.trackerTransform; +#endif + //#if hOPENVR && (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX) + // if (humanoid.openVR != null) + // return humanoid.openVR.GetTrackingTransform(); + //#endif + return null; + } + + public void SyncTrackingSpace(HumanoidControl humanoid) { + if (humanoid == null) + return; + + Transform trackingTransform = GetTrackingTransform(humanoid); + if (trackingTransform == null) + return; + + if (debug <= HumanoidNetworking.DebugLevel.Info) + DebugLog("Send Sync Tracking Space " + humanoid.humanoidId + " " + trackingTransform.position + " " + trackingTransform.rotation); + + HumanoidNetworking.SyncTrackingSpace syncTrackingSpace = + new HumanoidNetworking.SyncTrackingSpace(humanoid, trackingTransform.position, trackingTransform.rotation); + + if (createLocalRemotes) + // Does this make sense? + this.Receive(syncTrackingSpace); + + byte[] data = syncTrackingSpace.Serialize(); +#if hPHOTON2 + photonView.RPC("RpcSyncTracking", RpcTarget.Others, data); +#else + photonView.RPC("RpcSyncTracking", PhotonTargets.Others, data); +#endif + + } + + [PunRPC] + protected virtual void RpcSyncTracking(byte[] data) { + this.ReceiveSyncTrackingSpace(data); + } + + #endregion + + #region Network Sync + + void IHumanoidNetworking.ReenableNetworkSync(GameObject obj) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log("ReenableNetworkSync " + obj); + + ReenableNetworkSync(obj); + } + + void IHumanoidNetworking.DisableNetworkSync(GameObject obj) { + if (debug <= HumanoidNetworking.DebugLevel.Info) + Debug.Log("DisableNetworkSync " + obj); + DisableNetworkSync(obj); + } + + public static void ReenableNetworkSync(GameObject obj) { +#if hPHOTON2 + PhotonView photonView = obj.GetComponent(); + if (photonView != null) { + photonView.Synchronization = ViewSynchronization.UnreliableOnChange; + } +#endif + + PhotonTransformView transformView = obj.GetComponent(); + if (transformView != null) { +#if hPHOTON2 + transformView.m_SynchronizePosition = true; + transformView.m_SynchronizeRotation = true; + transformView.enabled = true; + +#else + transformView.m_PositionModel.SynchronizeEnabled = true; + transformView.m_RotationModel.SynchronizeEnabled = true; +#endif + } + } + + public static void TakeOwnership(GameObject obj) { +#if hPHOTON2 + PhotonView photonView = obj.GetComponent(); + if (photonView != null) + photonView.RequestOwnership(); +#endif + } + + public static void DisableNetworkSync(GameObject obj) { + PhotonTransformView transformView = obj.GetComponent(); + if (transformView != null) { +#if hPHOTON2 + transformView.m_SynchronizePosition = false; + transformView.m_SynchronizeRotation = false; + transformView.enabled = false; +#else + transformView.m_PositionModel.SynchronizeEnabled = false; + transformView.m_RotationModel.SynchronizeEnabled = false; +#endif + } + } + + #endregion + + #region Network Object + + #region Void Event + + public void RPC(FunctionCall functionCall) { + ulong objIdentity = GetObjectIdentity(functionCall.targetGameObject); + if (objIdentity == 0) { + if (debug <= HumanoidNetworking.DebugLevel.Warning) + Debug.LogError("Photon Grab: Grabbed object does not have a PhotonView"); + return; + } + + photonView.RPC("RpcFunctionCall", RpcTarget.Others, objIdentity, functionCall.methodName); + } + + [PunRPC] + public void RpcFunctionCall(ulong objIdentity, string methodName) { + GameObject targetGameObject = GetGameObject(objIdentity); + if (targetGameObject == null) { + if (debug <= HumanoidNetworking.DebugLevel.Warning) + Debug.LogError("FunctionCall: Could not find object for method " + methodName); + return; + } + + FunctionCall.Execute(targetGameObject, methodName); + } + #endregion + + #endregion Network Object + + #region Send + public void Send(bool b) { stream.SendNext(b); } + public void Send(byte b) { stream.SendNext(b); } + public void Send(int x) { stream.SendNext(x); } + public void Send(float f) { stream.SendNext(f); } + public void Send(Vector3 v) { stream.SendNext(v); } + public void Send(Quaternion q) { stream.SendNext(q); } + #endregion + + #region Receive + public bool ReceiveBool() { return (bool)reader.ReceiveNext(); } + public byte ReceiveByte() { return (byte)reader.ReceiveNext(); } + public int ReceiveInt() { return (int)reader.ReceiveNext(); } + public float ReceiveFloat() { return (float)reader.ReceiveNext(); } + public Vector3 ReceiveVector3() { return (Vector3)reader.ReceiveNext(); } + public Quaternion ReceiveQuaternion() { return (Quaternion)reader.ReceiveNext(); } + #endregion + + #region Debug + + public void DebugLog(string message) { +#if hPHOTON2 + Debug.Log(photonView.ViewID + ": " + message); +#else + Debug.Log(photonView.viewID + ": " + message); +#endif + } + + public void DebugWarning(string message) { +#if hPHOTON2 + Debug.LogWarning(photonView.ViewID + ": " + message); +#else + Debug.LogWarning(photonView.viewID + ": " + message); +#endif + } + + public void DebugError(string message) { +#if hPHOTON2 + Debug.LogError(photonView.ViewID + ": " + message); +#else + Debug.LogError(photonView.viewID + ": " + message); +#endif + } + + #endregion + } +#endif +} diff --git a/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs.meta b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs.meta new file mode 100644 index 0000000..2dbcce9 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPun.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b2b89683096330a4eb3810fdaeb79fb6 +timeCreated: 1504014033 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs new file mode 100644 index 0000000..531616e --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs @@ -0,0 +1,72 @@ +using UnityEngine; +#if hPUNVOICE2 +using Photon.Pun; +#endif + +namespace Passer.Humanoid { + +#if !hPUNVOICE2 + public partial class HumanoidPlayerPunVoice : MonoBehaviour { +#else + public class HumanoidPlayerPunVoice : MonoBehaviourPunCallbacks { +#endif + /// + /// The humanoid to follow + /// + public HumanoidControl humanoid; + +#if hPUNVOICE2 + + private bool updateAudioSource = true; + + #region Init + + protected virtual void Start() { + Debug.Log("Started HumanoidVoice"); + DontDestroyOnLoad(this.gameObject); + } + + #endregion Init + + #region Update + + protected virtual void Update() { + if (photonView.Controller.IsLocal) { + transform.position = humanoid.headTarget.transform.position; + } + else { + if (updateAudioSource) { + AudioSource audioSource = GetComponent(); + if (audioSource != null) { + audioSource.rolloffMode = AudioRolloffMode.Linear; + audioSource.spatialBlend = 1; + audioSource.minDistance = 0; + audioSource.maxDistance = 1; + updateAudioSource = false; + } + } + if (humanoid == null) { + foreach (HumanoidControl humanoid in HumanoidControl.allHumanoids) { + if (humanoid.headTarget == null) + continue; + float distance = Vector3.Distance(this.transform.position, humanoid.headTarget.transform.position); + if (distance < 0.01F) { + this.humanoid = humanoid; + AudioSource audioSource = this.humanoid.headTarget.GetComponentInChildren(); +#if pUNITYXR + if (audioSource == null && this.humanoid.headTarget.unityXR.unityXR.hmd != null) + audioSource = this.humanoid.headTarget.unityXR.unityXR.hmd.GetComponentInChildren(); +#endif + if (audioSource != null) + audioSource = this.GetComponent(); + } + } + } + } + } + + #endregion Update + +#endif + } +} \ No newline at end of file diff --git a/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs.meta b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs.meta new file mode 100644 index 0000000..5be9168 --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/HumanoidPlayerPunVoice.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69a31162e39169c4fad112f52654bd40 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs new file mode 100644 index 0000000..5e6dd6c --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs @@ -0,0 +1,97 @@ +using UnityEngine; +#if hPHOTON2 +using Photon.Pun; +using Photon.Realtime; +#endif +#if hPUNVOICE2 +using Photon.Voice.PUN; +using Photon.Voice.Unity; +#endif + +namespace Passer { +#if hNW_PHOTON + public class PunStarter : INetworkingStarter { + + public GameObject playerPrefab; + + public string roomName; + public int gameVersion; + public int sendRate; + + public void Awake() { +#if hPUNVOICE2 && !UNITY_WEBGL + PhotonVoiceNetwork voiceNetwork = Object.FindObjectOfType(); + if (voiceNetwork != null) + return; + + GameObject voiceNetworkObject = new GameObject("Voice Network"); + voiceNetwork = voiceNetworkObject.AddComponent(); + + Recorder voiceRecorder = voiceNetworkObject.AddComponent(); + voiceRecorder.ReactOnSystemChanges = true; + voiceRecorder.TransmitEnabled = true; + voiceRecorder.SamplingRate = POpusCodec.Enums.SamplingRate.Sampling48000; + + voiceNetwork.PrimaryRecorder = voiceRecorder; +#endif + } + + GameObject INetworkingStarter.GetHumanoidPrefab() { + GameObject humanoidPrefab = Resources.Load("HumanoidPlayer"); + return humanoidPrefab; + } + + void INetworkingStarter.StartHost(NetworkingStarter nwStarter) { + ((INetworkingStarter)this).StartClient(nwStarter); + } + + void INetworkingStarter.StartClient(NetworkingStarter nwStarter) { + ((INetworkingStarter)this).StartClient(nwStarter, nwStarter.roomName, nwStarter.gameVersion); + } + + void INetworkingStarter.StartClient(NetworkingStarter nwStarter, string _roomName, int _gameVersion) { + roomName = _roomName; + gameVersion = _gameVersion; + playerPrefab = Resources.Load("HumanoidPlayer"); + sendRate = nwStarter.sendRate; + +#if hPHOTON2 + PhotonNetwork.SendRate = sendRate; + PhotonNetwork.SerializationRate = sendRate; + PhotonNetwork.GameVersion = gameVersion.ToString(); + PhotonNetwork.ConnectUsingSettings(); +#else + PhotonNetwork.sendRate = sendRate; + PhotonNetwork.sendRateOnSerialize = sendRate; + PhotonNetwork.ConnectUsingSettings(gameVersion.ToString()); +#endif + } + + public virtual void OnConnectedToPhoton() { + Debug.Log("Photon"); + } + + public virtual void OnConnectedToMaster() { + RoomOptions roomOptions = new RoomOptions() { IsVisible = false, MaxPlayers = 4 }; + PhotonNetwork.JoinOrCreateRoom(roomName, roomOptions, TypedLobby.Default); + } + + public virtual void OnPhotonJoinRoomFailed() { + Debug.LogError("Could not joint the " + roomName + " room"); + } + + public virtual void OnJoinedRoom(GameObject playerPrefab) { + if (playerPrefab != null) + PhotonNetwork.Instantiate(playerPrefab.name, Vector3.zero, Quaternion.identity, 0); + + //NetworkingSpawner spawner = FindObjectOfType(); + //if (spawner != null) + // spawner.OnNetworkingStarted(); + } + + public void StopClient() { + PhotonNetwork.Disconnect(); + } + } +#endif +} diff --git a/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs.meta b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs.meta new file mode 100644 index 0000000..39b69ba --- /dev/null +++ b/Runtime/HumanoidControl/Scripts/Networking/PhotonPun/PunStarter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bbe6fd67c1c770e478d9cb8eef19b594 +timeCreated: 1466884930 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: