diff --git a/Assets/GameContent/Feature_MainUI/Prefabs/Common/TerminalChapterPanel.prefab b/Assets/GameContent/Feature_MainUI/Prefabs/Common/TerminalChapterPanel.prefab index 5391cf15b..661366a17 100644 --- a/Assets/GameContent/Feature_MainUI/Prefabs/Common/TerminalChapterPanel.prefab +++ b/Assets/GameContent/Feature_MainUI/Prefabs/Common/TerminalChapterPanel.prefab @@ -1053,6 +1053,7 @@ GameObject: - component: {fileID: 6205916594876141295} - component: {fileID: 7869115368522661861} - component: {fileID: 3469418760292733387} + - component: {fileID: 3469418760292733388} m_Layer: 0 m_Name: < Button m_TagString: Untagged @@ -1167,6 +1168,18 @@ MonoBehaviour: onStateTransition: m_PersistentCalls: m_Calls: [] +--- !u!114 &3469418760292733388 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3287442686753485554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4e8f2a19b3d47658e0f1a2b3c4d5e6f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &3870454585511995554 GameObject: m_ObjectHideFlags: 0 @@ -1179,6 +1192,7 @@ GameObject: - component: {fileID: 4356273674151839268} - component: {fileID: 3025403663481808802} - component: {fileID: 3189088484011772765} + - component: {fileID: 3189088484011772766} m_Layer: 0 m_Name: '> Button' m_TagString: Untagged @@ -1293,6 +1307,18 @@ MonoBehaviour: onStateTransition: m_PersistentCalls: m_Calls: [] +--- !u!114 &3189088484011772766 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3870454585511995554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4e8f2a19b3d47658e0f1a2b3c4d5e6f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &4545690484842323913 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/GameContent/Feature_MainUI/Prefabs/TerminalChapterPanel.prefab b/Assets/GameContent/Feature_MainUI/Prefabs/TerminalChapterPanel.prefab index 9ca8518b9..b467b6eda 100644 --- a/Assets/GameContent/Feature_MainUI/Prefabs/TerminalChapterPanel.prefab +++ b/Assets/GameContent/Feature_MainUI/Prefabs/TerminalChapterPanel.prefab @@ -146,6 +146,7 @@ GameObject: - component: {fileID: 813550245757536296} - component: {fileID: 2349484527078911041} - component: {fileID: 7511681537542705576} + - component: {fileID: 7511681537542705577} m_Layer: 5 m_Name: Right Btn m_TagString: Untagged @@ -219,7 +220,7 @@ MonoBehaviour: m_GameObject: {fileID: 5803930194917653799} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Script: {fileID: 11500000, guid: f5702aa38bfd4746aecc799b153aab91, type: 3} m_Name: m_EditorClassIdentifier: m_Navigation: @@ -254,6 +255,21 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] + onStateTransition: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &7511681537542705577 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5803930194917653799} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4e8f2a19b3d47658e0f1a2b3c4d5e6f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &7684576435073937010 GameObject: m_ObjectHideFlags: 0 @@ -266,6 +282,7 @@ GameObject: - component: {fileID: 6266102391853274815} - component: {fileID: 2430117081551875153} - component: {fileID: 4277087511383866260} + - component: {fileID: 4277087511383866261} m_Layer: 5 m_Name: Left Btn m_TagString: Untagged @@ -339,7 +356,7 @@ MonoBehaviour: m_GameObject: {fileID: 7684576435073937010} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Script: {fileID: 11500000, guid: f5702aa38bfd4746aecc799b153aab91, type: 3} m_Name: m_EditorClassIdentifier: m_Navigation: @@ -374,6 +391,21 @@ MonoBehaviour: m_OnClick: m_PersistentCalls: m_Calls: [] + onStateTransition: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &4277087511383866261 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7684576435073937010} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4e8f2a19b3d47658e0f1a2b3c4d5e6f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &8626785295523857742 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Framework/AudioKit/AudioEnum.cs b/Assets/Scripts/Framework/AudioKit/AudioEnum.cs index b57897743..59640d11b 100644 --- a/Assets/Scripts/Framework/AudioKit/AudioEnum.cs +++ b/Assets/Scripts/Framework/AudioKit/AudioEnum.cs @@ -17,6 +17,7 @@ Bar, Dream, MainMenu, - Empty + Empty, + PauseMenu } } \ No newline at end of file diff --git a/Assets/Scripts/Framework/AudioKit/AudioManager.cs b/Assets/Scripts/Framework/AudioKit/AudioManager.cs index 5ae0d165b..9bfca83ed 100644 --- a/Assets/Scripts/Framework/AudioKit/AudioManager.cs +++ b/Assets/Scripts/Framework/AudioKit/AudioManager.cs @@ -1,9 +1,11 @@ using System; using System.Collections; using System.Collections.Generic; +using AibisDream; using AibisDream.FixSystem; using AibisDream.Framework; using AibisDream.SaveSystem; +using AibisDream.UI; using FMOD; using FMOD.Studio; using FMODUnity; @@ -16,6 +18,7 @@ namespace AibisDream.Kit public class AudioManager : Singleton { private const string AmbStateName = "scene"; + private const string MainMenuStageParamName = "mainMenuStage"; public EventReference ambEvent; @@ -28,6 +31,10 @@ namespace AibisDream.Kit [Tooltip("Maximum volume in dB when slider is at 1")] [SerializeField] private float maxDecibels = 0f; + + [Header("Terminal UI")] + [SerializeField] private string terminalHoverSfx = "event:/ActionFB/menu_hover"; + [SerializeField] private string terminalClickSfx = "event:/ActionFB/menu_click"; #region Event实例 @@ -42,6 +49,9 @@ namespace AibisDream.Kit private List _removeTrigger = new(); private AmbState _currentAmbState = AmbState.Main; + private AmbState? _ambStateBeforePauseMenu; + + public AmbState CurrentAmbState => _currentAmbState; #endregion @@ -65,7 +75,16 @@ namespace AibisDream.Kit _removeTrigger.Add(EnumEventSystem.Global.Register(EventEnum.FixSceneModeChanged, OnFixSceneModeChange)); // 主菜单 / 退出局内 _removeTrigger.Add(EnumEventSystem.Global.Register(GameLoopEnum.AppStart, OnAppStart)); + _removeTrigger.Add(EnumEventSystem.Global.Register(GameLoopEnum.GameStart, OnGameStart)); _removeTrigger.Add(EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, OnGameQuit)); + _removeTrigger.Add(EnumEventSystem.Global.Register( + TerminalUIEvent.MainMenuPhase, OnMainMenuPhase)); + _removeTrigger.Add(EnumEventSystem.Global.Register(TerminalUIEvent.PauseMenuAmbEnter, OnPauseMenuAmbEnter)); + _removeTrigger.Add(EnumEventSystem.Global.Register( + TerminalUIEvent.PauseMenuAmbExit, OnPauseMenuAmbExit)); + + SingleCastEventSystem.Global.Register(TerminalUIAudioEnum.Hover, OnTerminalUIHover); + SingleCastEventSystem.Global.Register(TerminalUIAudioEnum.Click, OnTerminalUIClick); } public override void OnSingletonDestroy() @@ -80,13 +99,30 @@ namespace AibisDream.Kit trigger.UnRegister(); } _removeTrigger.Clear(); + + SingleCastEventSystem.Global.Unregister(TerminalUIAudioEnum.Hover); + SingleCastEventSystem.Global.Unregister(TerminalUIAudioEnum.Click); + } + + private void OnTerminalUIHover() + { + PlaySfx(terminalHoverSfx); + } + + private void OnTerminalUIClick() + { + PlaySfx(terminalClickSfx); } public AudioSnapshotDto CaptureSnapshot() { + var ambState = _currentAmbState == AmbState.PauseMenu && _ambStateBeforePauseMenu.HasValue + ? _ambStateBeforePauseMenu.Value + : _currentAmbState; + var dto = new AudioSnapshotDto { - ambState = _currentAmbState.ToString() + ambState = ambState.ToString() }; foreach (var pair in _musicDict) @@ -181,16 +217,57 @@ namespace AibisDream.Kit RuntimeManager.StudioSystem.setParameterByName(AmbStateName, (float)state); } + private void OnPauseMenuAmbEnter() + { + if (_currentAmbState == AmbState.PauseMenu) + { + return; + } + + _ambStateBeforePauseMenu = _currentAmbState; + ChangeAmb(AmbState.PauseMenu); + } + + private void OnPauseMenuAmbExit(bool restorePrevious) + { + if (!_ambStateBeforePauseMenu.HasValue) + { + return; + } + + if (restorePrevious) + { + ChangeAmb(_ambStateBeforePauseMenu.Value); + } + + _ambStateBeforePauseMenu = null; + } + public void SetGlobalParam(string paramName, float value) { RuntimeManager.StudioSystem.setParameterByName(paramName, value); } + public void SetMainMenuStage(int stage) + { + SetGlobalParam(MainMenuStageParamName, stage); + } + private void OnAppStart() { ChangeAmb(menuAmbState); } + private void OnMainMenuPhase(TerminalMainMenuPhase phase) + { + SetMainMenuStage((int)phase); + } + + private void OnGameStart() + { + SetMainMenuStage(3); + } + private void OnSceneLoad(string loadingScene) { // 场景加载时切换AMB diff --git a/Assets/Scripts/Game Loop/EventEnums.cs b/Assets/Scripts/Game Loop/EventEnums.cs index 983b7c44e..2946a9a8d 100644 --- a/Assets/Scripts/Game Loop/EventEnums.cs +++ b/Assets/Scripts/Game Loop/EventEnums.cs @@ -85,4 +85,17 @@ namespace AibisDream TextSpeed, LocaleChanged } + + public enum TerminalUIAudioEnum + { + Hover, + Click, + } + + public enum TerminalUIEvent + { + MainMenuPhase, + PauseMenuAmbEnter, + PauseMenuAmbExit, + } } diff --git a/Assets/Scripts/UI/Components/BaseButton.cs b/Assets/Scripts/UI/Components/BaseButton.cs index be2e4e8bb..902609dd8 100644 --- a/Assets/Scripts/UI/Components/BaseButton.cs +++ b/Assets/Scripts/UI/Components/BaseButton.cs @@ -14,7 +14,8 @@ namespace AibisDream { if (!gameObject.activeInHierarchy) return; - + + base.DoStateTransition(state, instant); onStateTransition?.Invoke(TransStateToType(state), instant); } diff --git a/Assets/Scripts/UI/Form/SelectItem.cs b/Assets/Scripts/UI/Form/SelectItem.cs index abb75f4ea..121402ee7 100644 --- a/Assets/Scripts/UI/Form/SelectItem.cs +++ b/Assets/Scripts/UI/Form/SelectItem.cs @@ -1,4 +1,5 @@ using System; +using AibisDream.UI; using AibisDream.Utility; using TMPro; using UnityEngine; @@ -37,6 +38,7 @@ namespace AibisDream private int _curIdx; private Action _onValueChanged; private bool _isListening; + private bool _isHovered; private ColorBlock _darkRowButtonColors; private void Awake() @@ -58,11 +60,18 @@ namespace AibisDream public void OnPointerEnter(PointerEventData eventData) { + if (!_isHovered) + { + _isHovered = true; + TerminalUIAudio.NotifyHover(); + } + SetHovered(true); } public void OnPointerExit(PointerEventData eventData) { + _isHovered = false; SetHovered(false); } @@ -167,6 +176,7 @@ namespace AibisDream _curIdx = CommonUtil.LoopStep(_curIdx, 0, _options.Length - 1, offset); RefreshValue(); _onValueChanged?.Invoke(_propName, _options[_curIdx].prop); + TerminalUIAudio.NotifyClick(); } private void RefreshValue() diff --git a/Assets/Scripts/UI/Form/SliderItem.cs b/Assets/Scripts/UI/Form/SliderItem.cs index f4b62ea3e..f4ba3a4b7 100644 --- a/Assets/Scripts/UI/Form/SliderItem.cs +++ b/Assets/Scripts/UI/Form/SliderItem.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using AibisDream.UI; using AibisDream.Utility; using TMPro; using UnityEngine; @@ -24,6 +25,7 @@ namespace AibisDream private string _propName; private Action _onValueChanged; private bool _isListening; + private bool _isHovered; private void Awake() { @@ -38,11 +40,18 @@ namespace AibisDream public void OnPointerEnter(PointerEventData eventData) { + if (!_isHovered) + { + _isHovered = true; + TerminalUIAudio.NotifyHover(); + } + SetHovered(true); } public void OnPointerExit(PointerEventData eventData) { + _isHovered = false; SetHovered(false); } diff --git a/Assets/Scripts/UI/Terminal/InGameTerminalPanel.cs b/Assets/Scripts/UI/Terminal/InGameTerminalPanel.cs index 1965a587b..e872cc656 100644 --- a/Assets/Scripts/UI/Terminal/InGameTerminalPanel.cs +++ b/Assets/Scripts/UI/Terminal/InGameTerminalPanel.cs @@ -129,17 +129,22 @@ namespace AibisDream.UI } public void Close() + { + Close(restoreAmb: true); + } + + public void Close(bool restoreAmb) { HideAllPages(); _backStack.Clear(); _currentPage = InGameTerminalPage.None; - ContinueIfPaused(); + ContinueIfPaused(restoreAmb); gameObject.SetActive(false); } public void CloseToMainMenu() { - Close(); + Close(restoreAmb: false); GameManager.Instance.QuitGame(); } @@ -166,10 +171,11 @@ namespace AibisDream.UI } GameManager.Instance.PauseGame(); + TerminalUIAudio.NotifyPauseMenuAmbEnter(); _pausedByPanel = true; } - private void ContinueIfPaused() + private void ContinueIfPaused(bool restoreAmb = true) { if (!_pausedByPanel) { @@ -177,6 +183,7 @@ namespace AibisDream.UI } GameManager.Instance.ContinueGame(); + TerminalUIAudio.NotifyPauseMenuAmbExit(restoreAmb); _pausedByPanel = false; } diff --git a/Assets/Scripts/UI/Terminal/TerminalButton.cs b/Assets/Scripts/UI/Terminal/TerminalButton.cs index d2dbacf85..79869844a 100644 --- a/Assets/Scripts/UI/Terminal/TerminalButton.cs +++ b/Assets/Scripts/UI/Terminal/TerminalButton.cs @@ -36,6 +36,8 @@ namespace AibisDream.UI public BaseButton Button => button != null ? button : (button = GetComponent()); + private SelectionType _prevSelectionState = SelectionType.Normal; + private void Awake() { button = GetComponent(); @@ -50,6 +52,7 @@ namespace AibisDream.UI } button.onStateTransition.AddListener(OnStateTransition); + button.onClick.AddListener(OnClick); if (!string.IsNullOrEmpty(defaultLabel)) { @@ -70,6 +73,7 @@ namespace AibisDream.UI if (button != null) { button.onStateTransition.RemoveListener(OnStateTransition); + button.onClick.RemoveListener(OnClick); } } @@ -96,6 +100,15 @@ namespace AibisDream.UI private void OnStateTransition(SelectionType state, bool instant) { + if (button.interactable + && state == SelectionType.Highlighted + && _prevSelectionState == SelectionType.Normal) + { + TerminalUIAudio.NotifyHover(); + } + + _prevSelectionState = state; + switch (state) { case SelectionType.Disabled: @@ -136,6 +149,14 @@ namespace AibisDream.UI } } + private void OnClick() + { + if (button != null && button.interactable) + { + TerminalUIAudio.NotifyClick(); + } + } + private static bool IsLocalizationKey(string value) { return !string.IsNullOrEmpty(value) && value.Contains("_", StringComparison.Ordinal); diff --git a/Assets/Scripts/UI/Terminal/TerminalMenuItemView.cs b/Assets/Scripts/UI/Terminal/TerminalMenuItemView.cs index 8913d563a..fe8a71d96 100644 --- a/Assets/Scripts/UI/Terminal/TerminalMenuItemView.cs +++ b/Assets/Scripts/UI/Terminal/TerminalMenuItemView.cs @@ -26,6 +26,7 @@ namespace AibisDream.UI private CanvasGroup _canvasGroup; private bool _isDanger; private bool _isSelected; + private SelectionType _prevSelectionState = SelectionType.Normal; public event Action Clicked; public event Action Hovered; @@ -122,11 +123,25 @@ namespace AibisDream.UI private void HandleClick() { + if (_button != null && _button.interactable) + { + TerminalUIAudio.NotifyClick(); + } + Clicked?.Invoke(this); } private void OnButtonStateTransition(SelectionType state, bool instant) { + if (_button.interactable + && state == SelectionType.Highlighted + && _prevSelectionState == SelectionType.Normal) + { + TerminalUIAudio.NotifyHover(); + } + + _prevSelectionState = state; + if (state is SelectionType.Highlighted or SelectionType.Selected or SelectionType.Pressed) { Hovered?.Invoke(this); diff --git a/Assets/Scripts/UI/Terminal/TerminalPanel.cs b/Assets/Scripts/UI/Terminal/TerminalPanel.cs index 9d222c069..a4a182fc8 100644 --- a/Assets/Scripts/UI/Terminal/TerminalPanel.cs +++ b/Assets/Scripts/UI/Terminal/TerminalPanel.cs @@ -71,6 +71,7 @@ namespace AibisDream.UI { if (_introCompletedThisSession) { + TerminalUIAudio.NotifyMainMenuPhase(TerminalMainMenuPhase.Interactive); Open(TerminalPage.Start); return; } @@ -79,6 +80,7 @@ namespace AibisDream.UI { Debug.LogError("[TerminalPanel] introDirector is not assigned. Opening Start directly."); _introCompletedThisSession = true; + TerminalUIAudio.NotifyMainMenuPhase(TerminalMainMenuPhase.Interactive); Open(TerminalPage.Start); return; } @@ -103,6 +105,7 @@ namespace AibisDream.UI return; } + TerminalUIAudio.NotifyMainMenuPhase(TerminalMainMenuPhase.Interactive); StartCoroutine(PlayIntroAndRevealStart()); } @@ -124,6 +127,7 @@ namespace AibisDream.UI HideAllPages(); _bootPhase = TerminalBootPhase.PressAnyKey; + TerminalUIAudio.NotifyMainMenuPhase(TerminalMainMenuPhase.Boot); } private IEnumerator PlayIntroAndRevealStart() diff --git a/Assets/Scripts/UI/Terminal/TerminalUIAudio.cs b/Assets/Scripts/UI/Terminal/TerminalUIAudio.cs new file mode 100644 index 000000000..2adf29569 --- /dev/null +++ b/Assets/Scripts/UI/Terminal/TerminalUIAudio.cs @@ -0,0 +1,29 @@ +using AibisDream; +using AibisDream.Framework; + +namespace AibisDream.UI +{ + public enum TerminalMainMenuPhase + { + Boot = 1, + Interactive = 2, + } + + public static class TerminalUIAudio + { + public static void NotifyHover() => + SingleCastEventSystem.Global.Trigger(TerminalUIAudioEnum.Hover); + + public static void NotifyClick() => + SingleCastEventSystem.Global.Trigger(TerminalUIAudioEnum.Click); + + public static void NotifyMainMenuPhase(TerminalMainMenuPhase phase) => + EnumEventSystem.Global.Send(TerminalUIEvent.MainMenuPhase, phase); + + public static void NotifyPauseMenuAmbEnter() => + EnumEventSystem.Global.Send(TerminalUIEvent.PauseMenuAmbEnter); + + public static void NotifyPauseMenuAmbExit(bool restorePrevious) => + EnumEventSystem.Global.Send(TerminalUIEvent.PauseMenuAmbExit, restorePrevious); + } +} diff --git a/Assets/Scripts/UI/Terminal/TerminalUIAudio.cs.meta b/Assets/Scripts/UI/Terminal/TerminalUIAudio.cs.meta new file mode 100644 index 000000000..82face84b --- /dev/null +++ b/Assets/Scripts/UI/Terminal/TerminalUIAudio.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55aaeeece31e179488471980b4f8cc2f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/Terminal/TerminalUIAudioBehaviour.cs b/Assets/Scripts/UI/Terminal/TerminalUIAudioBehaviour.cs new file mode 100644 index 000000000..7c27d0079 --- /dev/null +++ b/Assets/Scripts/UI/Terminal/TerminalUIAudioBehaviour.cs @@ -0,0 +1,57 @@ +using AibisDream; +using UnityEngine; + +namespace AibisDream.UI +{ + [RequireComponent(typeof(BaseButton))] + [DisallowMultipleComponent] + public class TerminalUIAudioBehaviour : MonoBehaviour + { + private BaseButton _button; + private SelectionType _prevState = SelectionType.Normal; + + private void Awake() + { + if (TryGetComponent(out _)) + { + enabled = false; + return; + } + + _button = GetComponent(); + _button.onStateTransition.AddListener(OnStateTransition); + _button.onClick.AddListener(OnClick); + } + + private void OnDestroy() + { + if (_button == null) + { + return; + } + + _button.onStateTransition.RemoveListener(OnStateTransition); + _button.onClick.RemoveListener(OnClick); + } + + private void OnStateTransition(SelectionType state, bool instant) + { + if (_button.interactable + && state == SelectionType.Highlighted + && _prevState == SelectionType.Normal) + { + TerminalUIAudio.NotifyHover(); + } + + _prevState = state; + } + + private void OnClick() + { + if (_button != null && _button.interactable) + { + TerminalUIAudio.NotifyClick(); + } + } + } +} diff --git a/Assets/Scripts/UI/Terminal/TerminalUIAudioBehaviour.cs.meta b/Assets/Scripts/UI/Terminal/TerminalUIAudioBehaviour.cs.meta new file mode 100644 index 000000000..620d9b963 --- /dev/null +++ b/Assets/Scripts/UI/Terminal/TerminalUIAudioBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4e8f2a19b3d47658e0f1a2b3c4d5e6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: