This commit is contained in:
陈思海 2025-09-05 19:46:30 +08:00
commit 79eaed43c5
314 changed files with 18588 additions and 0 deletions

8
Editor.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 623616b6a77c0c048a198b3db98e9824
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
{
"name": "AlicizaX.Framework.Editor",
"rootNamespace": "AlicizaX.Framework.Editor",
"references": [
"GUID:acfef7cabed3b0a42b25edb1cd4fa259",
"GUID:1619e00706139ce488ff80c0daeea8e7",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:4d1926c9df5b052469a1c63448b7609a",
"GUID:75b6f2078d190f14dbda4a5b747d709c"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fb064c8bf96bac94e90d2f39090daa94
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Audio.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2e7e6217d22087e449ba363fe2c0fe71
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,44 @@
using System;
using AlicizaX.Audio.Runtime;
using AlicizaX.Editor;
using UnityEditor;
namespace AlicizaX.Audio.Editor
{
[CustomEditor(typeof(AudioComponent))]
internal sealed class AudioComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_AudioMixer = null;
private SerializedProperty m_AudioGroupConfigs = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
AudioComponent t = (AudioComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
EditorGUILayout.PropertyField(m_AudioMixer);
EditorGUILayout.PropertyField(m_AudioGroupConfigs, true);
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
private void OnEnable()
{
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_AudioMixer = serializedObject.FindProperty("m_AudioMixer");
m_AudioGroupConfigs = serializedObject.FindProperty("m_AudioGroupConfigs");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 886dba87f6324f2c8b9639a9d4947bff
timeCreated: 1737390298

8
Editor/Debugger.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 857c20fbb3a13c74eaee070018a8321c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e98e73807718166469aac777a004bd7e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
using System;
using AlicizaX.Editor;
using UnityEditor;
using UnityEngine;
using AlicizaX.Debugger.Runtime;
namespace AlicizaX.Debugger.Editor
{
[CustomEditor(typeof(DebuggerComponent))]
internal sealed class DebuggerComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_Skin = null;
private SerializedProperty m_ActiveWindow = null;
private SerializedProperty m_ShowFullWindow = null;
private SerializedProperty m_ConsoleWindow = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
DebuggerComponent t = (DebuggerComponent)target;
EditorGUILayout.PropertyField(m_Skin);
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
bool activeWindow = EditorGUILayout.Toggle("Active Window", t.ActiveWindow);
if (activeWindow != t.ActiveWindow)
{
t.ActiveWindow = activeWindow;
}
}
else
{
EditorGUILayout.PropertyField(m_ActiveWindow);
}
EditorGUILayout.PropertyField(m_ShowFullWindow);
if (EditorApplication.isPlaying)
{
if (GUILayout.Button("Reset Layout"))
{
t.ResetLayout();
}
}
EditorGUILayout.PropertyField(m_ConsoleWindow, true);
serializedObject.ApplyModifiedProperties();
}
private void OnEnable()
{
m_Skin = serializedObject.FindProperty("m_Skin");
m_ActiveWindow = serializedObject.FindProperty("m_ActiveWindow");
m_ShowFullWindow = serializedObject.FindProperty("m_ShowFullWindow");
m_ConsoleWindow = serializedObject.FindProperty("m_ConsoleWindow");
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 346bd5fc6cf0d76478b39f7e69185a23
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Editor/Debugger/Res.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f52e94520a8d8544f84756063cf06d42
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dce698819fdb70b42b393d9b0b6d420e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

8
Editor/FSM.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db3480ef83bb9664ca5e816ef897fbbf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,121 @@
// ===================== FSMDebugger Window (unchanged API, auto-binding now) =====================
using AlicizaX.Fsm;
using UnityEditor;
using UnityEngine;
internal class FsmDebuggerWindow : EditorWindow
{
[MenuItem("Window/HighPerfFSM Debugger")]
public static void ShowWindow()
{
var win = GetWindow<FsmDebuggerWindow>("FSM Debugger");
win.Show();
}
private Vector2 _scroll;
private bool _autoRefresh = true;
private void OnEnable()
{
FSMDebugger.SetEnabled(true);
EditorApplication.update += RepaintIfNeeded;
}
private void OnDisable()
{
EditorApplication.update -= RepaintIfNeeded;
}
private void RepaintIfNeeded()
{
if (_autoRefresh) Repaint();
}
private void OnGUI()
{
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
{
GUILayout.Label("HighPerfFSM Debugger", EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
_autoRefresh = GUILayout.Toggle(_autoRefresh, "Auto Refresh", EditorStyles.toolbarButton);
}
_scroll = EditorGUILayout.BeginScrollView(_scroll);
foreach (var kv in FSMDebugger.Entries)
{
var entry = kv.Value;
EditorGUILayout.BeginVertical("box");
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label($"ID: {entry.Id}", GUILayout.Width(90));
GUILayout.Label(entry.Name, EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
}
var stateName = (entry.StateNameGetter != null)
? entry.StateNameGetter(entry.StateIndex) ?? entry.StateIndex.ToString()
: entry.StateIndex.ToString();
EditorGUILayout.LabelField("State", stateName);
EditorGUILayout.LabelField("TimeInState", entry.TimeInState.ToString("F3"));
if (entry.BlackboardGetter != null && entry.Fields != null)
{
object bbObj = null;
try
{
bbObj = entry.BlackboardGetter();
}
catch
{
}
if (bbObj != null)
{
EditorGUILayout.LabelField("Blackboard");
EditorGUI.indentLevel++;
for (int i = 0; i < entry.Fields.Length; i++)
{
var f = entry.Fields[i];
object val = null;
try
{
val = f.GetValue(bbObj);
}
catch
{
}
EditorGUILayout.LabelField(f.Name, val != null ? val.ToString() : "null");
}
EditorGUI.indentLevel--;
}
else
{
EditorGUILayout.HelpBox("Blackboard getter returned null.", MessageType.Info);
}
}
if (entry.Owner != null && entry.Owner.TryGetTarget(out var owner) && owner != null)
{
EditorGUILayout.ObjectField("Owner", owner, typeof(UnityEngine.Object), true);
}
EditorGUILayout.EndVertical();
GUILayout.Space(4);
}
EditorGUILayout.EndScrollView();
if (GUILayout.Button("Clear All (Unregister)"))
{
var ids = new System.Collections.Generic.List<int>();
foreach (var kv in FSMDebugger.Entries) ids.Add(kv.Key);
foreach (var id in ids) FSMDebugger.Unregister(id);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b7e760f8a07d441dba01f9a5bf8fff62
timeCreated: 1745562869

8
Editor/Resource.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b34974735d949c545b6b2b60f4d96355
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1ad0cb4b2fbda55409ca1d4a66e6d4f0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,50 @@
using AlicizaX.Resource.Runtime;
namespace AlicizaX.Resource.Editor
{
using System;
using System.IO;
using YooAsset;
/// <summary>
/// 文件偏移加密方式
/// </summary>
public class FileOffsetEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
int offset = 32;
byte[] fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
var encryptedData = new byte[fileData.Length + offset];
Buffer.BlockCopy(fileData, 0, encryptedData, offset, fileData.Length);
EncryptResult result = new EncryptResult();
result.Encrypted = true;
result.EncryptedData = encryptedData;
return result;
}
}
/// <summary>
/// 文件流加密方式
/// </summary>
public class FileStreamEncryption : IEncryptionServices
{
public const byte KEY = 64;
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
var fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
for (int i = 0; i < fileData.Length; i++)
{
fileData[i] ^= BundleStream.KEY;
}
EncryptResult result = new EncryptResult();
result.Encrypted = true;
result.EncryptedData = fileData;
return result;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39b42829cd724f10999caec280e260f7
timeCreated: 1737867622

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b27fb2c235a240e8a3d034a23c0c5323
timeCreated: 1737441909

View File

@ -0,0 +1,264 @@
using System;
using System.Collections.Generic;
using AlicizaX.Editor;
using AlicizaX.Resource.Runtime;
using UnityEditor;
using YooAsset;
using YooAsset.Editor;
namespace AlicizaX.Resource.Editor
{
[CustomEditor(typeof(ResourceComponent))]
internal sealed class ResourceComponentInspector : GameFrameworkInspector
{
private SerializedProperty _milliseconds = null;
private SerializedProperty _minUnloadUnusedAssetsInterval = null;
private SerializedProperty _maxUnloadUnusedAssetsInterval = null;
private SerializedProperty _useSystemUnloadUnusedAssets = null;
private SerializedProperty _assetAutoReleaseInterval = null;
private SerializedProperty _assetCapacity = null;
private SerializedProperty _assetExpireTime = null;
private SerializedProperty _assetPriority = null;
private SerializedProperty _downloadingMaxNum = null;
private SerializedProperty _failedTryAgain = null;
private SerializedProperty _packageName = null;
private SerializedProperty _decryptionServices = null;
private int _packageNameIndex = 0;
private string[] _packageNames;
private List<string> m_DecryptionServicesTypeName = new();
private int m_DecryptionSelectIndex;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
ResourceComponent t = (ResourceComponent)target;
m_DecryptionSelectIndex = EditorGUILayout.Popup("解密服务", m_DecryptionSelectIndex, m_DecryptionServicesTypeName.ToArray());
string selectService = m_DecryptionServicesTypeName[m_DecryptionSelectIndex];
if (_decryptionServices.stringValue != selectService)
{
string serviceName = selectService.Equals(NoneOptionName) ? string.Empty : selectService;
_decryptionServices.stringValue = serviceName;
}
_packageNames = GetBuildPackageNames().ToArray();
_packageNameIndex = Array.IndexOf(_packageNames, _packageName.stringValue);
if (_packageNameIndex < 0)
{
_packageNameIndex = 0;
}
_packageNameIndex = EditorGUILayout.Popup("Package Name", _packageNameIndex, _packageNames);
if (_packageName.stringValue != _packageNames[_packageNameIndex])
{
_packageName.stringValue = _packageNames[_packageNameIndex];
}
int milliseconds = EditorGUILayout.DelayedIntField("Milliseconds", _milliseconds.intValue);
if (milliseconds != _milliseconds.intValue)
{
if (EditorApplication.isPlaying)
{
t.milliseconds = milliseconds;
}
else
{
_milliseconds.longValue = milliseconds;
}
}
EditorGUILayout.PropertyField(_useSystemUnloadUnusedAssets);
float minUnloadUnusedAssetsInterval =
EditorGUILayout.Slider("Min Unload Unused Assets Interval", _minUnloadUnusedAssetsInterval.floatValue, 0f, 3600f);
if (Math.Abs(minUnloadUnusedAssetsInterval - _minUnloadUnusedAssetsInterval.floatValue) > 0.01f)
{
if (EditorApplication.isPlaying)
{
t.MinUnloadUnusedAssetsInterval = minUnloadUnusedAssetsInterval;
}
else
{
_minUnloadUnusedAssetsInterval.floatValue = minUnloadUnusedAssetsInterval;
}
}
float maxUnloadUnusedAssetsInterval =
EditorGUILayout.Slider("Max Unload Unused Assets Interval", _maxUnloadUnusedAssetsInterval.floatValue, 0f, 3600f);
if (Math.Abs(maxUnloadUnusedAssetsInterval - _maxUnloadUnusedAssetsInterval.floatValue) > 0.01f)
{
if (EditorApplication.isPlaying)
{
t.MaxUnloadUnusedAssetsInterval = maxUnloadUnusedAssetsInterval;
}
else
{
_maxUnloadUnusedAssetsInterval.floatValue = maxUnloadUnusedAssetsInterval;
}
}
float downloadingMaxNum = EditorGUILayout.Slider("Max Downloading Num", _downloadingMaxNum.intValue, 1f, 48f);
if (Math.Abs(downloadingMaxNum - _downloadingMaxNum.intValue) > 0.001f)
{
if (EditorApplication.isPlaying)
{
t.DownloadingMaxNum = (int)downloadingMaxNum;
}
else
{
_downloadingMaxNum.intValue = (int)downloadingMaxNum;
}
}
float failedTryAgain = EditorGUILayout.Slider("Max FailedTryAgain Count", _failedTryAgain.intValue, 1f, 48f);
if (Math.Abs(failedTryAgain - _failedTryAgain.intValue) > 0.001f)
{
if (EditorApplication.isPlaying)
{
t.FailedTryAgain = (int)failedTryAgain;
}
else
{
_failedTryAgain.intValue = (int)failedTryAgain;
}
}
EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying);
{
float assetAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Asset Auto Release Interval", _assetAutoReleaseInterval.floatValue);
if (Math.Abs(assetAutoReleaseInterval - _assetAutoReleaseInterval.floatValue) > 0.01f)
{
if (EditorApplication.isPlaying)
{
t.AssetAutoReleaseInterval = assetAutoReleaseInterval;
}
else
{
_assetAutoReleaseInterval.floatValue = assetAutoReleaseInterval;
}
}
int assetCapacity = EditorGUILayout.DelayedIntField("Asset Capacity", _assetCapacity.intValue);
if (assetCapacity != _assetCapacity.intValue)
{
if (EditorApplication.isPlaying)
{
t.AssetCapacity = assetCapacity;
}
else
{
_assetCapacity.intValue = assetCapacity;
}
}
float assetExpireTime = EditorGUILayout.DelayedFloatField("Asset Expire Time", _assetExpireTime.floatValue);
if (Math.Abs(assetExpireTime - _assetExpireTime.floatValue) > 0.01f)
{
if (EditorApplication.isPlaying)
{
t.AssetExpireTime = assetExpireTime;
}
else
{
_assetExpireTime.floatValue = assetExpireTime;
}
}
int assetPriority = EditorGUILayout.DelayedIntField("Asset Priority", _assetPriority.intValue);
if (assetPriority != _assetPriority.intValue)
{
if (EditorApplication.isPlaying)
{
t.AssetPriority = assetPriority;
}
else
{
_assetPriority.intValue = assetPriority;
}
}
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Unload Unused Assets",
AlicizaX.Utility.Text.Format("{0:F2} / {1:F2}", t.LastUnloadUnusedAssetsOperationElapseSeconds, t.MaxUnloadUnusedAssetsInterval));
EditorGUILayout.LabelField("Applicable Game Version", t.ApplicableGameVersion ?? "<Unknwon>");
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
_milliseconds = serializedObject.FindProperty("milliseconds");
_minUnloadUnusedAssetsInterval = serializedObject.FindProperty("minUnloadUnusedAssetsInterval");
_maxUnloadUnusedAssetsInterval = serializedObject.FindProperty("maxUnloadUnusedAssetsInterval");
_useSystemUnloadUnusedAssets = serializedObject.FindProperty("useSystemUnloadUnusedAssets");
_assetAutoReleaseInterval = serializedObject.FindProperty("assetAutoReleaseInterval");
_assetCapacity = serializedObject.FindProperty("assetCapacity");
_assetExpireTime = serializedObject.FindProperty("assetExpireTime");
_assetPriority = serializedObject.FindProperty("assetPriority");
_downloadingMaxNum = serializedObject.FindProperty("downloadingMaxNum");
_failedTryAgain = serializedObject.FindProperty("failedTryAgain");
_packageName = serializedObject.FindProperty("packageName");
_decryptionServices = serializedObject.FindProperty("_decryptionServices");
RefreshDecryptionServices();
RefreshTypeNames();
}
private void RefreshDecryptionServices()
{
m_DecryptionServicesTypeName = new List<string>
{
NoneOptionName
};
m_DecryptionServicesTypeName.AddRange(AlicizaX.Utility.Assembly.GetRuntimeTypeNames(typeof(IDecryptionServices)));
m_DecryptionSelectIndex = m_DecryptionServicesTypeName.IndexOf(_decryptionServices.stringValue);
if (m_DecryptionSelectIndex < 0)
{
m_DecryptionSelectIndex = 0;
}
}
private void RefreshTypeNames()
{
serializedObject.ApplyModifiedProperties();
}
/// <summary>
/// 获取构建包名称列表,用于下拉可选择
/// </summary>
/// <returns></returns>
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
result.Add(package.PackageName);
}
return result;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dfe8d0fdb8d74e33a9b051644dd94676
timeCreated: 1737458008

View File

@ -0,0 +1,59 @@
// using System;
// using AlicizaX.Editor;
// using AlicizaX.Resource.Runtime;
// using UnityEditor;
// using UnityEngine;
//
// namespace AlicizaX.Resource.Editor
// {
// [CustomEditor(typeof(ResourceExtComponent))]
// internal sealed class ResourceExtComponentInspector : GameFrameworkInspector
// {
// private SerializedProperty m_CheckCanReleaseInterval = null;
// private SerializedProperty m_AutoReleaseInterval = null;
//
// public override void OnInspectorGUI()
// {
// base.OnInspectorGUI();
// serializedObject.Update();
//
// ResourceExtComponent t = (ResourceExtComponent)target;
//
// EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
// {
// EditorGUILayout.BeginVertical("box");
// {
// float checkCanReleaseInterval = EditorGUILayout.Slider("检查释放间隔", m_CheckCanReleaseInterval.floatValue, 30, 460);
// if (m_CheckCanReleaseInterval.floatValue != checkCanReleaseInterval)
// {
// m_CheckCanReleaseInterval.floatValue = checkCanReleaseInterval;
// }
//
//
// float autoReleaseInterval = EditorGUILayout.Slider("对象池释放间隔", m_AutoReleaseInterval.floatValue, 60, 1800);
// if (m_AutoReleaseInterval.floatValue != autoReleaseInterval)
// {
// m_AutoReleaseInterval.floatValue = autoReleaseInterval;
// }
// }
//
// if (GUILayout.Button("ReleaseUnused"))
// {
// t.ReleaseUnused();
// }
//
//
// EditorGUILayout.EndVertical();
// }
// EditorGUI.EndDisabledGroup();
//
// serializedObject.ApplyModifiedProperties();
// }
//
// private void OnEnable()
// {
// m_CheckCanReleaseInterval = serializedObject.FindProperty("m_CheckCanReleaseInterval");
// m_AutoReleaseInterval = serializedObject.FindProperty("m_AutoReleaseInterval");
// }
// }
// }

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f9278b79811545c38cc9edf00d666bee
timeCreated: 1737441939

8
Editor/UI.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4a717b10b37856e43972776bbf4cc0ff
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d9940ca83fab4087ab1116f5a2ea01a4
timeCreated: 1739274233

View File

@ -0,0 +1,21 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace AlicizaX.UI.Editor
{
public static class UIGenerateEditorTool
{
[MenuItem("GameObject/UI工具/热更工程UI代码", priority = -1)]
public static void GenerateHotfixUIScript()
{
UIGenerateWindow.ShowWindow(Selection.gameObjects.FirstOrDefault(),UIGenerateConfiguration.Instance.UIScriptGenerateConfig.HotFixProjectUIScriptGenerateData);
}
[MenuItem("GameObject/UI工具/主工程UI代码", priority = -1)]
public static void GenerateMainUIScript()
{
UIGenerateWindow.ShowWindow(Selection.gameObjects.FirstOrDefault(),UIGenerateConfiguration.Instance.UIScriptGenerateConfig.MainProjectUIScriptGenerateData);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8df5224864804bc3a206ab20e5024e5c
timeCreated: 1739274266

View File

@ -0,0 +1,42 @@
using UnityEditor;
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AlicizaX.UI.Editor;
using AlicizaX.UI.Runtime;
using UnityEngine.UIElements;
public class UIGenerateWindow : EditorWindow
{
private GameObject targetObject;
public static GameObject GetTargetObject()
{
return GetWindow<UIGenerateWindow>().targetObject;
}
public static void ShowWindow(GameObject target, UIScriptGenerateData scriptGenerateData)
{
var window = GetWindow<UIGenerateWindow>(false, "UI Config Editor", false);
window.maxSize = Vector2.zero;
window.minSize = Vector2.zero;
window.rootVisualElement.style.display = DisplayStyle.None;
window.rootVisualElement.parent.style.display = DisplayStyle.None;
window.Initlize(target, scriptGenerateData);
}
public static void CloseWindow()
{
var window = GetWindow<UIGenerateWindow>(false, "UI Config Editor");
window.Close();
}
private void Initlize(GameObject target, UIScriptGenerateData scriptGenerateData)
{
targetObject = target;
UIScriptGeneratorHelper.GenerateAndAttachScript(targetObject, scriptGenerateData);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7bfa0d164c11486cb3a133829d53dccf
timeCreated: 1739339632

View File

@ -0,0 +1,469 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using AlicizaX.UI.Editor;
using AlicizaX.UI.Runtime;
using Sirenix.Utilities.Editor;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine.UI;
namespace AlicizaX.UI.Editor
{
enum EBindType
{
None,
Widget,
ListCom,
}
[Serializable]
class UIBindData
{
public string Name;
public List<Component> BindCom;
public EBindType BindType;
public UIBindData(string name, List<Component> bindCom, EBindType bindType = EBindType.None)
{
Name = name;
BindCom = bindCom;
BindType = bindType;
}
public UIBindData(string name, Component bindCom, EBindType bindType = EBindType.None)
{
Name = name;
BindCom = new List<Component>() { bindCom };
BindType = bindType;
}
}
public static class UIScriptGeneratorHelper
{
private static UIGenerateConfiguration _uiGenerateConfiguration;
static UIGenerateConfiguration UIGenerateConfiguration
{
get
{
if (_uiGenerateConfiguration == null)
{
_uiGenerateConfiguration = UIGenerateConfiguration.Instance;
}
return _uiGenerateConfiguration;
}
}
private static string GetVerType(string uiName)
{
foreach (var pair in UIGenerateConfiguration.UIElementRegexConfigs)
{
if (uiName.StartsWith(pair.uiElementRegex))
{
return pair.componentType;
}
}
return string.Empty;
}
private static string[] SplitComName(string name)
{
bool hasCom = name.Contains(UIGenerateConfiguration.UIGenerateCommonData.ComCheckEndName);
if (!hasCom) return null;
string comStr = name.Substring(0, name.IndexOf(UIGenerateConfiguration.UIGenerateCommonData.ComCheckEndName));
return comStr.Split(UIGenerateConfiguration.UIGenerateCommonData.ComCheckSplitName);
}
private static string GetKeyName(string key, string componentName)
{
return $"{key}{componentName.Substring(componentName.IndexOf(UIGenerateConfiguration.UIGenerateCommonData.ComCheckEndName) + 1)}";
}
private static List<UIBindData> UIBindDatas = new List<UIBindData>();
private static string GenerateNameSpace = string.Empty;
private static List<string> ArrayComs = new List<string>();
private static void GetBindData(Transform root)
{
for (int i = 0; i < root.childCount; ++i)
{
Transform child = root.GetChild(i);
bool hasWdiget = child.GetComponent<UIHolderObjectBase>() != null;
if (UIGenerateConfiguration.UIGenerateCommonData.ExcludeKeywords.Any(k => child.name.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0)) continue;
bool isArrayComs = child.name.StartsWith(UIGenerateConfiguration.UIGenerateCommonData.ArrayComSplitName);
if (hasWdiget)
{
CollectWidget(child);
}
else if (isArrayComs)
{
string splitCode = UIGenerateConfiguration.UIGenerateCommonData.ArrayComSplitName;
int lastIndex = child.name.LastIndexOf(splitCode);
string text = child.name.Substring(child.name.IndexOf(splitCode) + 1, lastIndex - 1);
if (ArrayComs.Contains(text)) continue;
ArrayComs.Add(text);
List<Transform> arrayComs = new List<Transform>();
for (int j = 0; j < root.childCount; j++)
{
if (root.GetChild(j).name.Contains(text))
{
arrayComs.Add(root.GetChild(j));
}
}
CollectArrayComponent(arrayComs, text);
}
else if (!isArrayComs && !hasWdiget)
{
CollectComponent(child);
GetBindData(child);
}
}
}
private static void CollectComponent(Transform node)
{
string[] comArray = SplitComName(node.name);
if (comArray != null)
{
foreach (var com in comArray)
{
string typeName = GetVerType(com);
if (string.IsNullOrEmpty(typeName)) continue;
Component component = node.GetComponent(typeName);
if (component != null)
{
string keyName = GetKeyName(com, node.name);
if (UIBindDatas.Exists(a => a.Name == keyName))
{
Debug.LogError($"Duplicate key found: {keyName}");
continue;
}
UIBindDatas.Add(new UIBindData(keyName, component));
}
else
{
Debug.LogError($"{node.name} does not have component of type {typeName}");
}
}
}
}
private static void CollectWidget(Transform node)
{
if (node.name.IndexOf(UIGenerateConfiguration.UIGenerateCommonData.ComCheckEndName) != -1 && node.name.IndexOf(UIGenerateConfiguration.UIGenerateCommonData.ComCheckSplitName) != -1)
{
Debug.LogWarning($"{node.name} 子组件不能包含规则定义符号!");
return;
}
UIHolderObjectBase component = node.GetComponent<UIHolderObjectBase>();
string keyName = node.name;
if (UIBindDatas.Exists(a => a.Name == keyName))
{
Debug.LogError($"Duplicate key found: {keyName}");
return;
}
UIBindDatas.Add(new UIBindData(keyName, component, EBindType.Widget));
}
private static void CollectArrayComponent(List<Transform> arrayNode, string nodeName)
{
string[] comArray = SplitComName(nodeName);
arrayNode = arrayNode.OrderBy(s => int.Parse(s.name.Split('*').Last())).ToList();
List<UIBindData> tempBindDatas = new List<UIBindData>(comArray.Length);
if (comArray != null)
{
int index = 0;
foreach (var com in comArray)
{
foreach (var node in arrayNode)
{
string typeName = GetVerType(com);
if (string.IsNullOrEmpty(typeName)) continue;
Component component = node.GetComponent(typeName);
if (component != null)
{
string keyName = GetKeyName(com, nodeName) + "List";
if (tempBindDatas.Count - 1 < index) tempBindDatas.Add(new UIBindData(keyName, new List<Component>(), EBindType.ListCom));
tempBindDatas[index].BindCom.Add(component);
}
else
{
Debug.LogError($"{node.name} does not have component of type {typeName}");
}
}
index++;
}
}
UIBindDatas.AddRange(tempBindDatas.ToArray());
}
private static string GetRefrenceNameSpace()
{
StringBuilder refrenceNameSpaceBuilder = new StringBuilder();
HashSet<string> nameSpaces = new HashSet<string>();
nameSpaces.Add("UnityEngine");
refrenceNameSpaceBuilder.Append($"using UnityEngine;\n");
foreach (var bindData in UIBindDatas)
{
string nameSpace = bindData.BindCom.FirstOrDefault().GetType().Namespace;
if (bindData.BindType == EBindType.ListCom)
{
if (!nameSpaces.Contains("using System.Collections.Generic;"))
{
refrenceNameSpaceBuilder.Append("using System.Collections.Generic;\n");
}
}
if (!nameSpaces.Contains(nameSpace) && !string.IsNullOrEmpty(nameSpace))
{
nameSpaces.Add(nameSpace);
refrenceNameSpaceBuilder.Append($"using {nameSpace};\n");
}
}
return refrenceNameSpaceBuilder.ToString();
}
private static string GetVarText(List<UIBindData> uiBindDatas)
{
StringBuilder varTextBuilder = new StringBuilder();
foreach (var bindData in uiBindDatas)
{
var varName = bindData.Name;
varTextBuilder.Append("\t\t[SerializeField]\n");
varTextBuilder.Append("\t\t[ReadOnly]\n");
varTextBuilder.Append("\t\t[HideLabel]\n");
if (bindData.BindType == EBindType.None)
{
varTextBuilder.Append($"\t\tprivate {bindData.BindCom.FirstOrDefault().GetType().Name} m{varName};\n");
varTextBuilder.Append($"\t\tpublic {bindData.BindCom.FirstOrDefault().GetType().Name} {varName} => m{varName};\n\n");
}
else if (bindData.BindType == EBindType.ListCom)
{
varTextBuilder.Append($"\t\tprivate {bindData.BindCom.FirstOrDefault().GetType().Name} [] m{varName} = new {bindData.BindCom.FirstOrDefault().GetType().Name}[{bindData.BindCom.Count}];\n");
varTextBuilder.Append($"\t\tpublic {bindData.BindCom.FirstOrDefault().GetType().Name} [] {varName} => m{varName};\n\n");
}
else if (bindData.BindType == EBindType.Widget)
{
varTextBuilder.Append($"\t\tprivate {bindData.BindCom.FirstOrDefault().GetType().Name} m{varName};\n");
varTextBuilder.Append($"\t\tpublic {bindData.BindCom.FirstOrDefault().GetType().Name} {varName} => m{varName};\n\n");
}
}
return varTextBuilder.ToString();
}
private static string GenerateScript(string className)
{
StringBuilder scriptBuilder = new StringBuilder();
scriptBuilder.Append(GetRefrenceNameSpace());
scriptBuilder.Append("using Sirenix.OdinInspector;\n");
scriptBuilder.Append("using AlicizaX.UI.Runtime;\n");
scriptBuilder.Append($"namespace {GenerateNameSpace}\n");
scriptBuilder.Append("{\n");
scriptBuilder.Append($"\t#Attribute#\n");
scriptBuilder.Append($"\tpublic class {className} : UIHolderObjectBase\n");
scriptBuilder.Append("\t{\n");
scriptBuilder.Append($"\t\tpublic const string ResTag = #Tag#;\n");
scriptBuilder.Append("\t\t#region Generated by Script Tool\n\n");
scriptBuilder.Append(GetVarText(UIBindDatas));
scriptBuilder.Append("\n\t\t#endregion\n");
scriptBuilder.Append("\t}\n");
scriptBuilder.Append("}\n");
return scriptBuilder.ToString();
}
public static void GenerateAndAttachScript(GameObject targetObject, UIScriptGenerateData scriptGenerateData)
{
UIBindDatas.Clear();
GenerateNameSpace = scriptGenerateData.NameSpace;
ArrayComs.Clear();
string className = $"{UIGenerateConfiguration.UIGenerateCommonData.GeneratePrefix}_{targetObject.name}";
string scriptSavePath = Path.Combine(scriptGenerateData.GenerateHolderCodePath, className + ".cs");
GetBindData(targetObject.transform);
string scriptContent = GenerateScript(className);
string TagName = $"\"{targetObject.name}\"";
if (scriptGenerateData.LoadType == EUIResLoadType.Resources)
{
string matchWords = string.Empty;
UIGenerateConfiguration.UIGenerateCommonData.CombineWords.Any(t =>
{
if (targetObject.name.IndexOf(t.Key) >= 0)
{
matchWords = t.Value;
}
return targetObject.name.IndexOf(t.Key) >= 0;
});
string finalPath = Path.Combine(scriptGenerateData.UIPrefabRootPath.Replace("Assets/", "").Replace("Resources/", ""), matchWords);
string didc = Path.Combine(scriptGenerateData.UIPrefabRootPath, matchWords);
if (!Directory.Exists(didc))
{
Directory.CreateDirectory(didc);
}
finalPath = Utility.Path.GetRegularPath(finalPath);
TagName = $"\"{finalPath}/{targetObject.name}\"";
}
scriptContent = scriptContent.Replace("#Tag#", TagName);
//#Attribute#
string uiAttribute = $"[UIRes({className}.ResTag, EUIResLoadType.{scriptGenerateData.LoadType.ToString()})]";
scriptContent = scriptContent.Replace("#Attribute#", uiAttribute);
if (File.Exists(scriptSavePath))
{
string oldText = File.ReadAllText(scriptSavePath);
if (oldText.Equals(scriptContent))
{
EditorPrefs.SetString("Generate", className);
CheckHasAttach();
return;
}
}
File.WriteAllText(scriptSavePath, scriptContent);
EditorPrefs.SetString("Generate", className);
AssetDatabase.Refresh();
}
[DidReloadScripts]
private static void CheckHasAttach()
{
bool has = EditorPrefs.HasKey("Generate");
if (has)
{
UIBindDatas.Clear();
ArrayComs.Clear();
var className = EditorPrefs.GetString("Generate");
var targetObject = UIGenerateWindow.GetTargetObject();
EditorPrefs.DeleteKey("Generate");
GetBindData(targetObject.transform);
AttachScriptToGameObject(targetObject, className);
Debug.Log($"Generate {className} Successfully attached to game object");
UIGenerateWindow.CloseWindow();
}
}
private static void AttachScriptToGameObject(GameObject targetObject, string scriptClassName)
{
Type scriptType = null;
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.FullName.Contains("Editor")) continue;
var types = assembly.GetTypes();
foreach (var type in types)
{
if (type.IsClass && !type.IsAbstract && type.Name.Contains(scriptClassName))
{
scriptType = type;
}
}
}
if (scriptType != null)
{
Component component = targetObject.GetOrAddComponent(scriptType);
FieldInfo[] fields = scriptType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
List<Component> componentInObjects = UIBindDatas.Find(data => "m" + data.Name == field.Name)?.BindCom;
if (componentInObjects != null)
{
if (field.FieldType.IsArray)
{
// 获取数组元素类型
Type elementType = field.FieldType.GetElementType();
// 创建对应类型的数组
Array array = Array.CreateInstance(elementType, componentInObjects.Count);
for (int i = 0; i < componentInObjects.Count; i++)
{
Component comp = componentInObjects[i];
// 检查元素类型是否匹配
if (elementType.IsInstanceOfType(comp))
{
array.SetValue(comp, i);
}
else
{
Debug.LogError($"元素 {i} 类型不匹配,期望 {elementType.Name},实际为 {comp.GetType().Name}");
// 处理错误,如跳过或终止赋值
}
}
field.SetValue(component, array);
}
else
{
// 非数组字段取第一个元素
if (componentInObjects.Count > 0)
{
// 同样检查类型兼容性
if (field.FieldType.IsInstanceOfType(componentInObjects[0]))
{
field.SetValue(component, componentInObjects[0]);
}
else
{
Debug.LogError($"字段 {field.Name} 类型不匹配,无法赋值");
}
}
}
}
else
{
Debug.LogError($"字段 {field.Name} 未找到匹配的组件绑定");
}
}
}
else
{
Debug.LogError($"Could not find the class: {scriptClassName}");
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f42fd09682fc40898bf7176dbb24d085
timeCreated: 1739273282

View File

@ -0,0 +1,104 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEngine;
using UnityEngine.Windows;
namespace AlicizaX.UI.Editor
{
public class UISettingEditorWindow : OdinEditorWindow
{
[MenuItem("Tools/AlicizaX/UI Setting Window")]
private static void OpenWindow()
{
GetWindow<UISettingEditorWindow>().Show();
}
protected override void Initialize()
{
uiGenerateConfiguration = UIGenerateConfiguration.Instance;
UIGenerateCommonData = uiGenerateConfiguration.UIGenerateCommonData;
UIScriptGenerateConfig = uiGenerateConfiguration.UIScriptGenerateConfig;
UIElementRegexConfigs = uiGenerateConfiguration.UIElementRegexConfigs;
RefreshLabel();
}
// [Required] [InlineEditor(InlineEditorObjectFieldModes.CompletelyHidden)] [DisableInPlayMode] [HideLabel]
private UIGenerateConfiguration uiGenerateConfiguration;
[Required] [DisableInPlayMode] [HideLabel] [TabGroup("UI基础设置")] [SerializeField]
public UIGenerateCommonData UIGenerateCommonData;
[TabGroup("UI基础设置")] [LabelText("脚本生成预览")] [ShowInInspector] [ReadOnly] [OnValueChanged("RefreshLabel")]
private string previewLabel;
[TabGroup("UI基础设置")] [LabelText("组件生成预览")] [ShowInInspector] [ReadOnly] [OnValueChanged("RefreshLabel")] [SuffixLabel("(下标0开始)")]
private string previewCompLabel;
[Required] [DisableInPlayMode] [HideLabel] [TabGroup("UI构建配置")] [SerializeField]
public UIScriptGenerateConfig UIScriptGenerateConfig;
[Required] [DisableInPlayMode] [HideLabel] [TabGroup("UI元素映射")] [SerializeField] [TableList(ShowIndexLabels = false, DrawScrollView = true, AlwaysExpanded = true)]
public List<UIEelementRegexData> UIElementRegexConfigs;
private void RefreshLabel()
{
previewLabel = $"{UIGenerateCommonData.GeneratePrefix}_UITestWindow";
previewCompLabel = $"{UIGenerateCommonData.ArrayComSplitName}Text{UIGenerateCommonData.ComCheckSplitName}Img" +
$"{UIGenerateCommonData.ComCheckEndName}Test{UIGenerateCommonData.ArrayComSplitName}0";
}
[TabGroup("UI元素映射")]
[Sirenix.OdinInspector.Button("加载默认")]
private void LoadDefaultConfig()
{
const string Path = UIGlobalPath.DefaultComPath;
string text = System.IO.File.ReadAllText(Path);
UIElementRegexConfigs = JsonConvert.DeserializeObject<List<UIEelementRegexData>>(text);
}
[TabGroup("UI元素映射")]
[Sirenix.OdinInspector.Button("导出")]
private void ExportConfig()
{
var json = JsonConvert.SerializeObject(UIElementRegexConfigs);
System.IO.File.WriteAllText("Assets/uielementconfig.txt", json);
AssetDatabase.Refresh();
Debug.Log("Export UIElements Finished");
}
[TabGroup("UI元素映射")]
[Sirenix.OdinInspector.Button("导入")]
private void ImportConfig(TextAsset text)
{
UIElementRegexConfigs = JsonConvert.DeserializeObject<List<UIEelementRegexData>>(text.text);
Debug.Log("Import UIElements Finished");
}
protected override void OnDisable()
{
base.OnDisable();
uiGenerateConfiguration.UIGenerateCommonData = UIGenerateCommonData;
uiGenerateConfiguration.UIScriptGenerateConfig = UIScriptGenerateConfig;
uiGenerateConfiguration.UIElementRegexConfigs = UIElementRegexConfigs;
EditorUtility.SetDirty(uiGenerateConfiguration);
AssetDatabase.SaveAssets();
UIGenerateConfiguration.Save();
}
protected override void OnDestroy()
{
base.OnDestroy();
uiGenerateConfiguration.UIGenerateCommonData = UIGenerateCommonData;
uiGenerateConfiguration.UIScriptGenerateConfig = UIScriptGenerateConfig;
uiGenerateConfiguration.UIElementRegexConfigs = UIElementRegexConfigs;
EditorUtility.SetDirty(uiGenerateConfiguration);
AssetDatabase.SaveAssets();
UIGenerateConfiguration.Save();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6e004459b3645d4b3022bdde89795b9
timeCreated: 1741340568

3
Editor/UI/Inspector.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c775eb6a6aca4533bc75c89ef7a219a1
timeCreated: 1737704983

View File

@ -0,0 +1,62 @@
using System;
using AlicizaX.Editor;
using AlicizaX.UI.Runtime;
using UnityEditor;
using UnityEngine;
namespace AlicizaX.UI.Editor
{
[CustomEditor(typeof(UIComponent))]
internal sealed class UIComponentInspector : GameFrameworkInspector
{
private SerializedProperty uiRoot;
private SerializedProperty _isOrthographic;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
if (uiRoot.objectReferenceValue == null)
{
EditorGUILayout.HelpBox("uiroot can not be null!", MessageType.Error);
}
EditorGUILayout.BeginHorizontal();
GameObject rootPrefab = (GameObject)EditorGUILayout.ObjectField("UI根预设", uiRoot.objectReferenceValue, typeof(GameObject), false);
if (rootPrefab != uiRoot.objectReferenceValue)
{
uiRoot.objectReferenceValue = rootPrefab;
}
if (uiRoot.objectReferenceValue == null)
{
if (GUILayout.Button("设置默认"))
{
GameObject defaultPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(UIGlobalPath.UIPrefabPath);
uiRoot.objectReferenceValue = defaultPrefab;
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(_isOrthographic);
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
private void OnEnable()
{
uiRoot = serializedObject.FindProperty("uiRoot");
_isOrthographic = serializedObject.FindProperty("_isOrthographic");
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6c8dd72e28584576864a33af24255060
timeCreated: 1737704960

8
Editor/UI/Res.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1adcae2abd30deb478273eb8d2a4a1ac
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

312
Editor/UI/Res/UIRoot.prefab Normal file
View File

@ -0,0 +1,312 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &500891838716286123
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5373281001294974998}
- component: {fileID: 743195302492612381}
- component: {fileID: 7227605137039161963}
m_Layer: 0
m_Name: UICamera
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5373281001294974998
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 500891838716286123}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 86062277508691697}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!20 &743195302492612381
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 500891838716286123}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 3
m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 10
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: 2
m_CullingMask:
serializedVersion: 2
m_Bits: 32
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 0
m_AllowMSAA: 0
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!114 &7227605137039161963
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 500891838716286123}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_RenderShadows: 0
m_RequiresDepthTextureOption: 0
m_RequiresOpaqueTextureOption: 0
m_CameraType: 0
m_Cameras: []
m_RendererIndex: -1
m_VolumeLayerMask:
serializedVersion: 2
m_Bits: 0
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2
m_StopNaN: 0
m_Dithering: 0
m_ClearDepth: 1
m_AllowXRRendering: 1
m_AllowHDROutput: 1
m_UseScreenCoordOverride: 0
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_Version: 2
m_TaaSettings:
m_Quality: 3
m_FrameInfluence: 0.1
m_JitterScale: 1
m_MipBias: 0
m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0
--- !u!1 &1735351593002053547
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3110666966229274110}
- component: {fileID: 4697108639102116370}
- component: {fileID: 3475475550181341661}
- component: {fileID: 6941144161958937340}
m_Layer: 5
m_Name: UICanvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3110666966229274110
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 86062277508691697}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!223 &4697108639102116370
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 1
m_Camera: {fileID: 743195302492612381}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 1
m_AdditionalShaderChannelsFlag: 27
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!114 &3475475550181341661
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 1
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 1920, y: 1080}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 0
--- !u!114 &6941144161958937340
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1735351593002053547}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 55
--- !u!1 &4612363183729467837
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 86062277508691697}
- component: {fileID: 2601148299080526511}
- component: {fileID: 4177649269856392400}
m_Layer: 0
m_Name: UIRoot
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &86062277508691697
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4612363183729467837}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1000, y: 1000, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3110666966229274110}
- {fileID: 5373281001294974998}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2601148299080526511
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4612363183729467837}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!114 &4177649269856392400
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4612363183729467837}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 0}
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_DeselectOnBackgroundClick: 1
m_PointerBehavior: 0
m_CursorLockBehavior: 0
m_ScrollDeltaPerTick: 6

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9368ff38b2090b2468f8358242026e4b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1 @@
[{"uiElementRegex":"Rect","componentType":"RectTransform"},{"uiElementRegex":"Obj","componentType":"GameObject"},{"uiElementRegex":"Tf","componentType":"Transform"},{"uiElementRegex":"Btn","componentType":"UXButton"},{"uiElementRegex":"Slider","componentType":"Slider"},{"uiElementRegex":"Img","componentType":"Image"},{"uiElementRegex":"RImg","componentType":"RawImage"},{"uiElementRegex":"Scrollbar","componentType":"Scrollbar"},{"uiElementRegex":"ScrollRect","componentType":"ScrollRect"},{"uiElementRegex":"GLayout","componentType":"GridLayoutGroup"},{"uiElementRegex":"HLayout","componentType":"HorizontalLayoutGroup"},{"uiElementRegex":"VLayout","componentType":"VerticalLayoutGroup"},{"uiElementRegex":"Text","componentType":"TMPro.TextMeshProUGUI"},{"uiElementRegex":"TogGroup","componentType":"UXGroup"},{"uiElementRegex":"Mask2D","componentType":"RectMask2D"},{"uiElementRegex":"Video","componentType":"Video.VideoPlayer"},{"uiElementRegex":"Input","componentType":"TMPro.TMP_InputField"},{"uiElementRegex":"CanvasGroup","componentType":"CanvasGroup"},{"uiElementRegex":"ScrollView","componentType":"RecyclerView"},{"uiElementRegex":"Drag","componentType":"UXDraggable"}]

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cd96f3d9dd2a90d40a81a1d4319ce8f2
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

3
Editor/UI/UIConfig.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2f54df36513f40bd80b00f7149741495
timeCreated: 1737704936

View File

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AlicizaX.Editor.Setting;
using AlicizaX;
using AlicizaX.UI.Runtime;
using Newtonsoft.Json;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Serialization;
namespace AlicizaX.UI.Editor
{
[AlicizaX.Editor.Setting.FilePath("ProjectSettings/UIGenerateConfiguration.asset")]
internal class UIGenerateConfiguration : ScriptableSingleton<UIGenerateConfiguration>
{
public UIGenerateCommonData UIGenerateCommonData = new UIGenerateCommonData();
public UIScriptGenerateConfig UIScriptGenerateConfig = new UIScriptGenerateConfig();
public List<UIEelementRegexData> UIElementRegexConfigs = new List<UIEelementRegexData>();
}
[System.Serializable]
public class UIGenerateCommonData
{
[LabelText("组件检查分隔符")] public string ComCheckSplitName = "#";
[LabelText("组件结尾分隔符")] public string ComCheckEndName = "@";
[LabelText("数组组件检查分隔符")] public string ArrayComSplitName = "*";
[LabelText("生成脚本前缀")] public string GeneratePrefix = "ui";
[LabelText("排除表")] public string[] ExcludeKeywords = { "ViewHolder" };
[ShowInInspector] [LabelText("生成路径拼接")]
public Dictionary<string, string> CombineWords = new Dictionary<string, string>
{
{ "Window", "Window" },
{ "ViewHolder", "ViewHolder" },
{ "Widget", "Widget" },
};
}
[System.Serializable]
public class UIEelementRegexData
{
public string uiElementRegex;
[ShowInInspector] [ValueDropdown("GetFilteredTypeList", ExpandAllMenuItems = false)]
public string componentType;
private static List<string> cacheFilterType;
public IEnumerable<string> GetFilteredTypeList()
{
if (cacheFilterType == null)
{
cacheFilterType = AlicizaX.Utility.Assembly.GetTypes()
.Where(m => !m.FullName.Contains("Editor"))
.Where(x => !x.IsAbstract || x.IsInterface)
.Where(x => !x.IsGenericTypeDefinition)
.Where(x => !x.IsSubclassOf(typeof(UIHolderObjectBase)))
.Where(x => x.IsSubclassOf(typeof(Component)))
.Where(x => !x.FullName.Contains("YooAsset"))
.Where(x => !x.FullName.Contains(("Unity.VisualScripting")))
.Where(x => !x.FullName.Contains(("Cysharp.Threading")))
.Where(x => !x.FullName.Contains(("UnityEngine.Rendering.UI.Debug")))
.Where(x => !x.FullName.Contains(("Unity.PerformanceTesting")))
.Where(x => !x.FullName.Contains(("UnityEngine.TestTools")))
.Select(x => x.Name).ToList();
cacheFilterType.Add(typeof(GameObject).Name);
}
return cacheFilterType;
}
}
[System.Serializable]
public class UIScriptGenerateConfig
{
[BoxGroup("主工程")] public UIScriptGenerateData MainProjectUIScriptGenerateData = new UIScriptGenerateData();
[BoxGroup("热更工程")] public UIScriptGenerateData HotFixProjectUIScriptGenerateData = new UIScriptGenerateData();
}
[System.Serializable]
public class UIScriptGenerateData
{
public string NameSpace;
[Sirenix.OdinInspector.FolderPath(RequireExistingPath = true, AbsolutePath = false)]
public string GenerateHolderCodePath;
[Sirenix.OdinInspector.FolderPath(RequireExistingPath = true, AbsolutePath = false)]
public string UIPrefabRootPath;
public EUIResLoadType LoadType;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b212f141eb1bc7b4d97c4dc8b938bc5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
namespace AlicizaX.UI.Editor
{
internal static class UIGlobalPath
{
public const string DefaultComPath = "Packages/com.alicizax.unity.framework/Editor/UI/Res/default.txt";
public const string UIPrefabPath = "Packages/com.alicizax.unity.framework/Editor/UI/Res/UIRoot.prefab";
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 665aa33b3f2e467bb675bb8da795bd21
timeCreated: 1757063844

201
LICENSE.md Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [2023] [ALianBlank of copyright owner][alianblank@outlook.com][https://alianblank.com/]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

7
LICENSE.md.meta Normal file
View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 773fb24b0f5c014438958e2dc2fe62d7
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Plugins.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a3e79e61e313b2b4ebf21a5b9afb39a3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Plugins/UI.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f372db68a9aaada4592cb3015b15773d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -0,0 +1,52 @@
fileFormatVersion: 2
guid: 4073667e4abebeb479ff5f9810398e92
labels:
- RoslynAnalyzer
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Any:
enabled: 1
settings:
Exclude Editor: 1
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 0
Editor:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux64:
enabled: 1
settings:
CPU: AnyCPU
OSXUniversal:
enabled: 1
settings:
CPU: AnyCPU
Win:
enabled: 1
settings:
CPU: AnyCPU
Win64:
enabled: 1
settings:
CPU: AnyCPU
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

8
Runtime.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 98f26ef6a50ff52458b160222752dfec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
{
"name": "AlicizaX.Framework.Runtime",
"rootNamespace": "AlicizaX.Framework.Runtime",
"references": [
"GUID:75b6f2078d190f14dbda4a5b747d709c",
"GUID:b4c00b967a932af48b2e067403eecbe2",
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:760f1778adc613f49a4394fb41ff0bbc",
"GUID:189d55e03d78888459720d730f4d2424"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.alicizax.unity.ui.extension",
"expression": "",
"define": "ALICIZAX_UI_EXTENSION_SUPPORT"
},
{
"name": "com.alicizax.unity.animationflow",
"expression": "",
"define": "ALICIZAX_UI_ANIMATION_SUPPORT"
}
],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1619e00706139ce488ff80c0daeea8e7
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

3
Runtime/Audio.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 65ab69a3b3c64f22b899938b5234583f
timeCreated: 1737390310

455
Runtime/Audio/AudioAgent.cs Normal file
View File

@ -0,0 +1,455 @@
using AlicizaX.Resource.Runtime;
using AlicizaX;
using UnityEngine;
using UnityEngine.Audio;
using YooAsset;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音频代理辅助器。
/// </summary>
public class AudioAgent
{
private int _instanceId;
private AudioSource _source;
private AudioData _audioData;
private IAudioModule _audioModule;
private IResourceModule _resourceModule;
private Transform _transform;
private float _volume = 1.0f;
private float _duration;
private float _fadeoutTimer;
private const float FADEOUT_DURATION = 0.2f;
private bool _inPool;
/// <summary>
/// 音频代理辅助器运行时状态。
/// </summary>
AudioAgentRuntimeState _audioAgentRuntimeState = AudioAgentRuntimeState.None;
/// <summary>
/// 音频代理加载请求。
/// </summary>
class LoadRequest
{
/// <summary>
/// 音频代理辅助器加载路径。
/// </summary>
public string Path;
/// <summary>
/// 是否异步。
/// </summary>
public bool BAsync;
/// <summary>
/// 是否池化。
/// </summary>
public bool BInPool;
}
/// <summary>
/// 音频代理加载请求。
/// </summary>
LoadRequest _pendingLoad = null;
/// <summary>
/// AudioSource实例化Id
/// </summary>
public int InstanceId => _instanceId;
/// <summary>
/// 资源操作句柄。
/// </summary>
public AudioData AudioData => _audioData;
/// <summary>
/// 音频代理辅助器音频大小。
/// </summary>
public float Volume
{
set
{
if (_source != null)
{
_volume = value;
_source.volume = _volume;
}
}
get => _volume;
}
/// <summary>
/// 音频代理辅助器当前是否空闲。
/// </summary>
public bool IsFree
{
get
{
if (_source != null)
{
return _audioAgentRuntimeState == AudioAgentRuntimeState.End;
}
else
{
return true;
}
}
}
/// <summary>
/// 音频代理辅助器播放秒数。
/// </summary>
public float Duration => _duration;
/// <summary>
/// 音频代理辅助器当前音频长度。
/// </summary>
public float Length
{
get
{
if (_source != null && _source.clip != null)
{
return _source.clip.length;
}
return 0;
}
}
/// <summary>
/// 音频代理辅助器实例位置。
/// </summary>
public Vector3 Position
{
get => _transform.position;
set => _transform.position = value;
}
/// <summary>
/// 音频代理辅助器是否循环。
/// </summary>
public bool IsLoop
{
get
{
if (_source != null)
{
return _source.loop;
}
else
{
return false;
}
}
set
{
if (_source != null)
{
_source.loop = value;
}
}
}
/// <summary>
/// 音频代理辅助器是否正在播放。
/// </summary>
internal bool IsPlaying
{
get
{
if (_source != null && _source.isPlaying)
{
return true;
}
else
{
return false;
}
}
}
/// <summary>
/// 音频代理辅助器获取当前声源。
/// </summary>
/// <returns></returns>
public AudioSource AudioResource()
{
return _source;
}
/// <summary>
/// 创建音频代理辅助器。
/// </summary>
/// <param name="path">生效路径。</param>
/// <param name="bAsync">是否异步。</param>
/// <param name="audioCategory">音频轨道(类别)。</param>
/// <param name="bInPool">是否池化。</param>
/// <returns>音频代理辅助器。</returns>
public static AudioAgent Create(string path, bool bAsync, AudioCategory audioCategory, bool bInPool = false)
{
AudioAgent audioAgent = new AudioAgent();
audioAgent.Init(audioCategory);
audioAgent.Load(path, bAsync, bInPool);
return audioAgent;
}
public static AudioAgent Create(AudioClip clip, AudioCategory audioCategory)
{
AudioAgent audioAgent = new AudioAgent();
audioAgent.Init(audioCategory);
audioAgent.SetAudioClip(clip);
return audioAgent;
}
public void SetAudioClip(AudioClip clip)
{
if (_source == null)
return;
Stop(false);
if (_audioData != null)
{
AudioData.DeAlloc(_audioData);
_audioData = null;
}
_source.clip = clip;
if (clip != null)
{
_source.Play();
_audioAgentRuntimeState = AudioAgentRuntimeState.Playing;
_duration = 0;
}
else
{
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
}
}
/// <summary>
/// 初始化音频代理辅助器。
/// </summary>
/// <param name="audioCategory">音频轨道(类别)。</param>
/// <param name="index">音频代理辅助器编号。</param>
public void Init(AudioCategory audioCategory, int index = 0)
{
_audioModule = ModuleSystem.GetModule<IAudioModule>();
_resourceModule = ModuleSystem.GetModule<IResourceModule>();
GameObject host = new GameObject(Utility.Text.Format("Audio Agent Helper - {0} - {1}", audioCategory.AudioMixerGroup.name, index));
host.transform.SetParent(audioCategory.InstanceRoot);
host.transform.localPosition = Vector3.zero;
_transform = host.transform;
_source = host.AddComponent<AudioSource>();
_source.playOnAwake = false;
AudioMixerGroup[] audioMixerGroups =
audioCategory.AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", audioCategory.AudioMixerGroup.name,
$"{audioCategory.AudioMixerGroup.name} - {index}"));
_source.outputAudioMixerGroup = audioMixerGroups.Length > 0 ? audioMixerGroups[0] : audioCategory.AudioMixerGroup;
_source.rolloffMode = audioCategory.AudioGroupConfig.audioRolloffMode;
_source.minDistance = audioCategory.AudioGroupConfig.minDistance;
_source.maxDistance = audioCategory.AudioGroupConfig.maxDistance;
_instanceId = _source.GetInstanceID();
}
/// <summary>
/// 加载音频代理辅助器。
/// </summary>
/// <param name="path">资源路径。</param>
/// <param name="bAsync">是否异步。</param>
/// <param name="bInPool">是否池化。</param>
public void Load(string path, bool bAsync, bool bInPool = false)
{
_inPool = bInPool;
if (_audioAgentRuntimeState == AudioAgentRuntimeState.None || _audioAgentRuntimeState == AudioAgentRuntimeState.End)
{
_duration = 0;
if (!string.IsNullOrEmpty(path))
{
if (bInPool && _audioModule.AudioClipPool.TryGetValue(path, out var operationHandle))
{
OnAssetLoadComplete(operationHandle);
return;
}
if (bAsync)
{
_audioAgentRuntimeState = AudioAgentRuntimeState.Loading;
AssetHandle handle = _resourceModule.LoadAssetAsyncHandle<AudioClip>(path);
handle.Completed += OnAssetLoadComplete;
}
else
{
AssetHandle handle = _resourceModule.LoadAssetSyncHandle<AudioClip>(path);
OnAssetLoadComplete(handle);
}
}
}
else
{
_pendingLoad = new LoadRequest { Path = path, BAsync = bAsync, BInPool = bInPool };
if (_audioAgentRuntimeState == AudioAgentRuntimeState.Playing)
{
Stop(true);
}
}
}
/// <summary>
/// 停止播放音频代理辅助器。
/// </summary>
/// <param name="fadeout">是否渐出。</param>
public void Stop(bool fadeout = false)
{
if (_source != null)
{
if (fadeout)
{
_fadeoutTimer = FADEOUT_DURATION;
_audioAgentRuntimeState = AudioAgentRuntimeState.FadingOut;
}
else
{
_source.Stop();
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
}
}
}
/// <summary>
/// 暂停音频代理辅助器。
/// </summary>
public void Pause()
{
if (_source != null)
{
_source.Pause();
}
}
/// <summary>
/// 取消暂停音频代理辅助器。
/// </summary>
public void UnPause()
{
if (_source != null)
{
_source.UnPause();
}
}
/// <summary>
/// 资源加载完成。
/// </summary>
/// <param name="handle">资源操作句柄。</param>
void OnAssetLoadComplete(AssetHandle handle)
{
if (handle != null)
{
if (_inPool)
{
_audioModule.AudioClipPool.TryAdd(handle.GetAssetInfo().Address, handle);
}
}
if (_pendingLoad != null)
{
if (!_inPool && handle != null)
{
handle.Dispose();
}
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
string path = _pendingLoad.Path;
bool bAsync = _pendingLoad.BAsync;
bool bInPool = _pendingLoad.BInPool;
_pendingLoad = null;
Load(path, bAsync, bInPool);
}
else if (handle != null)
{
if (_audioData != null)
{
AudioData.DeAlloc(_audioData);
_audioData = null;
}
_audioData = AudioData.Alloc(handle, _inPool);
_source.clip = handle.AssetObject as AudioClip;
if (_source.clip != null)
{
_source.Play();
_audioAgentRuntimeState = AudioAgentRuntimeState.Playing;
}
else
{
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
}
}
else
{
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
}
}
/// <summary>
/// 轮询音频代理辅助器。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
public void Update(float elapseSeconds)
{
if (_audioAgentRuntimeState == AudioAgentRuntimeState.Playing)
{
if (!_source.isPlaying)
{
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
}
}
else if (_audioAgentRuntimeState == AudioAgentRuntimeState.FadingOut)
{
if (_fadeoutTimer > 0f)
{
_fadeoutTimer -= elapseSeconds;
_source.volume = _volume * _fadeoutTimer / FADEOUT_DURATION;
}
else
{
Stop();
if (_pendingLoad != null)
{
string path = _pendingLoad.Path;
bool bAsync = _pendingLoad.BAsync;
bool bInPool = _pendingLoad.BInPool;
_pendingLoad = null;
Load(path, bAsync, bInPool);
}
_source.volume = _volume;
}
}
_duration += elapseSeconds;
}
/// <summary>
/// 销毁音频代理辅助器。
/// </summary>
public void Destroy()
{
if (_transform != null)
{
Object.Destroy(_transform.gameObject);
}
if (_audioData != null)
{
AudioData.DeAlloc(_audioData);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d4824a14181a0d4d921eb98fec100fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音频代理辅助器运行时状态枚举。
/// </summary>
public enum AudioAgentRuntimeState
{
/// <summary>
/// 无状态。
/// </summary>
None,
/// <summary>
/// 加载中状态。
/// </summary>
Loading,
/// <summary>
/// 播放中状态。
/// </summary>
Playing,
/// <summary>
/// 渐渐消失状态。
/// </summary>
FadingOut,
/// <summary>
/// 结束状态。
/// </summary>
End,
};
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f4ad4b8dc4cf4ecd813e58ec37406ba0
timeCreated: 1694849619

View File

@ -0,0 +1,239 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音频轨道(类别)。
/// </summary>
[Serializable]
public class AudioCategory
{
[SerializeField] private AudioMixer audioMixer = null;
public List<AudioAgent> AudioAgents;
private readonly AudioMixerGroup _audioMixerGroup;
private AudioGroupConfig _audioGroupConfig;
private int _maxChannel;
private bool _bEnable = true;
/// <summary>
/// 音频混响器。
/// </summary>
public AudioMixer AudioMixer => audioMixer;
/// <summary>
/// 音频混响器组。
/// </summary>
public AudioMixerGroup AudioMixerGroup => _audioMixerGroup;
/// <summary>
/// 音频组配置。
/// </summary>
public AudioGroupConfig AudioGroupConfig => _audioGroupConfig;
/// <summary>
/// 实例化根节点。
/// </summary>
public Transform InstanceRoot { private set; get; }
/// <summary>
/// 音频轨道是否启用。
/// </summary>
public bool Enable
{
get => _bEnable;
set
{
if (_bEnable != value)
{
_bEnable = value;
if (!_bEnable)
{
foreach (var audioAgent in AudioAgents)
{
if (audioAgent != null)
{
audioAgent.Stop();
}
}
}
}
}
}
/// <summary>
/// 音频轨道构造函数。
/// </summary>
/// <param name="maxChannel">最大Channel。</param>
/// <param name="audioMixer">音频混响器。</param>
/// <param name="audioGroupConfig">音频轨道组配置。</param>
public AudioCategory(int maxChannel, AudioMixer audioMixer, AudioGroupConfig audioGroupConfig)
{
var audioModule = ModuleSystem.GetModule<IAudioModule>();
this.audioMixer = audioMixer;
_maxChannel = maxChannel;
_audioGroupConfig = audioGroupConfig;
AudioMixerGroup[] audioMixerGroups = audioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}", audioGroupConfig.AudioType.ToString()));
if (audioMixerGroups.Length > 0)
{
_audioMixerGroup = audioMixerGroups[0];
}
else
{
_audioMixerGroup = audioMixer.FindMatchingGroups("Master")[0];
}
AudioAgents = new List<AudioAgent>(32);
InstanceRoot = new GameObject(Utility.Text.Format("Audio Category - {0}", _audioMixerGroup.name)).transform;
InstanceRoot.SetParent(audioModule.InstanceRoot);
for (int index = 0; index < _maxChannel; index++)
{
AudioAgent audioAgent = new AudioAgent();
audioAgent.Init(this, index);
AudioAgents.Add(audioAgent);
}
}
/// <summary>
/// 增加音频。
/// </summary>
/// <param name="num"></param>
public void AddAudio(int num)
{
_maxChannel += num;
for (int i = 0; i < num; i++)
{
AudioAgents.Add(null);
}
}
public AudioAgent Play(AudioClip clip)
{
if (!_bEnable)
{
return null;
}
int freeChannel = -1;
float duration = -1;
for (int i = 0; i < AudioAgents.Count; i++)
{
if (AudioAgents[i].IsFree)
{
freeChannel = i;
break;
}
else if (AudioAgents[i].Duration > duration)
{
duration = AudioAgents[i].Duration;
freeChannel = i;
}
}
if (freeChannel >= 0)
{
if (AudioAgents[freeChannel] == null)
{
AudioAgents[freeChannel] = AudioAgent.Create(clip, this);
}
else
{
AudioAgents[freeChannel].SetAudioClip(clip);
}
return AudioAgents[freeChannel];
}
else
{
Log.Error($"Here is no channel to play audio clip");
return null;
}
}
/// <summary>
/// 播放音频。
/// </summary>
/// <param name="path"></param>
/// <param name="bAsync"></param>
/// <param name="bInPool"></param>
/// <returns></returns>
public AudioAgent Play(string path, bool bAsync, bool bInPool = false)
{
if (!_bEnable)
{
return null;
}
int freeChannel = -1;
float duration = -1;
for (int i = 0; i < AudioAgents.Count; i++)
{
if (AudioAgents[i].AudioData?.AssetHandle == null || AudioAgents[i].IsFree)
{
freeChannel = i;
break;
}
else if (AudioAgents[i].Duration > duration)
{
duration = AudioAgents[i].Duration;
freeChannel = i;
}
}
if (freeChannel >= 0)
{
if (AudioAgents[freeChannel] == null)
{
AudioAgents[freeChannel] = AudioAgent.Create(path, bAsync, this, bInPool);
}
else
{
AudioAgents[freeChannel].Load(path, bAsync, bInPool);
}
return AudioAgents[freeChannel];
}
else
{
Log.Error($"Here is no channel to play audio {path}");
return null;
}
}
/// <summary>
/// 暂停音频。
/// </summary>
/// <param name="fadeout">是否渐出</param>
public void Stop(bool fadeout)
{
for (int i = 0; i < AudioAgents.Count; ++i)
{
if (AudioAgents[i] != null)
{
AudioAgents[i].Stop(fadeout);
}
}
}
/// <summary>
/// 音频轨道轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
public void Update(float elapseSeconds)
{
for (int i = 0; i < AudioAgents.Count; ++i)
{
if (AudioAgents[i] != null)
{
AudioAgents[i].Update(elapseSeconds);
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6aefbd5a06fe1784590d373a93d1cf8a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
using AlicizaX;
using UnityEngine;
using UnityEngine.Audio;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音效管理,为游戏提供统一的音效播放接口。
/// </summary>
/// <remarks>场景3D音效挂到场景物件、技能3D音效挂到技能特效上并在AudioSource的Output上设置对应分类的AudioMixerGroup</remarks>
[DisallowMultipleComponent]
[AddComponentMenu("Game Framework/Audio")]
public sealed class AudioComponent : MonoBehaviour
{
[SerializeField] private AudioMixer m_AudioMixer;
[SerializeField] private Transform m_InstanceRoot = null;
[SerializeField] private AudioGroupConfig[] m_AudioGroupConfigs = null;
private IAudioModule _audioModule;
private void Awake()
{
_audioModule = ModuleSystem.RegisterModule<IAudioModule,AudioModule>();
}
/// <summary>
/// 初始化音频模块。
/// </summary>
void Start()
{
if (m_InstanceRoot == null)
{
m_InstanceRoot = new GameObject("[AudioModule Instances]").transform;
m_InstanceRoot.SetParent(gameObject.transform);
m_InstanceRoot.localScale = Vector3.one;
}
if (m_AudioMixer == null)
{
m_AudioMixer = Resources.Load<AudioMixer>("AudioMixer");
}
_audioModule.Initialize(m_AudioGroupConfigs, m_InstanceRoot, m_AudioMixer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7d0b3cff83fd3874394b1b456bb54dab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,67 @@
using AlicizaX;
using YooAsset;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音频数据。
/// </summary>
public class AudioData : MemoryObject
{
/// <summary>
/// 资源句柄。
/// </summary>
public AssetHandle AssetHandle { private set; get; }
/// <summary>
/// 是否使用对象池。
/// </summary>
public bool InPool { private set; get; } = false;
public override void InitFromPool()
{
}
/// <summary>
/// 回收到对象池。
/// </summary>
public override void RecycleToPool()
{
if (!InPool)
{
AssetHandle.Dispose();
}
InPool = false;
AssetHandle = null;
}
/// <summary>
/// 生成音频数据。
/// </summary>
/// <param name="assetHandle">资源操作句柄。</param>
/// <param name="inPool">是否使用对象池。</param>
/// <returns>音频数据。</returns>
internal static AudioData Alloc(AssetHandle assetHandle, bool inPool)
{
AudioData ret = MemoryPool.Acquire<AudioData>();
ret.AssetHandle = assetHandle;
ret.InPool = inPool;
ret.InitFromPool();
return ret;
}
/// <summary>
/// 回收音频数据。
/// </summary>
/// <param name="audioData"></param>
internal static void DeAlloc(AudioData audioData)
{
if (audioData != null)
{
MemoryPool.Release(audioData);
audioData.RecycleToPool();
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 036a1af4acb84666b73909ba28455cfa
timeCreated: 1742472335

View File

@ -0,0 +1,48 @@
using System;
using UnityEngine;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音频轨道组配置。
/// </summary>
[Serializable]
public sealed class AudioGroupConfig
{
[SerializeField] private string m_Name = null;
[SerializeField] private bool m_Mute = false;
[SerializeField, Range(0f, 1f)] private float m_Volume = 1f;
[SerializeField] private int m_AgentHelperCount = 1;
public AudioType AudioType;
public AudioRolloffMode audioRolloffMode = AudioRolloffMode.Logarithmic;
public float minDistance = 1f;
public float maxDistance = 500f;
public string Name
{
get { return m_Name; }
}
public bool Mute
{
get { return m_Mute; }
}
public float Volume
{
get { return m_Volume; }
}
public int AgentHelperCount
{
get { return m_AgentHelperCount; }
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 067935df275fd1340a935f81e7f3a768
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,593 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AlicizaX.Resource.Runtime;
using AlicizaX;
using UnityEngine;
using UnityEngine.Audio;
using YooAsset;
using AudioType = AlicizaX.Audio.Runtime.AudioType;
namespace AlicizaX.Audio.Runtime
{
internal class AudioModule : IAudioModule
{
public const string MUSIC_VOLUME_NAME = "MusicVolume";
public const string UI_SOUND_VOLUME_NAME = "UISoundVolume";
public const string VOICE_VOLUME_NAME = "VoiceVolume";
private AudioMixer _audioMixer;
private Transform _instanceRoot = null;
private AudioGroupConfig[] _audioGroupConfigs = null;
private float _volume = 1f;
private bool _enable = true;
private readonly AudioCategory[] _audioCategories = new AudioCategory[(int)AudioType.Max];
private readonly float[] _categoriesVolume = new float[(int)AudioType.Max];
private bool _bUnityAudioDisabled = false;
#region Public Propreties
public Dictionary<string, AssetHandle> AudioClipPool { get; set; } = new Dictionary<string, AssetHandle>();
/// <summary>
/// 音频混响器。
/// </summary>
public AudioMixer AudioMixer => _audioMixer;
/// <summary>
/// 实例化根节点。
/// </summary>
public Transform InstanceRoot => _instanceRoot;
/// <summary>
/// 总音量控制。
/// </summary>
public float Volume
{
get
{
if (_bUnityAudioDisabled)
{
return 0.0f;
}
return _volume;
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
_volume = value;
AudioListener.volume = _volume;
}
}
/// <summary>
/// 总开关。
/// </summary>
public bool Enable
{
get
{
if (_bUnityAudioDisabled)
{
return false;
}
return _enable;
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
_enable = value;
AudioListener.volume = _enable ? _volume : 0f;
}
}
/// <summary>
/// 音乐音量。
/// </summary>
public float MusicVolume
{
get
{
if (_bUnityAudioDisabled)
{
return 0.0f;
}
return _categoriesVolume[(int)AudioType.Music];
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
_categoriesVolume[(int)AudioType.Music] = volume;
_audioMixer.SetFloat(MUSIC_VOLUME_NAME, Mathf.Log10(volume) * 20f);
}
}
/// <summary>
/// 音效音量。
/// </summary>
public float SoundVolume
{
get
{
if (_bUnityAudioDisabled)
{
return 0.0f;
}
return _categoriesVolume[(int)AudioType.Sound];
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
_categoriesVolume[(int)AudioType.Sound] = volume;
_audioMixer.SetFloat("SoundVolume", Mathf.Log10(volume) * 20f);
}
}
/// <summary>
/// UI音效音量。
/// </summary>
public float UISoundVolume
{
get
{
if (_bUnityAudioDisabled)
{
return 0.0f;
}
return _categoriesVolume[(int)AudioType.UISound];
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
_categoriesVolume[(int)AudioType.UISound] = volume;
_audioMixer.SetFloat(UI_SOUND_VOLUME_NAME, Mathf.Log10(volume) * 20f);
}
}
/// <summary>
/// 语音音量。
/// </summary>
public float VoiceVolume
{
get
{
if (_bUnityAudioDisabled)
{
return 0.0f;
}
return _categoriesVolume[(int)AudioType.Voice];
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
float volume = Mathf.Clamp(value, 0.0001f, 1.0f);
_categoriesVolume[(int)AudioType.Voice] = volume;
_audioMixer.SetFloat(VOICE_VOLUME_NAME, Mathf.Log10(volume) * 20f);
}
}
/// <summary>
/// 音乐开关
/// </summary>
public bool MusicEnable
{
get
{
if (_bUnityAudioDisabled)
{
return false;
}
if (_audioMixer.GetFloat(MUSIC_VOLUME_NAME, out var db))
{
return db > -80f;
}
else
{
return false;
}
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
_audioCategories[(int)AudioType.Music].Enable = value;
// 音乐采用0音量方式避免恢复播放时的复杂逻辑
if (value)
{
_audioMixer.SetFloat(MUSIC_VOLUME_NAME, Mathf.Log10(_categoriesVolume[(int)AudioType.Music]) * 20f);
}
else
{
_audioMixer.SetFloat(MUSIC_VOLUME_NAME, -80f);
}
}
}
/// <summary>
/// 音效开关。
/// </summary>
public bool SoundEnable
{
get
{
if (_bUnityAudioDisabled)
{
return false;
}
return _audioCategories[(int)AudioType.Sound].Enable;
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
_audioCategories[(int)AudioType.Sound].Enable = value;
}
}
/// <summary>
/// UI音效开关。
/// </summary>
public bool UISoundEnable
{
get
{
if (_bUnityAudioDisabled)
{
return false;
}
return _audioCategories[(int)AudioType.UISound].Enable;
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
_audioCategories[(int)AudioType.UISound].Enable = value;
}
}
/// <summary>
/// 语音开关。
/// </summary>
public bool VoiceEnable
{
get
{
if (_bUnityAudioDisabled)
{
return false;
}
return _audioCategories[(int)AudioType.Voice].Enable;
}
set
{
if (_bUnityAudioDisabled)
{
return;
}
_audioCategories[(int)AudioType.Voice].Enable = value;
}
}
#endregion
private IResourceModule _resourceModule;
void IModule.Dispose()
{
StopAll(fadeout: false);
CleanSoundPool();
}
/// <summary>
/// 初始化音频模块。
/// </summary>
/// <param name="audioGroupConfigs">音频轨道组配置。</param>
/// <param name="instanceRoot">实例化根节点。</param>
/// <param name="audioMixer">音频混响器。</param>
/// <exception cref="GameFrameworkException"></exception>
public void Initialize(AudioGroupConfig[] audioGroupConfigs, Transform instanceRoot = null, AudioMixer audioMixer = null)
{
_resourceModule = ModuleSystem.GetModule<IResourceModule>();
if (_instanceRoot == null)
{
_instanceRoot = instanceRoot;
}
if (audioGroupConfigs == null)
{
throw new GameFrameworkException("AudioGroupConfig[] is invalid.");
}
_audioGroupConfigs = audioGroupConfigs;
if (_instanceRoot == null)
{
_instanceRoot = new GameObject("[AudioModule Instances]").transform;
_instanceRoot.localScale = Vector3.one;
UnityEngine.Object.DontDestroyOnLoad(_instanceRoot);
}
#if UNITY_EDITOR
try
{
TypeInfo typeInfo = typeof(AudioSettings).GetTypeInfo();
PropertyInfo propertyInfo = typeInfo.GetDeclaredProperty("unityAudioDisabled");
_bUnityAudioDisabled = (bool)propertyInfo.GetValue(null);
if (_bUnityAudioDisabled)
{
return;
}
}
catch (Exception e)
{
Log.Error(e.ToString());
}
#endif
if (audioMixer != null)
{
_audioMixer = audioMixer;
}
if (_audioMixer == null)
{
_audioMixer = Resources.Load<AudioMixer>("AudioMixer");
}
for (int index = 0; index < (int)AudioType.Max; ++index)
{
AudioType audioType = (AudioType)index;
AudioGroupConfig audioGroupConfig = _audioGroupConfigs.First(t => t.AudioType == audioType);
_audioCategories[index] = new AudioCategory(audioGroupConfig.AgentHelperCount, _audioMixer, audioGroupConfig);
_categoriesVolume[index] = audioGroupConfig.Volume;
}
}
/// <summary>
/// 重启音频模块。
/// </summary>
public void Restart()
{
if (_bUnityAudioDisabled)
{
return;
}
CleanSoundPool();
for (int i = 0; i < (int)AudioType.Max; ++i)
{
var audioCategory = _audioCategories[i];
if (audioCategory != null)
{
for (int j = 0; j < audioCategory.AudioAgents.Count; ++j)
{
var audioAgent = audioCategory.AudioAgents[j];
if (audioAgent != null)
{
audioAgent.Destroy();
audioAgent = null;
}
}
}
audioCategory = null;
}
Initialize(_audioGroupConfigs);
}
/// <summary>
/// 播放如果超过最大发声数采用fadeout的方式复用最久播放的AudioSource。
/// </summary>
/// <param name="type">声音类型</param>
/// <param name="path">声音文件路径</param>
/// <param name="bLoop">是否循环播放</param>>
/// <param name="volume">音量0-1.0</param>
/// <param name="bAsync">是否异步加载</param>
/// <param name="bInPool">是否支持资源池</param>
public AudioAgent Play(AudioType type, string path, bool bLoop = false, float volume = 1.0f, bool bAsync = false, bool bInPool = false)
{
if (_bUnityAudioDisabled)
{
return null;
}
AudioAgent audioAgent = _audioCategories[(int)type].Play(path, bAsync, bInPool);
{
if (audioAgent != null)
{
audioAgent.IsLoop = bLoop;
audioAgent.Volume = volume;
}
return audioAgent;
}
}
public AudioAgent Play(AudioType type, AudioClip clip, bool bLoop = false, float volume = 1.0f)
{
if (_bUnityAudioDisabled)
{
return null;
}
AudioAgent audioAgent = _audioCategories[(int)type].Play(clip);
{
if (audioAgent != null)
{
audioAgent.IsLoop = bLoop;
audioAgent.Volume = volume;
}
return audioAgent;
}
}
/// <summary>
/// 停止某类声音播放。
/// </summary>
/// <param name="type">声音类型。</param>
/// <param name="fadeout">是否渐消。</param>
public void Stop(AudioType type, bool fadeout)
{
if (_bUnityAudioDisabled)
{
return;
}
_audioCategories[(int)type].Stop(fadeout);
}
/// <summary>
/// 停止所有声音。
/// </summary>
/// <param name="fadeout">是否渐消。</param>
public void StopAll(bool fadeout)
{
if (_bUnityAudioDisabled)
{
return;
}
for (int i = 0; i < (int)AudioType.Max; ++i)
{
if (_audioCategories[i] != null)
{
_audioCategories[i].Stop(fadeout);
}
}
}
/// <summary>
/// 预先加载AudioClip并放入对象池。
/// </summary>
/// <param name="list">AudioClip的AssetPath集合。</param>
public void PutInAudioPool(List<string> list)
{
if (_bUnityAudioDisabled)
{
return;
}
foreach (string path in list)
{
if (AudioClipPool != null && !AudioClipPool.ContainsKey(path))
{
AssetHandle assetData = _resourceModule.LoadAssetAsyncHandle<AudioClip>(path);
assetData.Completed += handle => { AudioClipPool?.Add(path, handle); };
}
}
}
/// <summary>
/// 将部分AudioClip从对象池移出。
/// </summary>
/// <param name="list">AudioClip的AssetPath集合。</param>
public void RemoveClipFromPool(List<string> list)
{
if (_bUnityAudioDisabled)
{
return;
}
foreach (string path in list)
{
if (AudioClipPool.ContainsKey(path))
{
AudioClipPool[path].Dispose();
AudioClipPool.Remove(path);
}
}
}
/// <summary>
/// 清空AudioClip的对象池。
/// </summary>
public void CleanSoundPool()
{
if (_bUnityAudioDisabled)
{
return;
}
foreach (var dic in AudioClipPool)
{
dic.Value.Dispose();
}
AudioClipPool.Clear();
}
/// <summary>
/// 音频模块轮询。
/// </summary>
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
void IModuleUpdate.Update(float elapseSeconds, float realElapseSeconds)
{
foreach (var audioCategory in _audioCategories)
{
if (audioCategory != null)
{
audioCategory.Update(elapseSeconds);
}
}
}
public int Priority { get; }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c35bbf6a82844c72b71b9bbe44f44a1e
timeCreated: 1694847017

View File

@ -0,0 +1,34 @@
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音效分类,可分别关闭/开启对应分类音效。
/// </summary>
/// <remarks>命名与AudioMixer中分类名保持一致。</remarks>
public enum AudioType
{
/// <summary>
/// 声音音效。
/// </summary>
Sound,
/// <summary>
/// UI声效。
/// </summary>
UISound,
/// <summary>
/// 背景音乐音效。
/// </summary>
Music,
/// <summary>
/// 人声音效。
/// </summary>
Voice,
/// <summary>
/// 最大。
/// </summary>
Max
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b4b86f93180273b4996d4f8c428def09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,130 @@
using System.Collections.Generic;
using AlicizaX;
using UnityEngine;
using UnityEngine.Audio;
using YooAsset;
namespace AlicizaX.Audio.Runtime
{
public interface IAudioModule:IModule,IModuleUpdate
{
/// <summary>
/// 总音量控制。
/// </summary>
public float Volume { get; set; }
/// <summary>
/// 总开关。
/// </summary>
public bool Enable { get; set; }
/// <summary>
/// 音乐音量
/// </summary>
public float MusicVolume { get; set; }
/// <summary>
/// 音效音量。
/// </summary>
public float SoundVolume { get; set; }
/// <summary>
/// UI音效音量。
/// </summary>
public float UISoundVolume { get; set; }
/// <summary>
/// 语音音量。
/// </summary>
public float VoiceVolume { get; set; }
/// <summary>
/// 音乐开关。
/// </summary>
public bool MusicEnable { get; set; }
/// <summary>
/// 音效开关。
/// </summary>
public bool SoundEnable { get; set; }
/// <summary>
/// UI音效开关。
/// </summary>
public bool UISoundEnable { get; set; }
/// <summary>
/// 语音开关。
/// </summary>
public bool VoiceEnable { get; set; }
/// <summary>
/// 音频混响器。
/// </summary>
public AudioMixer AudioMixer { get;}
/// <summary>
/// 实例化根节点。
/// </summary>
public Transform InstanceRoot { get;}
public Dictionary<string, AssetHandle> AudioClipPool { get; set; }
/// <summary>
/// 初始化音频模块。
/// </summary>
/// <param name="audioGroupConfigs">音频轨道组配置。</param>
/// <param name="instanceRoot">实例化根节点。</param>
/// <param name="audioMixer">音频混响器。</param>
/// <exception cref="GameFrameworkException"></exception>
public void Initialize(AudioGroupConfig[] audioGroupConfigs, Transform instanceRoot = null, AudioMixer audioMixer = null);
/// <summary>
/// 重启音频模块。
/// </summary>
public void Restart();
/// <summary>
/// 播放音频接口。
/// </summary>
/// <remarks>如果超过最大发声数采用fadeout的方式复用最久播放的AudioSource。</remarks>
/// <param name="type">声音类型。</param>
/// <param name="path">声音文件路径。</param>
/// <param name="bLoop">是否循环播放。</param>>
/// <param name="volume">音量0-1.0)。</param>
/// <param name="bAsync">是否异步加载。</param>
/// <param name="bInPool">是否支持资源池。</param>
public AudioAgent Play(AudioType type, string path, bool bLoop = false, float volume = 1.0f, bool bAsync = false, bool bInPool = false);
public AudioAgent Play(AudioType type,AudioClip clip,bool loop=false,float volume = 1.0f);
/// <summary>
/// 停止某类声音播放。
/// </summary>
/// <param name="type">声音类型。</param>
/// <param name="fadeout">是否渐消。</param>
public void Stop(AudioType type, bool fadeout);
/// <summary>
/// 停止所有声音。
/// </summary>
/// <param name="fadeout">是否渐消。</param>
public void StopAll(bool fadeout);
/// <summary>
/// 预先加载AudioClip并放入对象池。
/// </summary>
/// <param name="list">AudioClip的AssetPath集合。</param>
public void PutInAudioPool(List<string> list);
/// <summary>
/// 将部分AudioClip从对象池移出。
/// </summary>
/// <param name="list">AudioClip的AssetPath集合。</param>
public void RemoveClipFromPool(List<string> list);
/// <summary>
/// 清空AudioClip的对象池。
/// </summary>
public void CleanSoundPool();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f2a332020228453d8546d5d74aa60f9c
timeCreated: 1694847151

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 64a654fc0d761c24e9676a185ea4df8e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,708 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!244 &-8255999005317483048
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 5256fbc85eb3f884eb780f730c8da825
m_EffectName: Attenuation
m_MixLevel: 989fcb1cc28d4de4ea6e56c14101e674
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &-8165904320333843496
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 6b8ac75d99b7e57489701e084ea19b1f
m_EffectName: Attenuation
m_MixLevel: b19e64315aff6dc4a81ae36b22fc0492
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &-7861682458482441818
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: dcc48474d251d554e9f6f95668853a39
m_EffectName: Receive
m_MixLevel: e6248274fab455749bc046d72eace6de
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &-7758028812591520460
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Sound - 2
m_AudioMixer: {fileID: 24100000}
m_GroupID: 039cd795affa7134a8d5f5d43d3b659d
m_Children: []
m_Volume: 2a8ce0f3383c3f0468a04fa3fc5e317d
m_Pitch: b47f0c73299cd9b4fba9896e70683903
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -3825599753161013374}
m_UserColorIndex: 2
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &-6280614258348125054
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Sound - 1
m_AudioMixer: {fileID: 24100000}
m_GroupID: c0d40106c2ffb1a44bd48f50b210ee20
m_Children: []
m_Volume: f62a8b3fe89df00409532af739ee4e02
m_Pitch: 77212647508232a458ac7d48fb55d037
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -1890011256548497850}
m_UserColorIndex: 2
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &-4958177229083455073
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 104113b95764fe344a5d25469377c800
m_EffectName: Attenuation
m_MixLevel: 9ef29befaad178d4386e9d5ac022f964
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &-4372808504093502661
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Sound - 3
m_AudioMixer: {fileID: 24100000}
m_GroupID: 5f20d1b8f9ac1914dac8beae718e7d40
m_Children: []
m_Volume: e54edf7c1bf7ee44297e65adce5b10b7
m_Pitch: 8542b6bfd7b7bfc4d9b961ba97edf0d2
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 6637688299338053042}
m_UserColorIndex: 2
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &-4209890294574411305
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Music
m_AudioMixer: {fileID: 24100000}
m_GroupID: efe8591c00084024187b9df78858c0af
m_Children:
- {fileID: 1543978434442340687}
m_Volume: 6d4c2b8bc0ef38d44b2fbff2b3298ab4
m_Pitch: 862389c428a73854ab442dd043008729
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 246003612463095956}
m_UserColorIndex: 1
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &-3825599753161013374
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: d1bbcc7cbe0a53c459c9064925118e41
m_EffectName: Attenuation
m_MixLevel: e43bb5de098a2ec49807913fa5fdd2f7
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &-3720557753501792270
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UISound - 1
m_AudioMixer: {fileID: 24100000}
m_GroupID: e012b6d2e0501df43a88eb6beff8ae07
m_Children: []
m_Volume: 265eaf7c8910ab842a845c7bb5e570c4
m_Pitch: bf3ca9b57c9a67b40944a59839b12f62
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 5734415080786067514}
m_UserColorIndex: 3
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &-3395020342500439107
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Voice
m_AudioMixer: {fileID: 24100000}
m_GroupID: 5117f9b5a365ec049a9d5891c563b893
m_Children:
- {fileID: -1649243360580130678}
m_Volume: fe15a1b40c14ea646a13dacb15b6a73b
m_Pitch: 3398197a464677a4186e0cecd66bb13c
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -8165904320333843496}
m_UserColorIndex: 6
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &-2659745067392564156
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Sound - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: 71c50c6b966d1f548a63193919ebfbad
m_Children: []
m_Volume: 7835f2c4248cb3e43a1a773bab1f8b9d
m_Pitch: 30975daa872456b41bc18e0277e301e6
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -284252157345190109}
m_UserColorIndex: 2
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &-1890011256548497850
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 520975c71ea21c249b3cdf1f22032e57
m_EffectName: Attenuation
m_MixLevel: 932e3e893621c5b46bff3c368017e689
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &-1649243360580130678
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Voice - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: f46651e8ad3c6034b8764fd635dda3fd
m_Children: []
m_Volume: 0bc64c1c6cebbeb40ba2f724fdcaa257
m_Pitch: fff252bdd985513469f8607e016fc594
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -890847686165078200}
m_UserColorIndex: 6
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &-998299258853400712
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: d7d19927abbe5584080506164cb4e644
m_EffectName: Attenuation
m_MixLevel: 0b4264524e3eafc49b2daba7fba2ce97
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &-890847686165078200
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 4b41d8aa7a7944041a8b9428add83eff
m_EffectName: Attenuation
m_MixLevel: 73b7a9825978be245a1962a1001b0212
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &-284252157345190109
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 15668b74147caee41a72f695c3a2de56
m_EffectName: Attenuation
m_MixLevel: f71e84fb9a62ff24cad690a0a86cc47e
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &-21257493329335984
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: c9a6f7a9214534644bf2e6d83ff86569
m_EffectName: Distortion
m_MixLevel: 3f356cddae5dba949a6e8f4d20564d3e
m_Parameters:
- m_ParameterName: Level
m_GUID: 080be1914d960974481df4bebe2a2d77
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!241 &24100000
AudioMixerController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: AudioMixer
m_OutputGroup: {fileID: 0}
m_MasterGroup: {fileID: 24300002}
m_Snapshots:
- {fileID: 24500006}
m_StartSnapshot: {fileID: 24500006}
m_SuspendThreshold: -80
m_EnableSuspend: 1
m_UpdateMode: 0
m_ExposedParameters:
- guid: 7835f2c4248cb3e43a1a773bab1f8b9d
name: SoundVolume0
- guid: 41591fd4a32f4034f880ecbc14ee69f1
name: MusicVolume0
- guid: 6e0d1a5935a802d41b27d9e2fad3ba2f
name: UISoundVolume0
- guid: 0bc64c1c6cebbeb40ba2f724fdcaa257
name: VoiceVolume0
- guid: f62a8b3fe89df00409532af739ee4e02
name: SoundVolume1
- guid: 265eaf7c8910ab842a845c7bb5e570c4
name: UISoundVolume1
- guid: 2a8ce0f3383c3f0468a04fa3fc5e317d
name: SoundVolume2
- guid: e83be6d6c4ae85142a51f584159c4ff6
name: UISoundVolume2
- guid: e54edf7c1bf7ee44297e65adce5b10b7
name: SoundVolume3
- guid: 2dd26f9dadf160f4bbd77f307c3f4f2e
name: UISoundVolume3
- guid: ba83e724007d7e9459f157db3a54a741
name: MasterVolume
- guid: 6d4c2b8bc0ef38d44b2fbff2b3298ab4
name: MusicVolume
- guid: 3bbd22597ed32714eb271cf06b098c63
name: SoundVolume
- guid: 7d1c7ed015f5dba4f934c33ef330c5eb
name: UISoundVolume
- guid: fe15a1b40c14ea646a13dacb15b6a73b
name: VoiceVolume
m_AudioMixerGroupViews:
- guids:
- 72c1e77b100e3274fbfb88ca2ca12c4d
- efe8591c00084024187b9df78858c0af
- 648e49a020cf83346a9220d606e4ff39
- 5117f9b5a365ec049a9d5891c563b893
- f46651e8ad3c6034b8764fd635dda3fd
- 1cf576bd46399874d9494863d6502d94
- 71c50c6b966d1f548a63193919ebfbad
- df986418fa3e4ae448a1909ffbb633fb
- 29257697b1e6be546aa0558e342a15a6
- c0d40106c2ffb1a44bd48f50b210ee20
- 039cd795affa7134a8d5f5d43d3b659d
- 5f20d1b8f9ac1914dac8beae718e7d40
- e012b6d2e0501df43a88eb6beff8ae07
- e84c25a476798ea43a2f6de217af7dba
- 98657376d4096a947953ee04d82830c1
name: View
m_CurrentViewIndex: 0
m_TargetSnapshot: {fileID: 24500006}
--- !u!243 &24300002
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Master
m_AudioMixer: {fileID: 24100000}
m_GroupID: 72c1e77b100e3274fbfb88ca2ca12c4d
m_Children:
- {fileID: -4209890294574411305}
- {fileID: 7235523536312936115}
- {fileID: 7185772616558441635}
- {fileID: -3395020342500439107}
m_Volume: ba83e724007d7e9459f157db3a54a741
m_Pitch: a2d2b77391464bb4887f0bcd3835015b
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 24400004}
m_UserColorIndex: 8
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &24400004
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: ce944d90cb57ee4418426132d391d900
m_EffectName: Attenuation
m_MixLevel: 891c3ec10e0ae1b42a95c83727d411f1
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!245 &24500006
AudioMixerSnapshotController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Snapshot
m_AudioMixer: {fileID: 24100000}
m_SnapshotID: 91dee90f8902c804c9da7728ea355157
m_FloatValues:
b47f0c73299cd9b4fba9896e70683903: 1
ba83e724007d7e9459f157db3a54a741: 0
fe15a1b40c14ea646a13dacb15b6a73b: 0
77212647508232a458ac7d48fb55d037: 1
3bbd22597ed32714eb271cf06b098c63: 0
30975daa872456b41bc18e0277e301e6: 1
6d4c2b8bc0ef38d44b2fbff2b3298ab4: -0.03
8542b6bfd7b7bfc4d9b961ba97edf0d2: 1
m_TransitionOverrides: {}
--- !u!244 &246003612463095956
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 860c45ba06e3cbd4794061eaefe970a3
m_EffectName: Attenuation
m_MixLevel: bb4c221c9e3208941b1a2107831692ab
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &281287199725387719
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 812fbfe4555eb1641aeaeee69a13b4a6
m_EffectName: Lowpass Simple
m_MixLevel: 391139084347578409e42387008bd110
m_Parameters:
- m_ParameterName: Cutoff freq
m_GUID: b19756871f24b194d87c7d1fce3159e9
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &1413273517213151576
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: ce0c93d89826c7349a19b232116484db
m_EffectName: Attenuation
m_MixLevel: 7625365898787684c9bce9298a96f044
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &1543978434442340687
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Music - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: 1cf576bd46399874d9494863d6502d94
m_Children: []
m_Volume: 41591fd4a32f4034f880ecbc14ee69f1
m_Pitch: 9ad7e859a0cd1f142b59ffc659be28a7
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -8255999005317483048}
m_UserColorIndex: 1
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &1601410790413250045
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UISound - 3
m_AudioMixer: {fileID: 24100000}
m_GroupID: 98657376d4096a947953ee04d82830c1
m_Children: []
m_Volume: 2dd26f9dadf160f4bbd77f307c3f4f2e
m_Pitch: 5627fa8b0176a344bbb4e59ac5e648d3
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 1413273517213151576}
m_UserColorIndex: 3
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &2567082640316932351
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: a7394d86e1e2a1e4389182f0aec98773
m_EffectName: Attenuation
m_MixLevel: cb8b6dfd682072d4fb81143ba077bc3f
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &3865010338301366421
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UISound - 2
m_AudioMixer: {fileID: 24100000}
m_GroupID: e84c25a476798ea43a2f6de217af7dba
m_Children: []
m_Volume: e83be6d6c4ae85142a51f584159c4ff6
m_Pitch: c45439925e1cfd547894fd886160a11c
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 7834155774142160187}
m_UserColorIndex: 3
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &5734415080786067514
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 20eac414948135e49b2b54a89235f15e
m_EffectName: Attenuation
m_MixLevel: d087be8c429707c4db724a61186f67f6
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &5954042604037024145
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: ba434c984ec3c4442bfe3a399c11572b
m_EffectName: Echo
m_MixLevel: 0323002ce01f29a4abebc242337ea816
m_Parameters:
- m_ParameterName: Delay
m_GUID: f4cc548867353f843bc36a61722c6cbf
- m_ParameterName: Decay
m_GUID: e67c7b4426842f948a83f3dada794a99
- m_ParameterName: Max channels
m_GUID: 75c7951a8373f4644a44979a8c5776ed
- m_ParameterName: Drymix
m_GUID: 4d26b3b7a84b31d499176a7879734ba1
- m_ParameterName: Wetmix
m_GUID: 6efaeec45de20b045a4d560994684cba
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &6255340296135181231
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 3a251f2e65751b349bb255f73f0caeaf
m_EffectName: Duck Volume
m_MixLevel: 58cfdd03ab24c874cbe074238d636208
m_Parameters:
- m_ParameterName: Threshold
m_GUID: b1b5c57689fc533408e6195c0a9e26a9
- m_ParameterName: Ratio
m_GUID: dc9c2c635bce58746bd68c7dffb99ca0
- m_ParameterName: Attack Time
m_GUID: 078ff252301e4594c880cd5754b8a563
- m_ParameterName: Release Time
m_GUID: b3918efd0a966ea4882714c0f9edd40b
- m_ParameterName: Make-up Gain
m_GUID: 3cf881ca64b7cdb46b35d3593ff2cbe9
- m_ParameterName: Knee
m_GUID: 31ea47a78d927ab4abf12f854bd4c626
- m_ParameterName: Sidechain Mix
m_GUID: 468d86503d3572541a33c33bb9693dfd
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &6554641470784401750
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 4499c94d696ee5741a71370ed7431e12
m_EffectName: Send
m_MixLevel: f01b57f2509f26f4b8f2772993c2b8c6
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!244 &6637688299338053042
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: e84926aaeedf4074698e7d7f7f36b78b
m_EffectName: Attenuation
m_MixLevel: 8141a348079ee934686d3569f4758582
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0
--- !u!243 &7040861873718444651
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UISound - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: 29257697b1e6be546aa0558e342a15a6
m_Children: []
m_Volume: 6e0d1a5935a802d41b27d9e2fad3ba2f
m_Pitch: 7d01f3677fe8c5b41a877b64cc509766
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -4958177229083455073}
m_UserColorIndex: 3
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &7185772616558441635
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: UISound
m_AudioMixer: {fileID: 24100000}
m_GroupID: df986418fa3e4ae448a1909ffbb633fb
m_Children:
- {fileID: 7040861873718444651}
- {fileID: -3720557753501792270}
- {fileID: 3865010338301366421}
- {fileID: 1601410790413250045}
m_Volume: 7d1c7ed015f5dba4f934c33ef330c5eb
m_Pitch: 611d9d89c8a65b548b591e852596c35d
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: -998299258853400712}
m_UserColorIndex: 3
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!243 &7235523536312936115
AudioMixerGroupController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Sound
m_AudioMixer: {fileID: 24100000}
m_GroupID: 648e49a020cf83346a9220d606e4ff39
m_Children:
- {fileID: -2659745067392564156}
- {fileID: -6280614258348125054}
- {fileID: -7758028812591520460}
- {fileID: -4372808504093502661}
m_Volume: 3bbd22597ed32714eb271cf06b098c63
m_Pitch: 7f8a6510dd472ff4db8b07c5079a2013
m_Send: 00000000000000000000000000000000
m_Effects:
- {fileID: 2567082640316932351}
m_UserColorIndex: 2
m_Mute: 0
m_Solo: 0
m_BypassEffects: 0
--- !u!244 &7834155774142160187
AudioMixerEffectController:
m_ObjectHideFlags: 3
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_EffectID: 09e809d6183106b4a804ff08ca8ff9ed
m_EffectName: Attenuation
m_MixLevel: 92339d91519b09543844a84cea03aed3
m_Parameters: []
m_SendTarget: {fileID: 0}
m_EnableWetMix: 0
m_Bypass: 0

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1af7a1b121ae17541a1967d430cef006
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/Debugger.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c630b51c86a234242a84ff37c9342a82
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,28 @@
namespace AlicizaX.Debugger.Runtime
{
/// <summary>
/// 调试器激活窗口类型。
/// </summary>
public enum DebuggerActiveWindowType : byte
{
/// <summary>
/// 总是打开。
/// </summary>
AlwaysOpen = 0,
/// <summary>
/// 仅在开发模式时打开。
/// </summary>
OnlyOpenWhenDevelopment,
/// <summary>
/// 仅在编辑器中打开。
/// </summary>
OnlyOpenInEditor,
/// <summary>
/// 总是关闭。
/// </summary>
AlwaysClose,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d1baccfe5abb590428eb0322088bf4ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,420 @@

using System;
using System.Collections.Generic;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
[Serializable]
private sealed class ConsoleWindow : IDebuggerWindow
{
private readonly Queue<LogNode> m_LogNodes = new Queue<LogNode>();
private Vector2 m_LogScrollPosition = Vector2.zero;
private Vector2 m_StackScrollPosition = Vector2.zero;
private int m_InfoCount = 0;
private int m_WarningCount = 0;
private int m_ErrorCount = 0;
private int m_FatalCount = 0;
private LogNode m_SelectedNode = null;
private bool m_LastLockScroll = true;
private bool m_LastInfoFilter = true;
private bool m_LastWarningFilter = true;
private bool m_LastErrorFilter = true;
private bool m_LastFatalFilter = true;
[SerializeField] private bool m_LockScroll = true;
[SerializeField] private int m_MaxLine = 100;
[SerializeField] private bool m_InfoFilter = true;
[SerializeField] private bool m_WarningFilter = true;
[SerializeField] private bool m_ErrorFilter = true;
[SerializeField] private bool m_FatalFilter = true;
[SerializeField] private Color32 m_InfoColor = Color.white;
[SerializeField] private Color32 m_WarningColor = Color.yellow;
[SerializeField] private Color32 m_ErrorColor = Color.red;
[SerializeField] private Color32 m_FatalColor = new Color(0.7f, 0.2f, 0.2f);
public bool LockScroll
{
get { return m_LockScroll; }
set { m_LockScroll = value; }
}
public int MaxLine
{
get { return m_MaxLine; }
set { m_MaxLine = value; }
}
public bool InfoFilter
{
get { return m_InfoFilter; }
set { m_InfoFilter = value; }
}
public bool WarningFilter
{
get { return m_WarningFilter; }
set { m_WarningFilter = value; }
}
public bool ErrorFilter
{
get { return m_ErrorFilter; }
set { m_ErrorFilter = value; }
}
public bool FatalFilter
{
get { return m_FatalFilter; }
set { m_FatalFilter = value; }
}
public int InfoCount
{
get { return m_InfoCount; }
}
public int WarningCount
{
get { return m_WarningCount; }
}
public int ErrorCount
{
get { return m_ErrorCount; }
}
public int FatalCount
{
get { return m_FatalCount; }
}
public Color32 InfoColor
{
get { return m_InfoColor; }
set { m_InfoColor = value; }
}
public Color32 WarningColor
{
get { return m_WarningColor; }
set { m_WarningColor = value; }
}
public Color32 ErrorColor
{
get { return m_ErrorColor; }
set { m_ErrorColor = value; }
}
public Color32 FatalColor
{
get { return m_FatalColor; }
set { m_FatalColor = value; }
}
public void Initialize(params object[] args)
{
Application.logMessageReceived += OnLogMessageReceived;
m_LockScroll = m_LastLockScroll = Utility.PlayerPrefsX.GetBool("Debugger.Console.LockScroll", true);
m_InfoFilter = m_LastInfoFilter = Utility.PlayerPrefsX.GetBool("Debugger.Console.InfoFilter", true);
m_WarningFilter = m_LastWarningFilter = Utility.PlayerPrefsX.GetBool("Debugger.Console.WarningFilter", true);
m_ErrorFilter = m_LastErrorFilter = Utility.PlayerPrefsX.GetBool("Debugger.Console.ErrorFilter", true);
m_FatalFilter = m_LastFatalFilter = Utility.PlayerPrefsX.GetBool("Debugger.Console.FatalFilter", true);
}
public void Shutdown()
{
Application.logMessageReceived -= OnLogMessageReceived;
Clear();
}
public void OnEnter()
{
}
public void OnLeave()
{
}
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
if (m_LastLockScroll != m_LockScroll)
{
m_LastLockScroll = m_LockScroll;
Utility.PlayerPrefsX.SetBool("Debugger.Console.LockScroll", m_LockScroll);
}
if (m_LastInfoFilter != m_InfoFilter)
{
m_LastInfoFilter = m_InfoFilter;
Utility.PlayerPrefsX.SetBool("Debugger.Console.InfoFilter", m_InfoFilter);
}
if (m_LastWarningFilter != m_WarningFilter)
{
m_LastWarningFilter = m_WarningFilter;
Utility.PlayerPrefsX.SetBool("Debugger.Console.WarningFilter", m_WarningFilter);
}
if (m_LastErrorFilter != m_ErrorFilter)
{
m_LastErrorFilter = m_ErrorFilter;
Utility.PlayerPrefsX.SetBool("Debugger.Console.ErrorFilter", m_ErrorFilter);
}
if (m_LastFatalFilter != m_FatalFilter)
{
m_LastFatalFilter = m_FatalFilter;
Utility.PlayerPrefsX.SetBool("Debugger.Console.FatalFilter", m_FatalFilter);
}
}
public void OnDraw()
{
RefreshCount();
GUILayout.BeginHorizontal();
{
if (GUILayout.Button("Clear All", GUILayout.Width(100f)))
{
Clear();
}
m_LockScroll = GUILayout.Toggle(m_LockScroll, "Lock Scroll", GUILayout.Width(90f));
GUILayout.FlexibleSpace();
m_InfoFilter = GUILayout.Toggle(m_InfoFilter, Utility.Text.Format("Info ({0})", m_InfoCount), GUILayout.Width(90f));
m_WarningFilter = GUILayout.Toggle(m_WarningFilter, Utility.Text.Format("Warning ({0})", m_WarningCount), GUILayout.Width(90f));
m_ErrorFilter = GUILayout.Toggle(m_ErrorFilter, Utility.Text.Format("Error ({0})", m_ErrorCount), GUILayout.Width(90f));
m_FatalFilter = GUILayout.Toggle(m_FatalFilter, Utility.Text.Format("Fatal ({0})", m_FatalCount), GUILayout.Width(90f));
}
GUILayout.EndHorizontal();
GUILayout.BeginVertical("box");
{
if (m_LockScroll)
{
m_LogScrollPosition.y = float.MaxValue;
}
m_LogScrollPosition = GUILayout.BeginScrollView(m_LogScrollPosition);
{
bool selected = false;
foreach (LogNode logNode in m_LogNodes)
{
switch (logNode.LogType)
{
case LogType.Log:
if (!m_InfoFilter)
{
continue;
}
break;
case LogType.Warning:
if (!m_WarningFilter)
{
continue;
}
break;
case LogType.Error:
if (!m_ErrorFilter)
{
continue;
}
break;
case LogType.Exception:
if (!m_FatalFilter)
{
continue;
}
break;
}
if (GUILayout.Toggle(m_SelectedNode == logNode, GetLogString(logNode)))
{
selected = true;
if (m_SelectedNode != logNode)
{
m_SelectedNode = logNode;
m_StackScrollPosition = Vector2.zero;
}
}
}
if (!selected)
{
m_SelectedNode = null;
}
}
GUILayout.EndScrollView();
}
GUILayout.EndVertical();
GUILayout.BeginVertical("box");
{
m_StackScrollPosition = GUILayout.BeginScrollView(m_StackScrollPosition, GUILayout.Height(100f));
{
if (m_SelectedNode != null)
{
Color32 color = GetLogStringColor(m_SelectedNode.LogType);
if (GUILayout.Button(Utility.Text.Format("<color=#{0:x2}{1:x2}{2:x2}{3:x2}><b>{4}</b></color>{6}{6}{5}", color.r, color.g, color.b, color.a, m_SelectedNode.LogMessage, m_SelectedNode.StackTrack, Environment.NewLine), "label"))
{
CopyToClipboard(Utility.Text.Format("{0}{2}{2}{1}", m_SelectedNode.LogMessage, m_SelectedNode.StackTrack, Environment.NewLine));
}
}
}
GUILayout.EndScrollView();
}
GUILayout.EndVertical();
}
private void Clear()
{
m_LogNodes.Clear();
}
public void RefreshCount()
{
m_InfoCount = 0;
m_WarningCount = 0;
m_ErrorCount = 0;
m_FatalCount = 0;
foreach (LogNode logNode in m_LogNodes)
{
switch (logNode.LogType)
{
case LogType.Log:
m_InfoCount++;
break;
case LogType.Warning:
m_WarningCount++;
break;
case LogType.Error:
m_ErrorCount++;
break;
case LogType.Exception:
m_FatalCount++;
break;
}
}
}
public void GetRecentLogs(List<LogNode> results)
{
if (results == null)
{
Log.Error("Results is invalid.");
return;
}
results.Clear();
foreach (LogNode logNode in m_LogNodes)
{
results.Add(logNode);
}
}
public void GetRecentLogs(List<LogNode> results, int count)
{
if (results == null)
{
Log.Error("Results is invalid.");
return;
}
if (count <= 0)
{
Log.Error("Count is invalid.");
return;
}
int position = m_LogNodes.Count - count;
if (position < 0)
{
position = 0;
}
int index = 0;
results.Clear();
foreach (LogNode logNode in m_LogNodes)
{
if (index++ < position)
{
continue;
}
results.Add(logNode);
}
}
private void OnLogMessageReceived(string logMessage, string stackTrace, LogType logType)
{
if (logType == LogType.Assert)
{
logType = LogType.Error;
}
m_LogNodes.Enqueue(LogNode.Create(logType, logMessage, stackTrace));
while (m_LogNodes.Count > m_MaxLine)
{
MemoryPool.Release(m_LogNodes.Dequeue());
}
}
private string GetLogString(LogNode logNode)
{
Color32 color = GetLogStringColor(logNode.LogType);
return Utility.Text.Format("<color=#{0:x2}{1:x2}{2:x2}{3:x2}>[{4:HH:mm:ss.fff}][{5}] {6}</color>", color.r, color.g, color.b, color.a, logNode.LogTime.ToLocalTime(), logNode.LogFrameCount, logNode.LogMessage);
}
internal Color32 GetLogStringColor(LogType logType)
{
Color32 color = Color.white;
switch (logType)
{
case LogType.Log:
color = m_InfoColor;
break;
case LogType.Warning:
color = m_WarningColor;
break;
case LogType.Error:
color = m_ErrorColor;
break;
case LogType.Exception:
color = m_FatalColor;
break;
}
return color;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4a47e2730f999784eb1bbeefab72ef11
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,74 @@
using AlicizaX;
using UnityEngine;
#if UNITY_5_5_OR_NEWER
using UnityEngine.Rendering;
#endif
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class EnvironmentInformationWindow : ScrollableDebuggerWindowBase
{
public override void Initialize(params object[] args)
{
}
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Environment Information</b>");
GUILayout.BeginVertical("box");
{
DrawItem("Product Name", Application.productName);
DrawItem("Company Name", Application.companyName);
#if UNITY_5_6_OR_NEWER
DrawItem("Game Identifier", Application.identifier);
#else
DrawItem("Game Identifier", Application.bundleIdentifier);
#endif
DrawItem("Game Framework Version", AppVersion.GameFrameworkVersion);
DrawItem("Game Version", Utility.Text.Format("{0} ({1})", AppVersion.GameVersion, AppVersion.GameFrameworkVersion));
// DrawItem("Resource Version", m_BaseComponent.EditorResourceMode ? "Unavailable in editor resource mode" : (string.IsNullOrEmpty(m_ResourceComponent.ApplicableGameVersion) ? "Unknown" : Utility.Text.Format("{0} ({1})", m_ResourceComponent.ApplicableGameVersion, m_ResourceComponent.InternalResourceVersion)));
DrawItem("Application Version", Application.version);
DrawItem("Unity Version", Application.unityVersion);
DrawItem("Platform", Application.platform.ToString());
DrawItem("System Language", Application.systemLanguage.ToString());
DrawItem("Cloud Project Id", Application.cloudProjectId);
#if UNITY_5_6_OR_NEWER
DrawItem("Build Guid", Application.buildGUID);
#endif
DrawItem("Target Frame Rate", Application.targetFrameRate.ToString());
DrawItem("Internet Reachability", Application.internetReachability.ToString());
DrawItem("Background Loading Priority", Application.backgroundLoadingPriority.ToString());
DrawItem("Is Playing", Application.isPlaying.ToString());
#if UNITY_5_5_OR_NEWER
DrawItem("Splash Screen Is Finished", SplashScreen.isFinished.ToString());
#else
DrawItem("Is Showing Splash Screen", Application.isShowingSplashScreen.ToString());
#endif
DrawItem("Run In Background", Application.runInBackground.ToString());
#if UNITY_5_5_OR_NEWER
DrawItem("Install Name", Application.installerName);
#endif
DrawItem("Install Mode", Application.installMode.ToString());
DrawItem("Sandbox Type", Application.sandboxType.ToString());
DrawItem("Is Mobile Platform", Application.isMobilePlatform.ToString());
DrawItem("Is Console Platform", Application.isConsolePlatform.ToString());
DrawItem("Is Editor", Application.isEditor.ToString());
DrawItem("Is Debug Build", Debug.isDebugBuild.ToString());
#if UNITY_5_6_OR_NEWER
DrawItem("Is Focused", Application.isFocused.ToString());
#endif
#if UNITY_2018_2_OR_NEWER
DrawItem("Is Batch Mode", Application.isBatchMode.ToString());
#endif
#if UNITY_5_3
DrawItem("Stack Trace Log Type", Application.stackTraceLogType.ToString());
#endif
}
GUILayout.EndVertical();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c52c8dc8849c5fb429c50b45975a599b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,77 @@

namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class FpsCounter
{
private float m_UpdateInterval;
private float m_CurrentFps;
private int m_Frames;
private float m_Accumulator;
private float m_TimeLeft;
public FpsCounter(float updateInterval)
{
if (updateInterval <= 0f)
{
Log.Error("Update interval is invalid.");
return;
}
m_UpdateInterval = updateInterval;
Reset();
}
public float UpdateInterval
{
get
{
return m_UpdateInterval;
}
set
{
if (value <= 0f)
{
Log.Error("Update interval is invalid.");
return;
}
m_UpdateInterval = value;
Reset();
}
}
public float CurrentFps
{
get
{
return m_CurrentFps;
}
}
public void Update(float elapseSeconds, float realElapseSeconds)
{
m_Frames++;
m_Accumulator += realElapseSeconds;
m_TimeLeft -= realElapseSeconds;
if (m_TimeLeft <= 0f)
{
m_CurrentFps = m_Accumulator > 0f ? m_Frames / m_Accumulator : 0f;
m_Frames = 0;
m_Accumulator = 0f;
m_TimeLeft += m_UpdateInterval;
}
}
private void Reset()
{
m_CurrentFps = 0f;
m_Frames = 0;
m_Accumulator = 0f;
m_TimeLeft = 0f;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f24c805ead515d4286d3c03cd50f750
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,163 @@
using AlicizaX;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class GraphicsInformationWindow : ScrollableDebuggerWindowBase
{
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Graphics Information</b>");
GUILayout.BeginVertical("box");
{
DrawItem("Device ID", SystemInfo.graphicsDeviceID.ToString());
DrawItem("Device Name", SystemInfo.graphicsDeviceName);
DrawItem("Device Vendor ID", SystemInfo.graphicsDeviceVendorID.ToString());
DrawItem("Device Vendor", SystemInfo.graphicsDeviceVendor);
DrawItem("Device Type", SystemInfo.graphicsDeviceType.ToString());
DrawItem("Device Version", SystemInfo.graphicsDeviceVersion);
DrawItem("Memory Size", Utility.Text.Format("{0} MB", SystemInfo.graphicsMemorySize));
DrawItem("Multi Threaded", SystemInfo.graphicsMultiThreaded.ToString());
#if UNITY_2019_3_OR_NEWER
DrawItem("Rendering Threading Mode", SystemInfo.renderingThreadingMode.ToString());
#endif
#if UNITY_2020_1_OR_NEWER
DrawItem("HRD Display Support Flags", SystemInfo.hdrDisplaySupportFlags.ToString());
#endif
DrawItem("Shader Level", GetShaderLevelString(SystemInfo.graphicsShaderLevel));
DrawItem("Global Maximum LOD", Shader.globalMaximumLOD.ToString());
#if UNITY_5_6_OR_NEWER
DrawItem("Global Render Pipeline", Shader.globalRenderPipeline);
#endif
#if UNITY_2020_2_OR_NEWER
DrawItem("Min OpenGLES Version", Graphics.minOpenGLESVersion.ToString());
#endif
#if UNITY_5_5_OR_NEWER
DrawItem("Active Tier", Graphics.activeTier.ToString());
#endif
#if UNITY_2017_2_OR_NEWER
DrawItem("Active Color Gamut", Graphics.activeColorGamut.ToString());
#endif
#if UNITY_2019_2_OR_NEWER
DrawItem("Preserve Frame Buffer Alpha", Graphics.preserveFramebufferAlpha.ToString());
#endif
DrawItem("NPOT Support", SystemInfo.npotSupport.ToString());
DrawItem("Max Texture Size", SystemInfo.maxTextureSize.ToString());
DrawItem("Supported Render Target Count", SystemInfo.supportedRenderTargetCount.ToString());
#if UNITY_2019_3_OR_NEWER
DrawItem("Supported Random Write Target Count", SystemInfo.supportedRandomWriteTargetCount.ToString());
#endif
#if UNITY_5_4_OR_NEWER
DrawItem("Copy Texture Support", SystemInfo.copyTextureSupport.ToString());
#endif
#if UNITY_5_5_OR_NEWER
DrawItem("Uses Reversed ZBuffer", SystemInfo.usesReversedZBuffer.ToString());
#endif
#if UNITY_5_6_OR_NEWER
DrawItem("Max Cubemap Size", SystemInfo.maxCubemapSize.ToString());
DrawItem("Graphics UV Starts At Top", SystemInfo.graphicsUVStartsAtTop.ToString());
#endif
#if UNITY_2020_2_OR_NEWER
DrawItem("Constant Buffer Offset Alignment", SystemInfo.constantBufferOffsetAlignment.ToString());
#elif UNITY_2019_1_OR_NEWER
DrawItem("Min Constant Buffer Offset Alignment", SystemInfo.minConstantBufferOffsetAlignment.ToString());
#endif
#if UNITY_2018_3_OR_NEWER
DrawItem("Has Hidden Surface Removal On GPU", SystemInfo.hasHiddenSurfaceRemovalOnGPU.ToString());
DrawItem("Has Dynamic Uniform Array Indexing In Fragment Shaders", SystemInfo.hasDynamicUniformArrayIndexingInFragmentShaders.ToString());
#endif
#if UNITY_2019_2_OR_NEWER
DrawItem("Has Mip Max Level", SystemInfo.hasMipMaxLevel.ToString());
#endif
#if UNITY_2019_3_OR_NEWER
DrawItem("Uses Load Store Actions", SystemInfo.usesLoadStoreActions.ToString());
DrawItem("Max Compute Buffer Inputs Compute", SystemInfo.maxComputeBufferInputsCompute.ToString());
DrawItem("Max Compute Buffer Inputs Domain", SystemInfo.maxComputeBufferInputsDomain.ToString());
DrawItem("Max Compute Buffer Inputs Fragment", SystemInfo.maxComputeBufferInputsFragment.ToString());
DrawItem("Max Compute Buffer Inputs Geometry", SystemInfo.maxComputeBufferInputsGeometry.ToString());
DrawItem("Max Compute Buffer Inputs Hull", SystemInfo.maxComputeBufferInputsHull.ToString());
DrawItem("Max Compute Buffer Inputs Vertex", SystemInfo.maxComputeBufferInputsVertex.ToString());
DrawItem("Max Compute Work Group Size", SystemInfo.maxComputeWorkGroupSize.ToString());
DrawItem("Max Compute Work Group Size X", SystemInfo.maxComputeWorkGroupSizeX.ToString());
DrawItem("Max Compute Work Group Size Y", SystemInfo.maxComputeWorkGroupSizeY.ToString());
DrawItem("Max Compute Work Group Size Z", SystemInfo.maxComputeWorkGroupSizeZ.ToString());
#endif
#if UNITY_5_3 || UNITY_5_4
DrawItem("Supports Stencil", SystemInfo.supportsStencil.ToString());
DrawItem("Supports Render Textures", SystemInfo.supportsRenderTextures.ToString());
#endif
DrawItem("Supports Sparse Textures", SystemInfo.supportsSparseTextures.ToString());
DrawItem("Supports 3D Textures", SystemInfo.supports3DTextures.ToString());
DrawItem("Supports Shadows", SystemInfo.supportsShadows.ToString());
DrawItem("Supports Raw Shadow Depth Sampling", SystemInfo.supportsRawShadowDepthSampling.ToString());
#if !UNITY_2019_1_OR_NEWER
DrawItem("Supports Render To Cubemap", SystemInfo.supportsRenderToCubemap.ToString());
DrawItem("Supports Image Effects", SystemInfo.supportsImageEffects.ToString());
#endif
DrawItem("Supports Compute Shader", SystemInfo.supportsComputeShaders.ToString());
DrawItem("Supports Instancing", SystemInfo.supportsInstancing.ToString());
#if UNITY_5_4_OR_NEWER
DrawItem("Supports 2D Array Textures", SystemInfo.supports2DArrayTextures.ToString());
DrawItem("Supports Motion Vectors", SystemInfo.supportsMotionVectors.ToString());
#endif
#if UNITY_5_5_OR_NEWER
DrawItem("Supports Cubemap Array Textures", SystemInfo.supportsCubemapArrayTextures.ToString());
#endif
#if UNITY_5_6_OR_NEWER
DrawItem("Supports 3D Render Textures", SystemInfo.supports3DRenderTextures.ToString());
#endif
#if UNITY_2017_2_OR_NEWER && !UNITY_2017_2_0 || UNITY_2017_1_4
DrawItem("Supports Texture Wrap Mirror Once", SystemInfo.supportsTextureWrapMirrorOnce.ToString());
#endif
#if UNITY_2019_1_OR_NEWER
DrawItem("Supports Graphics Fence", SystemInfo.supportsGraphicsFence.ToString());
#elif UNITY_2017_3_OR_NEWER
DrawItem("Supports GPU Fence", SystemInfo.supportsGPUFence.ToString());
#endif
#if UNITY_2017_3_OR_NEWER
DrawItem("Supports Async Compute", SystemInfo.supportsAsyncCompute.ToString());
DrawItem("Supports Multi-sampled Textures", SystemInfo.supportsMultisampledTextures.ToString());
#endif
#if UNITY_2018_1_OR_NEWER
DrawItem("Supports Async GPU Readback", SystemInfo.supportsAsyncGPUReadback.ToString());
DrawItem("Supports 32bits Index Buffer", SystemInfo.supports32bitsIndexBuffer.ToString());
DrawItem("Supports Hardware Quad Topology", SystemInfo.supportsHardwareQuadTopology.ToString());
#endif
#if UNITY_2018_2_OR_NEWER
DrawItem("Supports Mip Streaming", SystemInfo.supportsMipStreaming.ToString());
DrawItem("Supports Multi-sample Auto Resolve", SystemInfo.supportsMultisampleAutoResolve.ToString());
#endif
#if UNITY_2018_3_OR_NEWER
DrawItem("Supports Separated Render Targets Blend", SystemInfo.supportsSeparatedRenderTargetsBlend.ToString());
#endif
#if UNITY_2019_1_OR_NEWER
DrawItem("Supports Set Constant Buffer", SystemInfo.supportsSetConstantBuffer.ToString());
#endif
#if UNITY_2019_3_OR_NEWER
DrawItem("Supports Geometry Shaders", SystemInfo.supportsGeometryShaders.ToString());
DrawItem("Supports Ray Tracing", SystemInfo.supportsRayTracing.ToString());
DrawItem("Supports Tessellation Shaders", SystemInfo.supportsTessellationShaders.ToString());
#endif
#if UNITY_2020_1_OR_NEWER
DrawItem("Supports Compressed 3D Textures", SystemInfo.supportsCompressed3DTextures.ToString());
DrawItem("Supports Conservative Raster", SystemInfo.supportsConservativeRaster.ToString());
DrawItem("Supports GPU Recorder", SystemInfo.supportsGpuRecorder.ToString());
#endif
#if UNITY_2020_2_OR_NEWER
DrawItem("Supports Multi-sampled 2D Array Textures", SystemInfo.supportsMultisampled2DArrayTextures.ToString());
DrawItem("Supports Multiview", SystemInfo.supportsMultiview.ToString());
DrawItem("Supports Render Target Array Index From Vertex Shader", SystemInfo.supportsRenderTargetArrayIndexFromVertexShader.ToString());
#endif
}
GUILayout.EndVertical();
}
private string GetShaderLevelString(int shaderLevel)
{
return Utility.Text.Format("Shader Model {0}.{1}", shaderLevel / 10, shaderLevel % 10);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a1342573add002c41b3bb1a8abb8ef3a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,39 @@
using AlicizaX;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class InputAccelerationInformationWindow : ScrollableDebuggerWindowBase
{
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Input Acceleration Information</b>");
GUILayout.BeginVertical("box");
{
DrawItem("Acceleration", Input.acceleration.ToString());
DrawItem("Acceleration Event Count", Input.accelerationEventCount.ToString());
DrawItem("Acceleration Events", GetAccelerationEventsString(Input.accelerationEvents));
}
GUILayout.EndVertical();
}
private string GetAccelerationEventString(AccelerationEvent accelerationEvent)
{
return Utility.Text.Format("{0}, {1}", accelerationEvent.acceleration, accelerationEvent.deltaTime);
}
private string GetAccelerationEventsString(AccelerationEvent[] accelerationEvents)
{
string[] accelerationEventStrings = new string[accelerationEvents.Length];
for (int i = 0; i < accelerationEvents.Length; i++)
{
accelerationEventStrings[i] = GetAccelerationEventString(accelerationEvents[i]);
}
return string.Join("; ", accelerationEventStrings);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99bd178c0d097a24d9e04fe1522bca60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,42 @@
using AlicizaX;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class InputCompassInformationWindow : ScrollableDebuggerWindowBase
{
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Input Compass Information</b>");
GUILayout.BeginVertical("box");
{
GUILayout.BeginHorizontal();
{
if (GUILayout.Button("Enable", GUILayout.Height(30f)))
{
Input.compass.enabled = true;
}
if (GUILayout.Button("Disable", GUILayout.Height(30f)))
{
Input.compass.enabled = false;
}
}
GUILayout.EndHorizontal();
DrawItem("Enabled", Input.compass.enabled.ToString());
if (Input.compass.enabled)
{
DrawItem("Heading Accuracy", Input.compass.headingAccuracy.ToString());
DrawItem("Magnetic Heading", Input.compass.magneticHeading.ToString());
DrawItem("Raw Vector", Input.compass.rawVector.ToString());
DrawItem("Timestamp", Input.compass.timestamp.ToString());
DrawItem("True Heading", Input.compass.trueHeading.ToString());
}
}
GUILayout.EndVertical();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8e33bb9948f7f54d988d80a6ae6a24a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
using AlicizaX;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class InputGyroscopeInformationWindow : ScrollableDebuggerWindowBase
{
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Input Gyroscope Information</b>");
GUILayout.BeginVertical("box");
{
GUILayout.BeginHorizontal();
{
if (GUILayout.Button("Enable", GUILayout.Height(30f)))
{
Input.gyro.enabled = true;
}
if (GUILayout.Button("Disable", GUILayout.Height(30f)))
{
Input.gyro.enabled = false;
}
}
GUILayout.EndHorizontal();
DrawItem("Enabled", Input.gyro.enabled.ToString());
if (Input.gyro.enabled)
{
DrawItem("Update Interval", Input.gyro.updateInterval.ToString());
DrawItem("Attitude", Input.gyro.attitude.eulerAngles.ToString());
DrawItem("Gravity", Input.gyro.gravity.ToString());
DrawItem("Rotation Rate", Input.gyro.rotationRate.ToString());
DrawItem("Rotation Rate Unbiased", Input.gyro.rotationRateUnbiased.ToString());
DrawItem("User Acceleration", Input.gyro.userAcceleration.ToString());
}
}
GUILayout.EndVertical();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 709450f452a296b44b4aa939cf37f37c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,44 @@
using AlicizaX;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class InputLocationInformationWindow : ScrollableDebuggerWindowBase
{
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Input Location Information</b>");
GUILayout.BeginVertical("box");
{
GUILayout.BeginHorizontal();
{
if (GUILayout.Button("Enable", GUILayout.Height(30f)))
{
Input.location.Start();
}
if (GUILayout.Button("Disable", GUILayout.Height(30f)))
{
Input.location.Stop();
}
}
GUILayout.EndHorizontal();
DrawItem("Is Enabled By User", Input.location.isEnabledByUser.ToString());
DrawItem("Status", Input.location.status.ToString());
if (Input.location.status == LocationServiceStatus.Running)
{
DrawItem("Horizontal Accuracy", Input.location.lastData.horizontalAccuracy.ToString());
DrawItem("Vertical Accuracy", Input.location.lastData.verticalAccuracy.ToString());
DrawItem("Longitude", Input.location.lastData.longitude.ToString());
DrawItem("Latitude", Input.location.lastData.latitude.ToString());
DrawItem("Altitude", Input.location.lastData.altitude.ToString());
DrawItem("Timestamp", Input.location.lastData.timestamp.ToString());
}
}
GUILayout.EndVertical();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74c5698b7ee786442b28b64003f564fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
using AlicizaX;
using UnityEngine;
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
private sealed class InputSummaryInformationWindow : ScrollableDebuggerWindowBase
{
protected override void OnDrawScrollableWindow()
{
GUILayout.Label("<b>Input Summary Information</b>");
GUILayout.BeginVertical("box");
{
DrawItem("Back Button Leaves App", Input.backButtonLeavesApp.ToString());
DrawItem("Device Orientation", Input.deviceOrientation.ToString());
DrawItem("Mouse Present", Input.mousePresent.ToString());
DrawItem("Mouse Position", Input.mousePosition.ToString());
DrawItem("Mouse Scroll Delta", Input.mouseScrollDelta.ToString());
DrawItem("Any Key", Input.anyKey.ToString());
DrawItem("Any Key Down", Input.anyKeyDown.ToString());
DrawItem("Input String", Input.inputString);
DrawItem("IME Is Selected", Input.imeIsSelected.ToString());
DrawItem("IME Composition Mode", Input.imeCompositionMode.ToString());
DrawItem("Compensate Sensors", Input.compensateSensors.ToString());
DrawItem("Composition Cursor Position", Input.compositionCursorPos.ToString());
DrawItem("Composition String", Input.compositionString);
}
GUILayout.EndVertical();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a2756ce9647dc6a49a66c75437edef8b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More