浏览代码

Adding volume controls and muting, though the actual cross-muting isn't yet working since the Vivox IDs aren't being mapped correctly to our Auth IDs yet.

/main/staging/vivox_package_integration
nathaniel.buck@unity3d.com 3 年前
当前提交
a685cb09
共有 17 个文件被更改,包括 297 次插入125 次删除
  1. 14
      Assets/Art/Crown/Crown.png.meta
  2. 14
      Assets/Art/Volume/volumeMuted.png.meta
  3. 14
      Assets/Art/Volume/volumeRings.png.meta
  4. 14
      Assets/Art/Volume/volumeSpeaker.png.meta
  5. 50
      Assets/Prefabs/UI/UserCardPanel.prefab
  6. 64
      Assets/Scenes/mainScene.unity
  7. 14
      Assets/Scripts/Game/GameManager.cs
  8. 32
      Assets/Scripts/Game/LobbyUser.cs
  9. 35
      Assets/Scripts/UI/InLobbyUserUI.cs
  10. 1
      Assets/Scripts/UI/LobbyUserVolumeUI.cs
  11. 2
      Assets/Scripts/UI/MuteUI.cs
  12. 27
      Assets/Scripts/Vivox/VivoxSetup.cs
  13. 28
      Assets/Scripts/Game/LobbyUserAudio.cs
  14. 79
      Assets/Scripts/Vivox/VivoxUserHandler.cs
  15. 11
      Assets/Scripts/Vivox/VivoxUserHandler.cs.meta
  16. 23
      Assets/Scripts/Game/LocalUserAudio.cs
  17. 0
      /Assets/Scripts/Game/LobbyUserAudio.cs.meta

14
Assets/Art/Crown/Crown.png.meta


serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0

platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1

14
Assets/Art/Volume/volumeMuted.png.meta


serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0

platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1

14
Assets/Art/Volume/volumeRings.png.meta


serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0

platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1

14
Assets/Art/Volume/volumeSpeaker.png.meta


serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0

platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1

50
Assets/Prefabs/UI/UserCardPanel.prefab


- component: {fileID: 5235189765028238254}
- component: {fileID: 788426075660952210}
- component: {fileID: 7885056472121154813}
- component: {fileID: 4826507163535553981}
m_Layer: 5
m_Name: UserCardPanel
m_TagString: Untagged

m_StatusText: {fileID: 3667934756810823183}
m_EmoteText: {fileID: 7097926522474954833}
m_HostIcon: {fileID: 2063326445664711249}
m_MuteUI: {fileID: 5371667691979465528}
m_lobbyUserVolumeUI: {fileID: 7750493951695561362}
m_vivoxUserHandler: {fileID: 4826507163535553981}
--- !u!114 &788426075660952210
MonoBehaviour:
m_ObjectHideFlags: 0

m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!114 &4826507163535553981
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1767503274657767312}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 78d292f3bd9f1614cb744dcb4fe3ac12, type: 3}
m_Name:
m_EditorClassIdentifier:
m_MuteUI: {fileID: 5371667691979465528}
m_lobbyUserVolumeUI: {fileID: 7750493951695561362}
--- !u!1 &3010031715874034773
GameObject:
m_ObjectHideFlags: 0

m_EditorClassIdentifier:
m_onVisibilityChange:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 0}
m_TargetAssemblyTypeName:
m_MethodName:
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName:
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
m_Calls: []
m_voiceRings: {fileID: 1287953984161108202}
--- !u!225 &5564390157418853622
CanvasGroup:

m_GameObject: {fileID: 3010031715874034773}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 0
m_BlocksRaycasts: 0
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!1 &3079367817526768243
GameObject:

onValueChanged:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5235189765028238254}
m_TargetAssemblyTypeName: LobbyRelaySample.UI.InLobbyUserUI, LobbyRelaySample
m_MethodName: OnMuteToggled
- m_Target: {fileID: 4826507163535553981}
m_TargetAssemblyTypeName: LobbyRelaySample.vivox.VivoxUserHandler, LobbyRelaySample
m_MethodName: OnMuteToggle
m_Mode: 0
m_Arguments:
m_ObjectArgument: {fileID: 0}

m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: 125
m_PreferredWidth: 100
m_PreferredHeight: 40
m_FlexibleWidth: -1
m_FlexibleHeight: -1

m_MinValue: 0
m_MaxValue: 1
m_WholeNumbers: 0
m_Value: 0
m_Value: 0.7142857
- m_Target: {fileID: 5235189765028238254}
m_TargetAssemblyTypeName: LobbyRelaySample.UI.InLobbyUserUI, LobbyRelaySample
- m_Target: {fileID: 4826507163535553981}
m_TargetAssemblyTypeName: LobbyRelaySample.vivox.VivoxUserHandler, LobbyRelaySample
m_MethodName: OnVolumeSlide
m_Mode: 0
m_Arguments:

64
Assets/Scenes/mainScene.unity


m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &2637199315837045701 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 4934742474031340841, guid: f1d618bdc6f1813449d428126e640aa5, type: 3}
m_PrefabInstance: {fileID: 2637199315837045693}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 78d292f3bd9f1614cb744dcb4fe3ac12, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &2637199315837045702 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 423528073811505134, guid: f1d618bdc6f1813449d428126e640aa5, type: 3}
m_PrefabInstance: {fileID: 2637199315837045693}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 78d292f3bd9f1614cb744dcb4fe3ac12, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &2637199315837045703 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 3263399567743306352, guid: f1d618bdc6f1813449d428126e640aa5, type: 3}
m_PrefabInstance: {fileID: 2637199315837045693}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 78d292f3bd9f1614cb744dcb4fe3ac12, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &2637199315837045704 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 7123579448709748099, guid: f1d618bdc6f1813449d428126e640aa5, type: 3}
m_PrefabInstance: {fileID: 2637199315837045693}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 78d292f3bd9f1614cb744dcb4fe3ac12, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &7716713812904700119
PrefabInstance:
m_ObjectHideFlags: 0

- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_logMode
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_vivoxUserHandlers.Array.size
value: 4
objectReference: {fileID: 0}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_GameStateObservers.Array.size

propertyPath: m_LocalLobbyObservers.Array.size
value: 10
objectReference: {fileID: 0}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_vivoxUserHandlers.Array.data[0]
value:
objectReference: {fileID: 2637199315837045704}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_vivoxUserHandlers.Array.data[1]
value:
objectReference: {fileID: 2637199315837045703}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_vivoxUserHandlers.Array.data[2]
value:
objectReference: {fileID: 2637199315837045702}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_vivoxUserHandlers.Array.data[3]
value:
objectReference: {fileID: 2637199315837045701}
- target: {fileID: 7716713811812636910, guid: f80fc24bab3dcda459a2669321e2e5a4, type: 3}
propertyPath: m_GameStateObservers.Array.data[0]
value:

14
Assets/Scripts/Game/GameManager.cs


/// </summary>
public class GameManager : MonoBehaviour, IReceiveMessages
{
/// <summary>
/// All these should be assigned the observers in the scene at the start.
/// </summary>
#region UI elements that observe the local state. These are
#region UI elements that observe the local state. These should be assigned the observers in the scene during Start.
[SerializeField]
private List<LocalGameStateObserver> m_GameStateObservers = new List<LocalGameStateObserver>();

private LocalGameState m_localGameState = new LocalGameState();
private LobbyUser m_localUser;
private LocalLobby m_localLobby;
[SerializeField]
private List<vivox.VivoxUserHandler> m_vivoxUserHandlers;
/// <summary>Rather than a setter, this is usable in-editor. It won't accept an enum, however.</summary>
public void SetLobbyColorFilter(int color)

Debug.Log("Signed in.");
m_localUser.ID = Locator.Get.Identity.GetSubIdentity(Auth.IIdentityType.Auth).GetContent("id");
m_localUser.DisplayName = NameGenerator.GetName(m_localUser.ID);
m_vivoxSetup.Initialize(m_vivoxUserHandlers); // Should be before AddPlayer, since that will attempt to set the Vivox ID based on the Auth ID.
m_vivoxSetup.Initialize(null);
}
private void BeginObservers()

m_lobbyContentHeartbeat.BeginTracking(m_localLobby, m_localUser);
SetUserLobbyState();
StartRelayConnection();
m_vivoxSetup.JoinLobbyChannel(m_localLobby.LobbyID);
m_vivoxSetup.JoinLobbyChannel(m_localLobby.LobbyID, null); // TODO: Retry on failure?
}
private void OnLeftLobby()

32
Assets/Scripts/Game/LobbyUser.cs


[Serializable]
public class LobbyUser : Observed<LobbyUser>
{
public LobbyUser(bool isHost = false, string displayName = null, string id = null, EmoteType emote = EmoteType.None, UserStatus userStatus = UserStatus.Menu, bool hasVoice = false)
public LobbyUser(bool isHost = false, string displayName = null, string id = null, EmoteType emote = EmoteType.None, UserStatus userStatus = UserStatus.Menu)
m_data = new UserData(isHost, displayName, id, emote, userStatus, hasVoice);
m_data = new UserData(isHost, displayName, id, emote, userStatus);
}
#region Local UserData

public string ID { get; set; }
public EmoteType Emote { get; set; }
public UserStatus UserStatus { get; set; }
public bool HasVoice { get; set; }
public UserData(bool isHost, string displayName, string id, EmoteType emote, UserStatus userStatus, bool hasVoice)
public UserData(bool isHost, string displayName, string id, EmoteType emote, UserStatus userStatus)
{
IsHost = isHost;
DisplayName = displayName;

HasVoice = hasVoice;
}
}

{
m_data = new UserData(false, m_data.DisplayName, m_data.ID, EmoteType.None, UserStatus.Menu, false); // ID and DisplayName should persist since this might be the local user.
m_data = new UserData(false, m_data.DisplayName, m_data.ID, EmoteType.None, UserStatus.Menu); // ID and DisplayName should persist since this might be the local user.
}
#endregion

DisplayName = 2,
Emote = 4,
ID = 8,
UserStatus = 16,
HasVoice = 32
//TODO Add in lobbyUsers Voice Activity for animation?
UserStatus = 16
}
private UserMembers m_lastChanged;

}
}
public bool HasVoice
{
get { return m_data.HasVoice; }
set
{
if (m_data.HasVoice != value)
{
m_data.HasVoice = value;
m_lastChanged = UserMembers.HasVoice;
OnChanged(this);
}
}
}
public override void CopyObserved(LobbyUser observed)
{
UserData data = observed.m_data;

(m_data.ID == data.ID ? 0 : (int)UserMembers.ID) |
(m_data.Emote == data.Emote ? 0 : (int)UserMembers.Emote) |
(m_data.UserStatus == data.UserStatus ? 0 : (int)UserMembers.UserStatus) |
(m_data.HasVoice == data.HasVoice ? 0 : (int)UserMembers.HasVoice);
(m_data.UserStatus == data.UserStatus ? 0 : (int)UserMembers.UserStatus);
if (lastChanged == 0) // Ensure something actually changed.
return;

35
Assets/Scripts/UI/InLobbyUserUI.cs


using TMPro;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace LobbyRelaySample.UI

Image m_HostIcon;
[SerializeField]
MuteUI m_MuteUI;
[SerializeField]
LobbyUserVolumeUI m_lobbyUserVolumeUI;
LobbyUserAudio m_userAudio = new LobbyUserAudio("None");
vivox.VivoxUserHandler m_vivoxUserHandler;
public bool IsAssigned => UserId != null;

m_observer = GetComponent<LobbyUserObserver>();
m_observer.BeginObserving(myLobbyUser);
UserId = myLobbyUser.ID;
m_userAudio = new LobbyUserAudio(UserId);
m_vivoxUserHandler.SetId(UserId);
}
public void OnUserLeft()

m_observer.EndObserving();
}
public void OnMuteToggled(bool muted)
{
m_userAudio.Muted = muted;
Locator.Get.Messenger.OnReceiveMessage(MessageType.SetPlayerSound, m_userAudio);
}
public void OnVolumeSlide(float volume)
{
m_userAudio.UserVolume = volume;
Locator.Get.Messenger.OnReceiveMessage(MessageType.SetPlayerSound, m_userAudio);
}
public override void ObservedUpdated(LobbyUser observed)
{
m_DisplayNameText.SetText(observed.DisplayName);

SetAudioState(observed.HasVoice);
SetAudioState(true);
}
/// <summary>

{
if (hasVoice)
{
m_MuteUI.EnableVoice();
m_lobbyUserVolumeUI.EnableVoice();
}
else
{
m_MuteUI.DisableVoice();
m_lobbyUserVolumeUI.DisableVoice();
}
// TODO: Disable if vivox is not available, per-user.
}
string SetStatusFancy(UserStatus status)

1
Assets/Scripts/UI/LobbyUserVolumeUI.cs


namespace LobbyRelaySample.UI
{
// TODO: Necessary?
public class LobbyUserVolumeUI : UIPanelBase
{
public void EnableVoice()

2
Assets/Scripts/UI/MuteUI.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace LobbyRelaySample.UI

27
Assets/Scripts/Vivox/VivoxSetup.cs


using System;
using System.Collections.Generic;
using Unity.Services.Vivox;
using VivoxUnity;

private bool m_isMidInitialize = false;
private ILoginSession m_loginSession = null;
private IChannelSession m_channelSession = null;
private List<VivoxUserHandler> m_userHandlers;
/// <param name="onComplete">Called on complete, whether successful or not. Not called if already in the middle of a previous Initialize call.</param>
public void Initialize(Action onComplete)
public void Initialize(List<VivoxUserHandler> userHandlers)
m_userHandlers = userHandlers;
string token = m_loginSession.GetLoginToken();
// TODO: Is BeginLogin guaranteed to call this callback?
catch
{
throw;
}
onComplete?.Invoke(); // TODO: Is BeginLogin guaranteed to call this callback?
}
});
}

/// </summary>
public void JoinLobbyChannel(string lobbyId)
/// <param name="onComplete">Called whether the channel is successfully joined or not.</param>
public void JoinLobbyChannel(string lobbyId, Action<bool> onComplete)
onComplete?.Invoke(false);
return;
}

string token = m_channelSession.GetConnectToken();
onComplete?.Invoke(true);
foreach (VivoxUserHandler userHandler in m_userHandlers)
userHandler.OnChannelJoined(m_channelSession);
// TODO: Reset slider and mute UI on lobby enter
/// <summary>
/// To be called when leaving a lobby.
/// </summary>

m_channelSession?.Disconnect(
(result) => { m_loginSession.DeleteChannelSession(id); }); // TODO: What about if this is called while also trying to connect?
foreach (VivoxUserHandler userHandler in m_userHandlers)
userHandler.OnChannelLeft();
}
/// <summary>

{
// TODO: Also call LeaveLobbyChannel?
if (!m_hasInitialized)
return;
m_loginSession.Logout();

28
Assets/Scripts/Game/LobbyUserAudio.cs


using UnityEngine;
namespace LobbyRelaySample
{
[SerializeField]
public class LobbyUserAudio
{
public string ID { get; private set; }
public bool HasVoice { get; set; }
public bool Muted { get; set; }
// We should explicitly ensure that UserVolume is a normalized value, as letting the volume be set too high could be harmful to listeners.
private float m_userVolume;
public float UserVolume
{
get => m_userVolume;
set => m_userVolume = Mathf.Clamp01(value);
}
public LobbyUserAudio(string userID)
{
ID = userID;
HasVoice = false;
Muted = false;
UserVolume = 50/70f; // Begin at what will be neutral volume given the range of min to max volume.
}
}
}

79
Assets/Scripts/Vivox/VivoxUserHandler.cs


using UnityEngine;
using Unity.Services.Vivox;
using VivoxUnity;
namespace LobbyRelaySample.vivox
{
/// <summary>
/// Listens for changes to Vivox state for one user in the lobby.
/// Instead of going through Relay, this will listen to the Vivox service since it will already transmit state changes for all clients.
/// </summary>
public class VivoxUserHandler : MonoBehaviour
{
[SerializeField]
private UI.MuteUI m_MuteUI;
[SerializeField]
private UI.LobbyUserVolumeUI m_lobbyUserVolumeUI;
private IChannelSession m_channelSession;
private string m_id;
private string m_vivoxId;
private const int k_volumeMin = -50, k_volumeMax = 20; // From the Vivox docs, the valid range is [-50, 50] but anything above 25 risks being painfully loud.
public void SetId(string id)
{
m_id = id;
Account account = new Account(id);
// Vivox appends additional info to the ID we provide, in order to associate it with a specific channel. We'll construct m_vivoxId to match the ID used by Vivox.
m_vivoxId = account.ToString(); //"sip:." + account.Issuer + "." + m_id + ".@" + account.Domain;
// TODO: This doesn't end up matching the Participants keys, since there's something else appended between id and domain.
}
public void OnChannelJoined(IChannelSession channelSession)
{
m_channelSession = channelSession;
}
public void OnChannelLeft()
{
m_channelSession = null;
}
public void OnVolumeSlide(float volumeNormalized)
{
if (m_channelSession == null || m_vivoxId == null) // Verify initialization, since SetId and OnChannelJoined are called at different times for local vs. remote clients.
return;
int vol = (int)Mathf.Clamp(k_volumeMin + (k_volumeMax - k_volumeMin) * volumeNormalized, k_volumeMin, k_volumeMax); // Clamping as a precaution; if UserVolume somehow got above 1, listeners could be harmed.
bool isSelf = m_channelSession.Participants[m_vivoxId].IsSelf;
if (isSelf)
{
VivoxService.Instance.Client.AudioInputDevices.VolumeAdjustment = vol;
}
else
{
// TODO: Verify non-null things?
m_channelSession.Participants[m_vivoxId].LocalVolumeAdjustment = vol;
}
}
public void OnMuteToggle(bool isMuted)
{
if (m_channelSession == null || m_vivoxId == null)
return;
bool isSelf = m_channelSession.Participants[m_vivoxId].IsSelf;
if (isSelf)
{
VivoxService.Instance.Client.AudioInputDevices.Muted = isMuted;
}
else
{
m_channelSession.Participants[m_vivoxId].LocalMute = isMuted;
}
}
}
}

11
Assets/Scripts/Vivox/VivoxUserHandler.cs.meta


fileFormatVersion: 2
guid: 78d292f3bd9f1614cb744dcb4fe3ac12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

23
Assets/Scripts/Game/LocalUserAudio.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace LobbyRelaySample
{
[SerializeField]
public class LobbyUserAudio
{
public string ID { get; private set; }
public bool HasVoice;
public bool Muted;
public float UserVolume;
public LobbyUserAudio(string userID)
{
ID = userID;
HasVoice = false;
Muted = false;
UserVolume = 1;
}
}
}

/Assets/Scripts/Game/LocalUserAudio.cs.meta → /Assets/Scripts/Game/LobbyUserAudio.cs.meta

正在加载...
取消
保存