non-vr lobby, version fix
This commit is contained in:
9
Assets/Photon/PhotonVoice/Code/PUN/Editor.meta
Normal file
9
Assets/Photon/PhotonVoice/Code/PUN/Editor.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ecb985625034aef4681a3a80b40cc5ed
|
||||
folderAsset: yes
|
||||
timeCreated: 1537958667
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "PhotonVoice.PUN.Editor",
|
||||
"references": [
|
||||
"PhotonVoice.PUN",
|
||||
"PhotonVoice.Editor",
|
||||
"PhotonVoice",
|
||||
"PhotonRealtime",
|
||||
"PhotonUnityNetworking"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc45562f375e105438d27eded7d73e12
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
|
||||
namespace Photon.Voice.PUN.Editor
|
||||
{
|
||||
using Unity.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Pun;
|
||||
|
||||
[CustomEditor(typeof(PhotonVoiceNetwork))]
|
||||
public class PhotonVoiceNetworkEditor : VoiceConnectionEditor
|
||||
{
|
||||
private SerializedProperty autoConnectAndJoinSp;
|
||||
private SerializedProperty autoLeaveAndDisconnectSp;
|
||||
private SerializedProperty usePunAppSettingsSp;
|
||||
private SerializedProperty usePunAuthValuesSp;
|
||||
private SerializedProperty workInOfflineModeSp;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
this.autoConnectAndJoinSp = this.serializedObject.FindProperty("AutoConnectAndJoin");
|
||||
this.autoLeaveAndDisconnectSp = this.serializedObject.FindProperty("AutoLeaveAndDisconnect");
|
||||
this.usePunAppSettingsSp = this.serializedObject.FindProperty("usePunAppSettings");
|
||||
this.usePunAuthValuesSp = this.serializedObject.FindProperty("usePunAuthValues");
|
||||
this.workInOfflineModeSp = this.serializedObject.FindProperty("WorkInOfflineMode");
|
||||
}
|
||||
|
||||
protected override void DisplayAppSettings()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(this.usePunAppSettingsSp, new GUIContent("Use PUN's App Settings", "Use App Settings From PUN's PhotonServerSettings"));
|
||||
if (GUILayout.Button("PhotonServerSettings", EditorStyles.miniButton, GUILayout.Width(120)))
|
||||
{
|
||||
Selection.objects = new Object[] { PhotonNetwork.PhotonServerSettings };
|
||||
EditorGUIUtility.PingObject(PhotonNetwork.PhotonServerSettings);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (!this.usePunAppSettingsSp.boolValue)
|
||||
{
|
||||
base.DisplayAppSettings();
|
||||
}
|
||||
EditorGUILayout.PropertyField(this.usePunAuthValuesSp, new GUIContent("Use PUN's Auth Values", "Use the same Authentication Values From PUN client"));
|
||||
}
|
||||
|
||||
protected override void ShowHeader()
|
||||
{
|
||||
base.ShowHeader();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(this.autoConnectAndJoinSp, new GUIContent("Auto Connect And Join", "Auto connect voice client and join a voice room when PUN client is joined to a PUN room"));
|
||||
EditorGUILayout.PropertyField(this.autoLeaveAndDisconnectSp, new GUIContent("Auto Leave And Disconnect", "Auto disconnect voice client when PUN client is not joined to a PUN room"));
|
||||
EditorGUILayout.PropertyField(this.workInOfflineModeSp, new GUIContent("Work In Offline Mode", "Whether or not Photon Voice client should follow PUN client if the latter is in offline mode."));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
this.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ShowAssetVersions()
|
||||
{
|
||||
base.ShowAssetVersions();
|
||||
string version = this.GetVersionString(this.punChangelogVersion).TrimStart('v');
|
||||
if (!PhotonNetwork.PunVersion.Equals(version, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
EditorGUILayout.LabelField(string.Format("PUN2, Inside Voice: {0} != Imported Separately: {1}", version, PhotonNetwork.PunVersion));
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.LabelField(string.Format("PUN2: {0}", version));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa70a22b498b27f41a0bb50f9a287764
|
||||
timeCreated: 1537357720
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoice.PUN.asmdef
Normal file
11
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoice.PUN.asmdef
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "PhotonVoice.PUN",
|
||||
"references": [
|
||||
"PhotonVoice",
|
||||
"PhotonUnityNetworking",
|
||||
"PhotonRealtime",
|
||||
"PhotonVoice.API"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d62e4537d6f8ca64c8d2affe565a5cd1
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
598
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoiceNetwork.cs
Normal file
598
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoiceNetwork.cs
Normal file
@@ -0,0 +1,598 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// <copyright file="PhotonVoiceNetwork.cs" company="Exit Games GmbH">
|
||||
// Photon Voice - Copyright (C) 2018 Exit Games GmbH
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// This class can be used to automatically join/leave Voice rooms when
|
||||
// Photon Unity Networking (PUN) joins or leaves its rooms. The Voice room
|
||||
// will use the same name as PUN, but with a "_voice_" postfix.
|
||||
// It also sets a custom PUN Speaker factory to find the Speaker
|
||||
// component for a character's voice. For this to work, the voice's UserData
|
||||
// must be set to the character's PhotonView ID.
|
||||
// (see "PhotonVoiceView.cs")
|
||||
// </summary>
|
||||
// <author>developer@photonengine.com</author>
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using UnityEngine;
|
||||
using Photon.Pun;
|
||||
using Photon.Realtime;
|
||||
using Photon.Voice.Unity;
|
||||
|
||||
namespace Photon.Voice.PUN
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class can be used to automatically sync client states between PUN and Voice.
|
||||
/// It also sets a custom PUN Speaker factory to find the Speaker component for a character's voice.
|
||||
/// For this to work attach a <see cref="PhotonVoiceView"/> next to the <see cref="PhotonView"/> of your player's prefab.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Photon Voice/Photon Voice Network")]
|
||||
[HelpURL("https://doc.photonengine.com/en-us/voice/v2/getting-started/voice-for-pun")]
|
||||
public class PhotonVoiceNetwork : VoiceConnection
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
/// <summary> Suffix for voice room names appended to PUN room names. </summary>
|
||||
public const string VoiceRoomNameSuffix = "_voice_";
|
||||
/// <summary> Auto connect voice client and join a voice room when PUN client is joined to a PUN room </summary>
|
||||
public bool AutoConnectAndJoin = true;
|
||||
/// <summary> Auto disconnect voice client when PUN client is not joined to a PUN room </summary>
|
||||
public bool AutoLeaveAndDisconnect = true;
|
||||
/// <summary> Whether or not Photon Voice client should follow PUN client if the latter is in offline mode. </summary>
|
||||
public bool WorkInOfflineMode = true;
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private EnterRoomParams voiceRoomParams = new EnterRoomParams
|
||||
{
|
||||
RoomOptions = new RoomOptions { IsVisible = false }
|
||||
};
|
||||
private bool clientCalledConnectAndJoin;
|
||||
private bool clientCalledDisconnect;
|
||||
private bool clientCalledConnectOnly;
|
||||
private bool internalDisconnect;
|
||||
private bool internalConnect;
|
||||
private static object instanceLock = new object();
|
||||
private static PhotonVoiceNetwork instance;
|
||||
private static bool instantiated;
|
||||
|
||||
[SerializeField]
|
||||
private bool usePunAppSettings = true;
|
||||
|
||||
[SerializeField]
|
||||
private bool usePunAuthValues = true;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance for PhotonVoiceNetwork
|
||||
/// </summary>
|
||||
public static PhotonVoiceNetwork Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (AppQuits)
|
||||
{
|
||||
if (instance.Logger.IsWarningEnabled)
|
||||
{
|
||||
instance.Logger.LogWarning("PhotonVoiceNetwork Instance already destroyed on application quit. Won't create again - returning null.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (!instantiated)
|
||||
{
|
||||
PhotonVoiceNetwork[] objects = FindObjectsOfType<PhotonVoiceNetwork>();
|
||||
if (objects == null || objects.Length < 1)
|
||||
{
|
||||
GameObject singleton = new GameObject();
|
||||
singleton.name = "PhotonVoiceNetwork singleton";
|
||||
instance = singleton.AddComponent<PhotonVoiceNetwork>();
|
||||
if (instance.Logger.IsInfoEnabled)
|
||||
{
|
||||
instance.Logger.LogInfo("An instance of PhotonVoiceNetwork was automatically created in the scene.");
|
||||
}
|
||||
}
|
||||
else if (objects.Length >= 1)
|
||||
{
|
||||
instance = objects[0];
|
||||
if (objects.Length > 1)
|
||||
{
|
||||
if (instance.Logger.IsErrorEnabled)
|
||||
{
|
||||
instance.Logger.LogError("{0} PhotonVoiceNetwork instances found. Using first one only and destroying all the other extra instances.", objects.Length);
|
||||
}
|
||||
for (int i = 1; i < objects.Length; i++)
|
||||
{
|
||||
Destroy(objects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
instantiated = true;
|
||||
if (instance.Logger.IsDebugEnabled)
|
||||
{
|
||||
instance.Logger.LogDebug("PhotonVoiceNetwork singleton instance is now set.");
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
if (instantiated)
|
||||
{
|
||||
if (instance.Logger.IsErrorEnabled)
|
||||
{
|
||||
instance.Logger.LogError("Cannot set PhotonVoiceNetwork.Instance to null.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Cannot set PhotonVoiceNetwork.Instance to null.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (instantiated)
|
||||
{
|
||||
if (instance.GetInstanceID() != value.GetInstanceID())
|
||||
{
|
||||
if (instance.Logger.IsErrorEnabled)
|
||||
{
|
||||
instance.Logger.LogError("An instance of PhotonVoiceNetwork is already set. Destroying extra instance.");
|
||||
}
|
||||
Destroy(value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
instance = value;
|
||||
instantiated = true;
|
||||
if (instance.Logger.IsDebugEnabled)
|
||||
{
|
||||
instance.Logger.LogDebug("PhotonVoiceNetwork singleton instance is now set.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to use the same PhotonNetwork.AuthValues in PhotonVoiceNetwork.Instance.Client.AuthValues.
|
||||
/// This means that the same UserID will be used in both clients.
|
||||
/// If custom authentication is used and setup in PUN app, the same configuration should be done for the Voice app.
|
||||
/// </summary>
|
||||
public bool UsePunAuthValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.usePunAuthValues;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.usePunAuthValues = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Connect voice client to Photon servers and join a Voice room
|
||||
/// </summary>
|
||||
/// <returns>If true, connection command send from client</returns>
|
||||
public bool ConnectAndJoinRoom()
|
||||
{
|
||||
if (!PhotonNetwork.InRoom)
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Cannot connect and join if PUN is not joined.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (this.Connect())
|
||||
{
|
||||
this.clientCalledConnectAndJoin = true;
|
||||
this.clientCalledDisconnect = false;
|
||||
return true;
|
||||
}
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Connecting to server failed.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect voice client from all Photon servers
|
||||
/// </summary>
|
||||
public void Disconnect()
|
||||
{
|
||||
if (!this.Client.IsConnected)
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Cannot Disconnect if not connected.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.clientCalledDisconnect = true;
|
||||
this.clientCalledConnectAndJoin = false;
|
||||
this.clientCalledConnectOnly = false;
|
||||
this.Client.Disconnect();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (instantiated && instance.GetInstanceID() == this.GetInstanceID())
|
||||
{
|
||||
base.Awake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
PhotonNetwork.NetworkingClient.StateChanged += this.OnPunStateChanged;
|
||||
this.FollowPun(); // in case this is enabled or activated late
|
||||
this.clientCalledConnectAndJoin = false;
|
||||
this.clientCalledConnectOnly = false;
|
||||
this.clientCalledDisconnect = false;
|
||||
this.internalDisconnect = false;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
PhotonNetwork.NetworkingClient.StateChanged -= this.OnPunStateChanged;
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
lock (instanceLock)
|
||||
{
|
||||
if (instantiated && instance.GetInstanceID() == this.GetInstanceID())
|
||||
{
|
||||
instantiated = false;
|
||||
if (instance.Logger.IsDebugEnabled)
|
||||
{
|
||||
instance.Logger.LogDebug("PhotonVoiceNetwork singleton instance is being reset because destroyed.");
|
||||
}
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPunStateChanged(ClientState fromState, ClientState toState)
|
||||
{
|
||||
if (this.Logger.IsDebugEnabled)
|
||||
{
|
||||
this.Logger.LogDebug("OnPunStateChanged from {0} to {1}", fromState, toState);
|
||||
}
|
||||
this.FollowPun(toState);
|
||||
}
|
||||
|
||||
protected override void OnVoiceStateChanged(ClientState fromState, ClientState toState)
|
||||
{
|
||||
base.OnVoiceStateChanged(fromState, toState);
|
||||
if (toState == ClientState.Disconnected)
|
||||
{
|
||||
if (this.internalDisconnect)
|
||||
{
|
||||
this.internalDisconnect = false;
|
||||
}
|
||||
else if (!this.clientCalledDisconnect)
|
||||
{
|
||||
this.clientCalledDisconnect = this.Client.DisconnectedCause == DisconnectCause.DisconnectByClientLogic;
|
||||
}
|
||||
}
|
||||
else if (toState == ClientState.ConnectedToMasterServer)
|
||||
{
|
||||
if (this.internalConnect)
|
||||
{
|
||||
this.internalConnect = false;
|
||||
}
|
||||
else if (!this.clientCalledConnectOnly && !this.clientCalledConnectAndJoin)
|
||||
{
|
||||
this.clientCalledConnectOnly = true;
|
||||
this.clientCalledDisconnect = false;
|
||||
}
|
||||
}
|
||||
this.FollowPun(toState);
|
||||
}
|
||||
|
||||
private void FollowPun(ClientState toState)
|
||||
{
|
||||
switch (toState)
|
||||
{
|
||||
case ClientState.Joined:
|
||||
case ClientState.Disconnected:
|
||||
case ClientState.ConnectedToMasterServer:
|
||||
this.FollowPun();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Speaker SimpleSpeakerFactory(int playerId, byte voiceId, object userData)
|
||||
{
|
||||
if (!(userData is int))
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("UserData ({0}) does not contain PhotonViewId. Remote voice {1}/{2} not linked. Do you have a Recorder not used with a PhotonVoiceView? is this expected?",
|
||||
userData == null ? "null" : userData.ToString(), playerId, voiceId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int photonViewId = (int)userData;
|
||||
PhotonView photonView = PhotonView.Find(photonViewId);
|
||||
if (photonView == null)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("No PhotonView with ID {0} found. Remote voice {1}/{2} not linked.", userData, playerId, voiceId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
PhotonVoiceView photonVoiceView = photonView.GetComponent<PhotonVoiceView>();
|
||||
if (photonVoiceView == null)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("No PhotonVoiceView attached to the PhotonView with ID {0}. Remote voice {1}/{2} not linked.", userData, playerId, voiceId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (!photonVoiceView.IgnoreGlobalLogLevel)
|
||||
{
|
||||
photonVoiceView.LogLevel = this.LogLevel;
|
||||
}
|
||||
if (!photonVoiceView.IsSpeaker)
|
||||
{
|
||||
photonVoiceView.SetupSpeakerInUse();
|
||||
}
|
||||
return photonVoiceView.SpeakerInUse;
|
||||
}
|
||||
|
||||
internal static string GetVoiceRoomName()
|
||||
{
|
||||
if (PhotonNetwork.InRoom)
|
||||
{
|
||||
return string.Format("{0}{1}", PhotonNetwork.CurrentRoom.Name, VoiceRoomNameSuffix);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ConnectOrJoin()
|
||||
{
|
||||
switch (this.ClientState)
|
||||
{
|
||||
case ClientState.PeerCreated:
|
||||
case ClientState.Disconnected:
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("PUN joined room, now connecting Voice client");
|
||||
}
|
||||
if (!this.Connect())
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Connecting to server failed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.internalConnect = this.AutoConnectAndJoin && !this.clientCalledConnectOnly && !this.clientCalledConnectAndJoin;
|
||||
}
|
||||
break;
|
||||
case ClientState.ConnectedToMasterServer:
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("PUN joined room, now joining Voice room");
|
||||
}
|
||||
if (!this.JoinRoom(GetVoiceRoomName()))
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Joining a voice room failed.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("PUN joined room, Voice client is busy ({0}). Is this expected?", this.ClientState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool Connect()
|
||||
{
|
||||
AppSettings settings = null;
|
||||
|
||||
if (this.usePunAppSettings)
|
||||
{
|
||||
settings = new AppSettings();
|
||||
settings = PhotonNetwork.PhotonServerSettings.AppSettings.CopyTo(settings); // creates an independent copy (cause we need to modify it slightly)
|
||||
if (!string.IsNullOrEmpty(PhotonNetwork.CloudRegion))
|
||||
{
|
||||
settings.FixedRegion = PhotonNetwork.CloudRegion; // makes sure the voice connection follows into the same cloud region (as PUN uses now).
|
||||
}
|
||||
|
||||
this.Client.SerializationProtocol = PhotonNetwork.NetworkingClient.SerializationProtocol;
|
||||
}
|
||||
|
||||
// use the same user, authentication, auth-mode and encryption as PUN
|
||||
if (this.UsePunAuthValues)
|
||||
{
|
||||
if (PhotonNetwork.AuthValues != null)
|
||||
{
|
||||
if (this.Client.AuthValues == null)
|
||||
{
|
||||
this.Client.AuthValues = new AuthenticationValues();
|
||||
}
|
||||
this.Client.AuthValues = PhotonNetwork.AuthValues.CopyTo(this.Client.AuthValues);
|
||||
}
|
||||
this.Client.AuthMode = PhotonNetwork.NetworkingClient.AuthMode;
|
||||
this.Client.EncryptionMode = PhotonNetwork.NetworkingClient.EncryptionMode;
|
||||
}
|
||||
|
||||
return this.ConnectUsingSettings(settings);
|
||||
}
|
||||
|
||||
private bool JoinRoom(string voiceRoomName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(voiceRoomName))
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Voice room name is null or empty.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this.voiceRoomParams.RoomName = voiceRoomName;
|
||||
return this.Client.OpJoinOrCreateRoom(this.voiceRoomParams);
|
||||
}
|
||||
|
||||
// Follow PUN client state
|
||||
// In case Voice client disconnects unexpectedly try to reconnect to the same room
|
||||
// In case Voice client is connected to the wrong room switch to the correct one
|
||||
private void FollowPun()
|
||||
{
|
||||
if (AppQuits)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (PhotonNetwork.OfflineMode && !this.WorkInOfflineMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (PhotonNetwork.NetworkClientState == this.ClientState)
|
||||
{
|
||||
if (PhotonNetwork.InRoom && this.AutoConnectAndJoin)
|
||||
{
|
||||
string expectedRoomName = GetVoiceRoomName();
|
||||
string currentRoomName = this.Client.CurrentRoom.Name;
|
||||
if (!currentRoomName.Equals(expectedRoomName))
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning(
|
||||
"Voice room mismatch: Expected:\"{0}\" Current:\"{1}\", leaving the second to join the first.",
|
||||
expectedRoomName, currentRoomName);
|
||||
}
|
||||
if (!this.Client.OpLeaveRoom(false))
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("Leaving the current voice room failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.ClientState == ClientState.ConnectedToMasterServer && this.AutoLeaveAndDisconnect && !this.clientCalledConnectAndJoin && !this.clientCalledConnectOnly)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Unexpected: PUN and Voice clients have the same client state: ConnectedToMasterServer, Disconnecting Voice client.");
|
||||
}
|
||||
this.internalDisconnect = true;
|
||||
this.Client.Disconnect();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (PhotonNetwork.InRoom)
|
||||
{
|
||||
if (this.clientCalledConnectAndJoin || this.AutoConnectAndJoin && !this.clientCalledDisconnect)
|
||||
{
|
||||
this.ConnectOrJoin();
|
||||
}
|
||||
}
|
||||
else if (this.Client.InRoom && this.AutoLeaveAndDisconnect && !this.clientCalledConnectAndJoin && !this.clientCalledConnectOnly)
|
||||
{
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("PUN left room, disconnecting Voice");
|
||||
}
|
||||
this.internalDisconnect = true;
|
||||
this.Client.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
internal void CheckLateLinking(Speaker speaker, int viewId)
|
||||
{
|
||||
if (!speaker || speaker == null)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Cannot check late linking for null Speaker");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (viewId <= 0)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Cannot check late linking for ViewID = {0} (<= 0)", viewId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!this.Client.InRoom)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Cannot check late linking while not joined to a voice room, client state: {0}", System.Enum.GetName(typeof(ClientState), this.ClientState));
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < this.cachedRemoteVoices.Count; i++)
|
||||
{
|
||||
RemoteVoiceLink remoteVoice = this.cachedRemoteVoices[i];
|
||||
if (remoteVoice.Info.UserData is int)
|
||||
{
|
||||
int photonViewId = (int)remoteVoice.Info.UserData;
|
||||
if (viewId == photonViewId)
|
||||
{
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("Speaker 'late-linking' for the PhotonView with ID {0} with remote voice {1}/{2}.", viewId, remoteVoice.PlayerId, remoteVoice.VoiceId);
|
||||
}
|
||||
this.LinkSpeaker(speaker, remoteVoice);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("VoiceInfo.UserData should be int/ViewId, received: {0}, do you have a Recorder not used with a PhotonVoiceView? is this expected?",
|
||||
remoteVoice.Info.UserData == null ? "null" : string.Format("{0} ({1})", remoteVoice.Info.UserData, remoteVoice.Info.UserData.GetType()));
|
||||
if (remoteVoice.PlayerId == viewId / PhotonNetwork.MAX_VIEW_IDS)
|
||||
{
|
||||
this.Logger.LogWarning("Player with ActorNumber {0} has started recording (voice # {1}) too early without setting a ViewId maybe? (before PhotonVoiceView setup)", remoteVoice.PlayerId, remoteVoice.VoiceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81d9debcbaf99472bb70ffc2f99cb23f
|
||||
timeCreated: 1540904568
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: dd940d333aeeaa048842e87b9b259188, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
501
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoiceView.cs
Normal file
501
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoiceView.cs
Normal file
@@ -0,0 +1,501 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// <copyright file="PhotonVoiceView.cs" company="Exit Games GmbH">
|
||||
// Photon Voice - Copyright (C) 2018 Exit Games GmbH
|
||||
// </copyright>
|
||||
// <summary>
|
||||
// Component that should be attached to a networked PUN prefab that has
|
||||
// PhotonView. It will bind remote Recorder with local Speaker of the same
|
||||
// networked prefab. This component makes automatic voice stream routing easy
|
||||
// for players' characters/avatars.
|
||||
// </summary>
|
||||
// <author>developer@photonengine.com</author>
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace Photon.Voice.PUN
|
||||
{
|
||||
using Pun;
|
||||
using UnityEngine;
|
||||
using Unity;
|
||||
|
||||
/// <summary>
|
||||
/// Component that should be attached to a networked PUN prefab that has <see cref="PhotonView"/>.
|
||||
/// It will bind remote <see cref="Recorder"/> with local <see cref="Speaker"/> of the same networked prefab.
|
||||
/// This component makes automatic voice stream routing easy for players' characters/avatars.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Photon Voice/Photon Voice View")]
|
||||
[RequireComponent(typeof(PhotonView))]
|
||||
[HelpURL("https://doc.photonengine.com/en-us/voice/v2/getting-started/voice-for-pun")]
|
||||
public class PhotonVoiceView : VoiceComponent
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private PhotonView photonView;
|
||||
|
||||
[SerializeField]
|
||||
private Recorder recorderInUse;
|
||||
|
||||
[SerializeField]
|
||||
private Speaker speakerInUse;
|
||||
|
||||
private bool onEnableCalledOnce;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary> If true, a Recorder component will be added to the same GameObject if not found already. </summary>
|
||||
public bool AutoCreateRecorderIfNotFound;
|
||||
/// <summary> If true, PhotonVoiceNetwork.PrimaryRecorder will be used by this PhotonVoiceView </summary>
|
||||
public bool UsePrimaryRecorder;
|
||||
/// <summary> If true, a Speaker component will be setup to be used for the DebugEcho mode </summary>
|
||||
public bool SetupDebugSpeaker;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary> The Recorder component currently used by this PhotonVoiceView </summary>
|
||||
public Recorder RecorderInUse
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.recorderInUse;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != this.recorderInUse)
|
||||
{
|
||||
this.recorderInUse = value;
|
||||
this.IsRecorder = false;
|
||||
}
|
||||
if (this.RequiresRecorder)
|
||||
{
|
||||
this.SetupRecorderInUse();
|
||||
}
|
||||
else if (this.IsPhotonViewReady)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("No need to set Recorder as the PhotonView does not belong to local player");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> The Speaker component currently used by this PhotonVoiceView </summary>
|
||||
public Speaker SpeakerInUse
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.speakerInUse;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (this.speakerInUse != value)
|
||||
{
|
||||
this.speakerInUse = value;
|
||||
this.IsSpeaker = false;
|
||||
}
|
||||
if (this.RequiresSpeaker)
|
||||
{
|
||||
this.SetupSpeakerInUse();
|
||||
}
|
||||
else if (this.IsPhotonViewReady)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Speaker not set because the PhotonView does not belong to a remote player or SetupDebugSpeaker is disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> If true, this PhotonVoiceView is setup and ready to be used </summary>
|
||||
public bool IsSetup
|
||||
{
|
||||
get { return this.IsPhotonViewReady && (!this.RequiresRecorder || this.IsRecorder) && (!this.RequiresSpeaker || this.IsSpeaker); }
|
||||
}
|
||||
/// <summary> If true, this PhotonVoiceView has a Speaker setup for playback of received audio frames from remote audio source </summary>
|
||||
public bool IsSpeaker { get; private set; }
|
||||
/// <summary> If true, this PhotonVoiceView has a Speaker that is currently playing received audio frames from remote audio source </summary>
|
||||
public bool IsSpeaking
|
||||
{
|
||||
get { return this.IsSpeaker && this.SpeakerInUse.IsPlaying; }
|
||||
}
|
||||
/// <summary> If true, this PhotonVoiceView has a Recorder setup for transmission of audio stream from local audio source </summary>
|
||||
public bool IsRecorder { get; private set; }
|
||||
/// <summary> If true, this PhotonVoiceView has a Recorder that is currently transmitting audio stream from local audio source </summary>
|
||||
public bool IsRecording
|
||||
{
|
||||
get { return this.IsRecorder && this.RecorderInUse.IsCurrentlyTransmitting; }
|
||||
}
|
||||
/// <summary> If true, the SpeakerInUse is linked to the remote voice stream </summary>
|
||||
public bool IsSpeakerLinked
|
||||
{
|
||||
get { return this.IsSpeaker && this.SpeakerInUse.IsLinked; }
|
||||
}
|
||||
/// <summary> If true, the PhotonView attached to the same GameObject has a valid ViewID > 0 </summary>
|
||||
public bool IsPhotonViewReady
|
||||
{
|
||||
get { return this.photonView && this.photonView != null && this.photonView.ViewID > 0; }
|
||||
}
|
||||
|
||||
internal bool RequiresSpeaker
|
||||
{
|
||||
get { return this.SetupDebugSpeaker || this.IsPhotonViewReady && !this.photonView.IsMine; }
|
||||
}
|
||||
|
||||
internal bool RequiresRecorder
|
||||
{
|
||||
get { return this.IsPhotonViewReady && this.photonView.IsMine; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
this.photonView = this.GetComponent<PhotonView>();
|
||||
this.Init();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (this.onEnableCalledOnce)
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.onEnableCalledOnce = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
private void CheckLateLinking()
|
||||
{
|
||||
if (PhotonVoiceNetwork.Instance.Client.InRoom)
|
||||
{
|
||||
if (this.IsSpeaker)
|
||||
{
|
||||
if (!this.IsSpeakerLinked)
|
||||
{
|
||||
PhotonVoiceNetwork.Instance.CheckLateLinking(this.SpeakerInUse, this.photonView.ViewID);
|
||||
}
|
||||
else if (this.Logger.IsDebugEnabled)
|
||||
{
|
||||
this.Logger.LogDebug("Speaker already linked");
|
||||
}
|
||||
}
|
||||
else if (this.Logger.IsDebugEnabled)
|
||||
{
|
||||
this.Logger.LogDebug("PhotonVoiceView does not have a Speaker and may not need late linking check");
|
||||
}
|
||||
}
|
||||
else if (this.Logger.IsDebugEnabled)
|
||||
{
|
||||
this.Logger.LogDebug("Voice client is still not in a room, skipping late linking check");
|
||||
}
|
||||
}
|
||||
|
||||
internal void Setup()
|
||||
{
|
||||
if (this.IsSetup)
|
||||
{
|
||||
if (this.Logger.IsDebugEnabled)
|
||||
{
|
||||
this.Logger.LogDebug("PhotonVoiceView already setup");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.SetupRecorderInUse();
|
||||
this.SetupSpeakerInUse();
|
||||
}
|
||||
|
||||
private bool SetupRecorder()
|
||||
{
|
||||
if (this.recorderInUse == null) // not manually assigned by user
|
||||
{
|
||||
if (this.UsePrimaryRecorder)
|
||||
{
|
||||
if (PhotonVoiceNetwork.Instance.PrimaryRecorder != null)
|
||||
{
|
||||
this.recorderInUse = PhotonVoiceNetwork.Instance.PrimaryRecorder;
|
||||
return this.SetupRecorder(this.recorderInUse);
|
||||
}
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("PrimaryRecorder is not set.");
|
||||
}
|
||||
}
|
||||
Recorder[] recorders = this.GetComponentsInChildren<Recorder>();
|
||||
if (recorders.Length > 0)
|
||||
{
|
||||
this.recorderInUse = recorders[0];
|
||||
if (recorders.Length > 1 && this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Multiple Recorder components found attached to the GameObject or its children.");
|
||||
}
|
||||
return this.SetupRecorder(this.recorderInUse);
|
||||
}
|
||||
if (!this.AutoCreateRecorderIfNotFound)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("No Recorder found to be setup.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this.recorderInUse = this.gameObject.AddComponent<Recorder>();
|
||||
}
|
||||
return this.SetupRecorder(this.recorderInUse);
|
||||
}
|
||||
|
||||
private bool SetupRecorder(Recorder recorder)
|
||||
{
|
||||
if (recorder == null)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Cannot setup a null Recorder.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!this.IsPhotonViewReady)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Recorder setup cannot be done before assigning a valid ViewID to the PhotonView attached to the same GameObject as the PhotonVoiceView.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
recorder.UserData = this.photonView.ViewID;
|
||||
if (!recorder.IsInitialized)
|
||||
{
|
||||
this.RecorderInUse.Init(PhotonVoiceNetwork.Instance);
|
||||
}
|
||||
if (recorder.RequiresRestart)
|
||||
{
|
||||
recorder.RestartRecording();
|
||||
}
|
||||
return recorder.IsInitialized && recorder.UserData is int && this.photonView.ViewID == (int) recorder.UserData;
|
||||
}
|
||||
|
||||
private bool SetupSpeaker()
|
||||
{
|
||||
if (this.speakerInUse == null) // not manually assigned by user
|
||||
{
|
||||
Speaker[] speakers = this.GetComponentsInChildren<Speaker>(true);
|
||||
if (speakers.Length > 0)
|
||||
{
|
||||
this.speakerInUse = speakers[0];
|
||||
if (speakers.Length > 1 && this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Multiple Speaker components found attached to the GameObject or its children. Using the first one we found.");
|
||||
}
|
||||
}
|
||||
if (this.speakerInUse == null)
|
||||
{
|
||||
if (!PhotonVoiceNetwork.Instance.AutoCreateSpeakerIfNotFound)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (PhotonVoiceNetwork.Instance.SpeakerPrefab != null)
|
||||
{
|
||||
GameObject go = Instantiate(PhotonVoiceNetwork.Instance.SpeakerPrefab, this.transform, false);
|
||||
speakers = go.GetComponentsInChildren<Speaker>(true);
|
||||
if (speakers.Length > 0)
|
||||
{
|
||||
this.speakerInUse = speakers[0];
|
||||
if (speakers.Length > 1 && this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Multiple Speaker components found attached to the GameObject (PhotonVoiceNetwork.SpeakerPrefab) or its children. Using the first one we found.");
|
||||
}
|
||||
}
|
||||
if (this.speakerInUse == null)
|
||||
{
|
||||
if (this.Logger.IsErrorEnabled)
|
||||
{
|
||||
this.Logger.LogError("SpeakerPrefab does not have a component of type Speaker in its hierarchy.");
|
||||
}
|
||||
Destroy(go);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.speakerInUse = this.gameObject.AddComponent<Speaker>();
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.SetupSpeaker(this.speakerInUse);
|
||||
}
|
||||
|
||||
private bool SetupSpeaker(Speaker speaker)
|
||||
{
|
||||
if (speaker == null)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Cannot setup a null Speaker");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
AudioSource audioSource = speaker.GetComponent<AudioSource>();
|
||||
if (audioSource == null)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Unexpected: no AudioSource found attached to the same GameObject as the Speaker component");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (audioSource.mute)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("audioSource.mute is true, playback may not work properly");
|
||||
}
|
||||
}
|
||||
if (audioSource.volume <= 0f)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("audioSource.volume is zero, playback may not work properly");
|
||||
}
|
||||
}
|
||||
if (!audioSource.enabled)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("audioSource.enabled is false, playback may not work properly");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void SetupRecorderInUse()
|
||||
{
|
||||
if (this.IsRecorder)
|
||||
{
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("Recorder already setup");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!this.RequiresRecorder)
|
||||
{
|
||||
if (this.IsPhotonViewReady)
|
||||
{
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("Recorder not needed");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.IsRecorder = this.SetupRecorder();
|
||||
if (!this.IsRecorder)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Recorder not setup for PhotonVoiceView: playback may not work properly.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.RecorderInUse.IsRecording && !this.RecorderInUse.AutoStart)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("PhotonVoiceView.RecorderInUse.AutoStart is false, don't forget to start recording manually using recorder.StartRecording() or recorder.IsRecording = true.");
|
||||
}
|
||||
}
|
||||
if (!this.RecorderInUse.TransmitEnabled)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("PhotonVoiceView.RecorderInUse.TransmitEnabled is false, don't forget to set it to true to enable transmission.");
|
||||
}
|
||||
}
|
||||
if (!this.RecorderInUse.isActiveAndEnabled && this.RecorderInUse.RecordOnlyWhenEnabled)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("PhotonVoiceView.RecorderInUse may not work properly as RecordOnlyWhenEnabled is set to true and recorder is disabled or attached to an inactive GameObject.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetupSpeakerInUse()
|
||||
{
|
||||
if (this.IsSpeaker)
|
||||
{
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("Speaker already setup");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!this.RequiresSpeaker)
|
||||
{
|
||||
if (this.IsPhotonViewReady)
|
||||
{
|
||||
if (this.Logger.IsInfoEnabled)
|
||||
{
|
||||
this.Logger.LogInfo("Speaker not needed");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.IsSpeaker = this.SetupSpeaker();
|
||||
if (!this.IsSpeaker)
|
||||
{
|
||||
if (this.Logger.IsWarningEnabled)
|
||||
{
|
||||
this.Logger.LogWarning("Speaker not setup for PhotonVoiceView: voice chat will not work.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CheckLateLinking();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this PhotonVoiceView for Voice usage based on the PhotonView, Recorder and Speaker components.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The initialization should happen automatically.
|
||||
/// Call this method explicitly if this does not succeed.
|
||||
/// The initialization is a two steps operation: step one is the setup of Recorder and Speaker to be used.
|
||||
/// Step two is the late-linking -if needed- of the SpeakerInUse and corresponding remote voice info -if any- via ViewID.
|
||||
/// </remarks>
|
||||
public void Init()
|
||||
{
|
||||
if (this.IsPhotonViewReady)
|
||||
{
|
||||
this.Setup();
|
||||
this.CheckLateLinking();
|
||||
}
|
||||
else if (this.Logger.IsDebugEnabled)
|
||||
{
|
||||
this.Logger.LogDebug("Tried to initialize PhotonVoiceView but PhotonView does not have a valid allocated ViewID yet.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
12
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoiceView.cs.meta
Normal file
12
Assets/Photon/PhotonVoice/Code/PUN/PhotonVoiceView.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 126494ae2a10a34499272ed97a6c9f5d
|
||||
timeCreated: 1540904580
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: dd940d333aeeaa048842e87b9b259188, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Photon/PhotonVoice/Code/PUN/UtilityScripts.meta
Normal file
8
Assets/Photon/PhotonVoice/Code/PUN/UtilityScripts.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22faa279621bc10479cc398c2447f370
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,242 @@
|
||||
namespace Photon.Voice.PUN.UtilityScripts
|
||||
{
|
||||
using Pun;
|
||||
using Unity;
|
||||
using Realtime;
|
||||
using UnityEngine;
|
||||
using ExitGames.Client.Photon;
|
||||
|
||||
/// <summary> Utility script to be attached next to PhotonVoiceView & PhotonView on the player prefab to be network instantiated.
|
||||
/// Call voiceDebugScript.CantHearYou() on the networked object of the remote (or local) player if you can't hear the corresponding player. </summary>
|
||||
[RequireComponent(typeof(PhotonVoiceView))]
|
||||
public class VoiceDebugScript : MonoBehaviourPun
|
||||
{
|
||||
private PhotonVoiceView photonVoiceView;
|
||||
|
||||
/// <summary> Make sure recorder.TransmitEnabled and recorder.IsRecording are true. </summary>
|
||||
public bool ForceRecordingAndTransmission;
|
||||
|
||||
/// <summary> Audio file to be broadcast when TestUsingAudioClip is enabled. </summary>
|
||||
public AudioClip TestAudioClip;
|
||||
|
||||
/// <summary> Broadcast Audio file to make sure transmission over network works if microphone (audio input device/hardware) is not reliable. Requires setting AudioClip in TestAudioClip. </summary>
|
||||
public bool TestUsingAudioClip;
|
||||
|
||||
/// <summary> Disable recorder.VoiceDetection for easier testing. </summary>
|
||||
public bool DisableVad;
|
||||
|
||||
/// <summary> Set main voice component's log level to ALL (max). </summary>
|
||||
public bool IncreaseLogLevels;
|
||||
|
||||
/// <summary> Debug DebugEcho mode (Can't Hear My Self?!). </summary>
|
||||
public bool LocalDebug;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
this.photonVoiceView = this.GetComponent<PhotonVoiceView>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
this.MaxLogs();
|
||||
if (this.photonVoiceView.IsRecorder)
|
||||
{
|
||||
if (this.TestUsingAudioClip)
|
||||
{
|
||||
if (!this.TestAudioClip || this.TestAudioClip == null)
|
||||
{
|
||||
Debug.LogError("Set an AudioClip first");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.photonVoiceView.RecorderInUse.SourceType = Recorder.InputSourceType.AudioClip;
|
||||
this.photonVoiceView.RecorderInUse.AudioClip = this.TestAudioClip;
|
||||
this.photonVoiceView.RecorderInUse.LoopAudioClip = true;
|
||||
if (this.photonVoiceView.RecorderInUse.RequiresRestart)
|
||||
{
|
||||
this.photonVoiceView.RecorderInUse.RestartRecording();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.photonVoiceView.RecorderInUse.StartRecording();
|
||||
}
|
||||
this.photonVoiceView.RecorderInUse.TransmitEnabled = true;
|
||||
}
|
||||
}
|
||||
if (this.ForceRecordingAndTransmission)
|
||||
{
|
||||
this.photonVoiceView.RecorderInUse.IsRecording = true;
|
||||
this.photonVoiceView.RecorderInUse.TransmitEnabled = true;
|
||||
}
|
||||
if (this.DisableVad)
|
||||
{
|
||||
this.photonVoiceView.RecorderInUse.VoiceDetection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("CantHearYou")]
|
||||
public void CantHearYou()
|
||||
{
|
||||
if (!PhotonVoiceNetwork.Instance.Client.InRoom)
|
||||
{
|
||||
Debug.LogError("local voice client is not joined to a voice room");
|
||||
}
|
||||
else if (!this.photonVoiceView.IsPhotonViewReady)
|
||||
{
|
||||
Debug.LogError("PhotonView is not ready yet; maybe PUN client is not joined to a room yet or this PhotonView is not valid");
|
||||
}
|
||||
else if (!this.photonVoiceView.IsSpeaker)
|
||||
{
|
||||
if (this.photonView.IsMine && !this.photonVoiceView.SetupDebugSpeaker)
|
||||
{
|
||||
Debug.LogError("local object does not have SetupDebugSpeaker enabled");
|
||||
if (this.LocalDebug)
|
||||
{
|
||||
Debug.Log("setup debug speaker not enabled, enabling it now (1)");
|
||||
this.photonVoiceView.SetupDebugSpeaker = true;
|
||||
this.photonVoiceView.Setup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("locally not speaker (yet?) (1)");
|
||||
this.photonVoiceView.Setup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.photonVoiceView.IsSpeakerLinked)
|
||||
{
|
||||
Debug.LogError("locally speaker not linked, trying late linking & asking anyway");
|
||||
// late linking maybe
|
||||
PhotonVoiceNetwork.Instance.CheckLateLinking(this.photonVoiceView.SpeakerInUse, this.photonView.ViewID);
|
||||
}
|
||||
this.photonView.RPC("CantHearYou", this.photonView.Owner, PhotonVoiceNetwork.Instance.Client.CurrentRoom.Name, PhotonVoiceNetwork.Instance.Client.LoadBalancingPeer.ServerIpAddress, PhotonVoiceNetwork.Instance.Client.AppVersion);
|
||||
}
|
||||
}
|
||||
|
||||
[PunRPC]
|
||||
private void CantHearYou(string roomName, string serverIp, string appVersion, PhotonMessageInfo photonMessageInfo)
|
||||
{
|
||||
string why;
|
||||
if (!PhotonVoiceNetwork.Instance.Client.InRoom)
|
||||
{
|
||||
why = "voice client not in a room";
|
||||
}
|
||||
else if (!PhotonVoiceNetwork.Instance.Client.CurrentRoom.Name.Equals(roomName))
|
||||
{
|
||||
why = string.Format("voice client is on another room {0} != {1}",
|
||||
PhotonVoiceNetwork.Instance.Client.CurrentRoom.Name, roomName);
|
||||
}
|
||||
else if (!PhotonVoiceNetwork.Instance.Client.LoadBalancingPeer.ServerIpAddress.Equals(serverIp))
|
||||
{
|
||||
why = string.Format("voice client is on another server {0} != {1}, maybe different Photon Cloud regions",
|
||||
PhotonVoiceNetwork.Instance.Client.LoadBalancingPeer.ServerIpAddress, serverIp);
|
||||
}
|
||||
else if (!PhotonVoiceNetwork.Instance.Client.AppVersion.Equals(appVersion))
|
||||
{
|
||||
why = string.Format("voice client uses different AppVersion {0} != {1}",
|
||||
PhotonVoiceNetwork.Instance.Client.AppVersion, appVersion);
|
||||
}
|
||||
else if (!this.photonVoiceView.IsRecorder)
|
||||
{
|
||||
why = "recorder not setup (yet?)";
|
||||
this.photonVoiceView.Setup();
|
||||
}
|
||||
else if (!this.photonVoiceView.RecorderInUse.IsRecording)
|
||||
{
|
||||
why = "recorder is not recording";
|
||||
this.photonVoiceView.RecorderInUse.IsRecording = true;
|
||||
}
|
||||
else if (!this.photonVoiceView.RecorderInUse.TransmitEnabled)
|
||||
{
|
||||
why = "recorder is not transmitting";
|
||||
this.photonVoiceView.RecorderInUse.TransmitEnabled = true;
|
||||
}
|
||||
else if (this.photonVoiceView.RecorderInUse.InterestGroup != 0)
|
||||
{
|
||||
why = "recorder.InterestGroup is not zero? is this on purpose? switching it back to zero";
|
||||
this.photonVoiceView.RecorderInUse.InterestGroup = 0;
|
||||
}
|
||||
else if (!(this.photonVoiceView.RecorderInUse.UserData is int) || (int)this.photonVoiceView.RecorderInUse.UserData != this.photonView.ViewID)
|
||||
{
|
||||
why = string.Format("recorder.UserData ({0}) != photonView.ViewID ({1}), fixing it now", this.photonVoiceView.RecorderInUse.UserData, this.photonView.ViewID);
|
||||
this.photonVoiceView.RecorderInUse.UserData = this.photonView.ViewID;
|
||||
this.photonVoiceView.RecorderInUse.RestartRecording();
|
||||
}
|
||||
else if (this.photonVoiceView.RecorderInUse.VoiceDetection && this.DisableVad) // todo: check WebRtcAudioDsp.VAD
|
||||
{
|
||||
why = "recorder vad is enabled, disable it for testing";
|
||||
this.photonVoiceView.RecorderInUse.VoiceDetection = false;
|
||||
}
|
||||
else if (this.photonView.OwnerActorNr == photonMessageInfo.Sender.ActorNumber)
|
||||
{
|
||||
if (this.LocalDebug)
|
||||
{
|
||||
if (this.photonVoiceView.IsSpeaker)
|
||||
{
|
||||
why = "no idea why!, should be working (1)";
|
||||
this.photonVoiceView.RecorderInUse.RestartRecording(true);
|
||||
}
|
||||
else if (!this.photonVoiceView.SetupDebugSpeaker) // unreachable probably
|
||||
{
|
||||
why = "setup debug speaker not enabled, enabling it now (2)";
|
||||
this.photonVoiceView.SetupDebugSpeaker = true;
|
||||
this.photonVoiceView.Setup();
|
||||
}
|
||||
else if (!this.photonVoiceView.RecorderInUse.DebugEchoMode)
|
||||
{
|
||||
why = "recorder debug echo mode not enabled, enabling it now";
|
||||
this.photonVoiceView.RecorderInUse.DebugEchoMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
why = "locally not speaker (yet?) (2)";
|
||||
this.photonVoiceView.Setup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
why = "local object, are you trying to hear yourself? (feedback DebugEcho), LocalDebug is disabled, enable it if you want to diagnose this";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
why = "no idea why!, should be working (2)";
|
||||
this.photonVoiceView.RecorderInUse.RestartRecording(true);
|
||||
}
|
||||
this.Reply(why, photonMessageInfo.Sender);
|
||||
}
|
||||
|
||||
private void Reply(string why, Player player)
|
||||
{
|
||||
this.photonView.RPC("HeresWhy", player, why);
|
||||
}
|
||||
|
||||
[PunRPC]
|
||||
private void HeresWhy(string why, PhotonMessageInfo photonMessageInfo)
|
||||
{
|
||||
Debug.LogErrorFormat("Player {0} replied to my CantHearYou message with {1}", photonMessageInfo.Sender, why);
|
||||
}
|
||||
|
||||
private void MaxLogs()
|
||||
{
|
||||
if (this.IncreaseLogLevels)
|
||||
{
|
||||
this.photonVoiceView.LogLevel = DebugLevel.ALL;
|
||||
PhotonVoiceNetwork.Instance.LogLevel = DebugLevel.ALL;
|
||||
PhotonVoiceNetwork.Instance.GlobalRecordersLogLevel = DebugLevel.ALL;
|
||||
PhotonVoiceNetwork.Instance.GlobalSpeakersLogLevel = DebugLevel.ALL;
|
||||
if (this.photonVoiceView.IsRecorder)
|
||||
{
|
||||
this.photonVoiceView.RecorderInUse.LogLevel = DebugLevel.ALL;
|
||||
}
|
||||
if (this.photonVoiceView.IsSpeaker)
|
||||
{
|
||||
this.photonVoiceView.SpeakerInUse.LogLevel = DebugLevel.ALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83be82b116045a747bf0141620a4a02f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user