更新使用文档

This commit is contained in:
陈思海 2026-04-01 13:20:06 +08:00
parent ee20687c98
commit 635754f072
85 changed files with 9231 additions and 62 deletions

632
Client/.tmp_api_editor.txt Normal file
View File

@ -0,0 +1,632 @@
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\HybridCLR\BuildDLLCommand.cs
NAMESPACE <global>
L13 public static class BuildDLLCommand
L16 public static string AssemblyTextAssetPath = Application.dataPath + "/" + "Bundles/DLL";
L22 public static void Disable()
L32 public static void Enable()
L41 public static void BuildAndCopyDlls()
L49 public static void GenerateAll()
L54 public static void BuildAndCopyDlls(BuildTarget target)
L60 public static void CopyAOTHotUpdateDlls(BuildTarget target)
L67 public static void CopyAOTAssembliesToAssetPath()
L129 public static void CopyHotUpdateAssembliesToAssetPath()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Postprocessor\Atlas\AtlasConfiguration.cs
NAMESPACE <global>
L7 public class AtlasConfiguration : AlicizaX.Editor.Setting.ScriptableSingleton<AtlasConfiguration>
L15 public TextureImporterFormat iosFormat = TextureImporterFormat.ASTC_5x5;
L16 public TextureImporterFormat webglFormat = TextureImporterFormat.ASTC_6x6;
L19 public bool enableRotation = true;
L20 public int blockOffset = 1;
L21 public bool tightPacking = true;
L24 public bool autoGenerate = true;
L25 public bool enableLogging = true;
L26 public bool enableV2 = true;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Postprocessor\Atlas\AtlasEditorWindow.cs
NAMESPACE <global>
L6 public class AtlasConfigWindow : EditorWindow
L9 public static void ShowWindow()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Postprocessor\Atlas\EditorSpriteSaveInfo.cs
NAMESPACE <global>
L11 public static class EditorSpriteSaveInfo
L34 public static void ConvertToSprite(string assetPath)
L73 public static void OnImportSprite(string assetPath)
L96 public static void OnDeleteSprite(string assetPath)
L114 public static void ForceGenerateAll()
L122 public static void ClearCache()
L129 public static void MarkParentAtlasesDirty(string assetPath)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Postprocessor\Atlas\SpritePostprocessor.cs
NAMESPACE <global>
L5 public class SpritePostprocessor : AssetPostprocessor
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\AssetTreeView.cs
NAMESPACE TEngine.Editor
L13 public AssetViewItem assetRoot;
L15 public AssetTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader) : base(state, multicolumnHeader)
L39 public void SortExpandItem()
L53 public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState(float treeViewWidth, bool isDepend)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\AssetViewItem.cs
NAMESPACE TEngine.Editor
L7 public ReferenceFinderData.AssetDescription data;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\ClickColumn.cs
NAMESPACE TEngine.Editor
L9 public delegate void SortInColumn();
L11 public static Dictionary<int, SortInColumn> SortWithIndex = new Dictionary<int, SortInColumn>
L17 public ClickColumn(MultiColumnHeaderState state) : base(state) => canSort = true;
L30 public static void SortByName() => SortHelper.SortByName();
L32 public static void SortByPath() => SortHelper.SortByPath();
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\DragAreaGetObject.cs
NAMESPACE TEngine.Editor
L8 public static Object[] GetObjects(string meg = null)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\ListInfo.cs
NAMESPACE TEngine.Editor
L5 public int Count;
L6 public string Name;
L7 public string Type;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\ReferenceFinderData.cs
NAMESPACE TEngine.Editor
L18 public enum AssetState : byte
L27 public const int MinThreadCount = 8;
L48 public string[] allAssets;
L49 public Dictionary<string, AssetDescription> assetDict = new Dictionary<string, AssetDescription>();
L51 public void CollectDependenciesInfo()
L115 public void ReadAssetInfo()
L137 public void GetAsset(string dataPath, string assetPath)
L198 public bool ReadFromCache()
L296 public void UpdateAssetState(string guid)
L318 public static string GetInfoByState(AssetState state)
L373 public void ClearCache() => _dictCache.Clear();
L375 public string GetRefCount(AssetDescription desc, AssetDescription parentDesc)
L409 public string assetDependencyHashString;
L410 public List<string> dependencies = new List<string>();
L411 public string name = "";
L412 public string path = "";
L413 public List<string> references = new List<string>();
L414 public AssetState state = AssetState.Normal;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\ResourceReferenceInfo.cs
NAMESPACE TEngine.Editor
L13 public static readonly ReferenceFinderData Data = new ReferenceFinderData();
L19 public bool needUpdateAssetTree;
L20 public bool needUpdateState = true;
L21 public List<string> selectedAssetGuid = new List<string>();
L30 public AssetTreeView mAssetTreeView;
L44 public static void FindRef()
L202 public void DrawOptionBar()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\SortConfig.cs
NAMESPACE TEngine.Editor
L7 public static readonly Dictionary<SortType, SortType> SortTypeChangeByNameHandler = new Dictionary<SortType, SortType>
L14 public static readonly Dictionary<SortType, SortType> SortTypeChangeByPathHandler = new Dictionary<SortType, SortType>
L21 public static readonly Dictionary<SortType, short> SortTypeGroup = new Dictionary<SortType, short>
L30 public const short TYPE_BY_NAME_GROUP = 2;
L31 public const short TYPE_BY_PATH_GROUP = 1;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\SortHelper.cs
NAMESPACE TEngine.Editor
L8 public delegate int SortCompare(string lString, string rString);
L10 public static readonly HashSet<string> SortedGuid = new HashSet<string>();
L11 public static readonly Dictionary<string, SortType> SortedAsset = new Dictionary<string, SortType>();
L12 public static SortType CurSortType = SortType.None;
L13 public static SortType PathType = SortType.None;
L14 public static SortType NameType = SortType.None;
L16 public static readonly Dictionary<SortType, SortCompare> CompareFunction = new Dictionary<SortType, SortCompare>
L24 public static void Init()
L30 public static void ChangeSortType(short sortGroup, Dictionary<SortType, SortType> handler, ref SortType recoverType)
L45 public static void SortByName() => ChangeSortType(SortConfig.TYPE_BY_NAME_GROUP, SortConfig.SortTypeChangeByNameHandler, ref NameType);
L47 public static void SortByPath() => ChangeSortType(SortConfig.TYPE_BY_PATH_GROUP, SortConfig.SortTypeChangeByPathHandler, ref PathType);
L49 public static void SortChild(ReferenceFinderData.AssetDescription data)
L77 public static void NormalSort(List<string> strList)
L83 public static void FastSort(List<string> strList)
L95 public static int CompareWithName(string lString, string rString)
L101 public static int CompareWithNameDesc(string lString, string rString) => 0 - CompareWithName(lString, rString);
L103 public static int CompareWithPath(string lString, string rString)
L109 public static int CompareWithPathDesc(string lString, string rString) => 0 - CompareWithPath(lString, rString);
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ReferenceFinder\SortType.cs
NAMESPACE TEngine.Editor
L3 public enum SortType
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\TexturePacker\UnityTexturePackEditor.cs
NAMESPACE <global>
L8 public class UnityTexturePackerEditor : EditorWindow
L22 public static void ShowWindow()
L154 public string name;
L155 public string sourcePath;
L156 public int x;
L157 public int y;
L158 public int w;
L159 public int h;
L160 public int sourceW;
L161 public int sourceH;
L166 public string path;
L167 public bool isReadable;
L168 public TextureImporterType type;
L169 public TextureImporterCompression compression;
L170 public int maxSize;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\ControlPanelWindow\MainToolbarControlPanelWindow.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L9 public class MainToolbarControlPanelWindow : EditorWindow
L32 public static void OpenWindow()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\ControlPanelWindow\MainToolbarElementController.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L23 public string Id { get; }
L24 public VisualElement ControlledVisualElement { get; }
L25 public bool HoldsAGroup => _foldout != null;
L26 public bool HoldsANativeElement { get; private set; }
L28 public MainToolbarElementController(OverridableElement overridableElement,
L64 public bool ContainsSubController(string id)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\ControlPanelWindow\OrganizationalFoldableContainer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L15 public OrganizationalFoldableContainer(string containerId, string foldoutText)
L41 public void SetControllers(IEnumerable<MainToolbarElementController> controllers)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\ControlPanelWindow\OverridableElement.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public string Id { get; }
L8 public VisualElement VisualElement { get; }
L9 public bool IsNative { get; }
L11 public OverridableElement(string id, VisualElement visualElement, bool isNative)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Extensions\EditorWindowExtensions.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L6 public static class EditorWindowExtensions
L8 public static void ShowAsDropdownForMainToolbar(this EditorWindow window, Rect activatorRect, Vector2 size)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\GroupDefinition.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public string GroupId { get; }
L8 public string GroupName { get; }
L9 public ToolbarAlign Alignment { get; }
L10 public int Order { get; }
L11 public string[] ToolbarElementsIds { get; }
L13 public GroupDefinition(string groupId, string groupName, ToolbarAlign alignment, int order, string[] toolbarElementsIds)
L22 public bool AreEquals(GroupDefinition other)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\GroupDropdownWindowPopup.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L12 public void Initialize(VisualElement[] groupElements)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\GroupDropdownWindowPopupManager.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L124 public static void Show(Rect activatorRect, VisualElement[] elements)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\GroupElement.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public VisualElement[] GroupedElements => _groupedElements.ToArray();
L12 public GroupElement(string name)
L19 public void Initialize(VisualElement[] groupedElements)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\GroupPopupSubWindowAttribute.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L6 public class GroupPopupSubWindowAttribute : Attribute
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\IGroupDefinitionRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public GroupDefinition[] GetAll();
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\MainToolbarElementDropdownAttribute.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\MainToolbarElementDropdownDrawer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L16 public override VisualElement CreatePropertyGUI(SerializedProperty property)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\ScriptableGroupDefinition.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L6 public sealed class ScriptableGroupDefinition : ScriptableObject
L23 public string GroupId => _groupId;
L24 public string GroupName => _groupName;
L25 public ToolbarAlign Alignment => _alignment;
L26 public int Order => _order;
L27 public string[] ToolbarElementsIds => _toolbarElementsIds == null ? new string[0] : _toolbarElementsIds;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\ScriptableGroupDefinitionHelper.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L18 public static void Refresh()
L33 public static IEnumerable<string> GetUnusedMainToolbarElementIds(IEnumerable<string> allIds)
L44 public static IEnumerable<string> GetGroupIds()
L49 public static IEnumerable<string> GetEligibleGroupChildsFor(string groupId)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\GroupDefinitions\ScriptableObjectGroupDefinitionRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L8 public GroupDefinition[] GetAll()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\GlobalActions.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L8 public static void ResetOverrides()
L14 public static void ResetOverridesIfUserAccepts()
L25 public static void ShowDialog(string title, string message, string okMessage,
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\Icons.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L15 public static Texture VisibilityOnOverrideIcon => VISIBILITY_ON_OVERRIDE_ICON_LAZY.Value;
L16 public static Texture VisibilityOffOverrideIcon => VISIBILITY_OFF_OVERRIDE_ICON_LAZY.Value;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\MenuItems.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L8 public static void Refresh()
L14 public static void OpenControlPanel()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\RefreshToolbarAutomaticExtenderOnSave.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\ServicesAndRepositories.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public static IMainToolbarElementOverrideRepository MainToolbarElementOverridesRepository =
L8 public static IGroupDefinitionRepository GroupDefinitionRepository =
L11 public static IMainToolbarElementRepository MainToolbarElementRepository =
L14 public static IValueSerializer ValueSerializer =
L17 public static IMainToolbarElementVariableSerializer MainToolbarElementVariableSerializer =
L20 public static IMainToolbarElementVariableRepository MainToolbarElementVariableRepository =
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\ToolInfo.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public const string COMPANY_NAME = "Tools/Extension/Toolbar";
L6 public const string EDITOR_MENU_BASE = COMPANY_NAME + "/" ;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\UnityNativeElementsIds.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L47 public const string TOOLBAR_PRODUCT_CAPTION = "ToolbarProductCaption";
L48 public const string ACCOUNT_DROPDOWN_ID = "AccountDropdown";
L49 public const string CLOUD_BUTTON_ID = "CloudButton";
L50 public const string VERSION_CONTROL_ID = "VersionControlButton";
L51 public const string STORE_BUTTON_ID = "StoreButton";
L54 public const string PLAY_BUTTON_ID = "PlayButton";
L55 public const string PAUSE_BUTTON_ID = "PauseButton";
L56 public const string FRAME_STEP_BUTTON_ID = "FrameStepButton";
L59 public const string LAYOUT_DROPDOWN_ID = "LayoutDropdown";
L60 public const string LAYERS_DROPDOWN_ID = "LayersDropdown";
L61 public const string SEARCH_BUTTON_ID = "SearchButton";
L62 public const string MODES_DROPDOWN_ID = "ModesDropdown";
L63 public const string PREVIEW_PACKAGES_IN_USE_DROPDOWN_ID = "PreviewPackagesInUseDropdown";
L64 public const string UNDO_BUTTON_ID = "UndoButton";
L65 public const string MULTIPLAYER_ROLE_DROPDOWN = "MultiplayerRoleDropdown";
L105 public static string IdOf(VisualElement visualElement)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Helpers\UserSettingsPrefs.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L9 public static class UserSettingsPrefs
L26 public static void SetInt(string key, int value)
L32 public static void SetFloat(string key, float value)
L38 public static void SetDouble(string key, double value)
L44 public static void SetBool(string key, bool value)
L50 public static void SetString(string key, string value)
L56 public static string GetString(string key, string defaultValue = null)
L64 public static bool GetBool(string key, bool defaultValue = false)
L72 public static int GetInt(string key, int defaultValue = 0)
L80 public static float GetFloat(string key, float defaultValue = 0.0f)
L88 public static double GetDouble(string key, double defaultValue = 0.0)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Override\IMainToolbarElementOverrideRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public MainToolbarElementOverride? Get(string elementId);
L6 public MainToolbarElementOverride[] GetAll();
L7 public void Save(MainToolbarElementOverride elementOverride);
L8 public void Clear();
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Override\MainToolbarElementOverride.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public string ElementId { get; }
L6 public bool Visible { get; }
L8 public MainToolbarElementOverride(string elementId, bool visible)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\Override\UserSettingsFileMainToolbarElementOverrideRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L16 public string ElementId;
L17 public bool Visible;
L22 public UserSettingsFileMainToolbarElementOverrideRepository()
L27 public void Clear()
L33 public MainToolbarElementOverride? Get(string elementId)
L41 public MainToolbarElementOverride[] GetAll()
L46 public void Save(MainToolbarElementOverride elementOverride)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\ButtonRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L9 public ButtonRecommendedStyle(Button button)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\ColorFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public ColorFieldRecommendedStyle(ColorField colorField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\DropdownFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L9 public DropdownFieldRecommendedStyle(DropdownField dropdownField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\EditorToolbarDropdownRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public EditorToolbarDropdownRecommendedStyle(EditorToolbarDropdown dropdown)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\EditorToolbarToggleRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L14 public EditorToolbarToggleRecommendedStyle(EditorToolbarToggle toolbarToggle)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\EnumFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L9 public EnumFieldRecommendedStyle(EnumField enumField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\EnumFlagsFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public EnumFlagsFieldRecommendedStyle(EnumFlagsField enumField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\FloatFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L11 public FloatFieldRecommendedStyle(FloatField floatField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\IntegerFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L12 public IntegerFieldRecommendedStyle(IntegerField integerField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\LayerFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public LayerFieldRecommendedStyle(LayerField layerField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\ObjectFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public ObjectFieldRecommendedStyle(ObjectField objectField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\RecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public void Apply(bool isInsideGroup)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\RecommendedStyles.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L15 public static void SetElements(RecommendedStyleVisualElement[] elements)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\RecommendedStyleVisualElement.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public VisualElement VisualElement { get; }
L8 public bool IsInsideGroup { get; }
L10 public RecommendedStyleVisualElement(VisualElement visualElement, bool isInsideGroup)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\SliderRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L11 public SliderRecommendedStyle(Slider slider)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\TagFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public TagFieldRecommendedStyle(TagField tagField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\TextFieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L11 public TextFieldRecommendedStyle(TextField textField)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\ToggleRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L9 public ToggleRecommendedStyle(Toggle toggle)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\Vector2FieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L12 public Vector2FieldRecommendedStyle(Vector2Field vector2Field)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\RecommendedStyles\Vector3FieldRecommendedStyle.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L11 public Vector3FieldRecommendedStyle(Vector3Field vector3Field)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\ElementVariables.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public MainToolbarElement MainToolbarElement;
L8 public FieldVariable[] Fields;
L9 public PropertyVariable[] Properties;
L11 public bool DidChange()
L24 public void UpdateValues()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\FieldVariable.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public readonly FieldInfo Field;
L9 public FieldVariable(MainToolbarElement element, FieldInfo field, IValueSerializer valueSerializer, SerializeAttribute attribute)
L15 public override object Get()
L20 public override void Set(object value)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\IMainToolbarElementVariableRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public void Set(SerializableElement serializableElement);
L6 public void SetAll(SerializableElement[] serializableElements);
L7 public SerializableElement[] GetAll();
L8 public void Save();
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\IMainToolbarElementVariableSerializer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public string Serialize(SerializableElementGroup serializableElementGroup);
L6 public SerializableElementGroup Deserialize(string serializedElementGroup);
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\IValueSerializer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\MainToolbarElementVariableWatcher.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L18 public MainToolbarElementVariableWatcher(IMainToolbarElementVariableRepository repository, IValueSerializer valueSerializer)
L24 public void RestoreValues(MainToolbarElement[] elements)
L77 public void Update()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\PropertyVariable.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L8 public readonly PropertyInfo Property;
L10 public PropertyVariable(MainToolbarElement element, PropertyInfo property, IValueSerializer valueSerializer, SerializeAttribute attribute)
L16 public override object Get()
L21 public override void Set(object value)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\SerializableElement.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public string ElementFullTypeName;
L6 public SerializableVariable[] Variables = new SerializableVariable[0];
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\SerializableElementGroup.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public Dictionary<string, SerializableElement> SerializableElements = new Dictionary<string, SerializableElement>();
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\SerializableVariable.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public ValueHolderType Type;
L8 public string Key;
L9 public Type ValueType;
L10 public object Value;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\SerializeAttribute.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L6 public class SerializeAttribute : Attribute
L8 public string SerializationKey { get; }
L10 public SerializeAttribute(string serializationKey = null)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\UnitySerializationMainToolbarElementVariableSerializer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L13 public Dictionary<string, SerializableElementDTO> SerializableElements;
L18 public string ElementFullTypeName;
L19 public SerializableVariableDTO[] Variables;
L24 public ValueHolderType Type;
L25 public string Key;
L26 public string SerializedValue;
L27 public string SerializedValueTypeFullyQualifiedName;
L33 public UnitySerializationMainToolbarElementVariableSerializer(IValueSerializer valuesSerializer)
L41 public string Serialize(SerializableElementGroup serializableElementGroup)
L48 public SerializableElementGroup Deserialize(string serializedElementGroup)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\UnitySerializationValueSerializer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public T Deserialize<T>(string serializedValue)
L12 public string Serialize<T>(T value)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\UserSettingsFileMainToolbarElementVariableRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L26 public UserSettingsFileMainToolbarElementVariableRepository(IMainToolbarElementVariableSerializer serializer)
L31 public SerializableElement[] GetAll()
L36 public void Set(SerializableElement serializableElement)
L41 public void SetAll(SerializableElement[] serializableElements)
L57 public void Save()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\ValueHolderType.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\SerializableValues\Variable.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L24 public MainToolbarElement Element { get; }
L25 public Type ValueType { get; }
L26 public SerializeAttribute Attribute { get; }
L28 public Variable(MainToolbarElement element, Type valueType, object initialValue, IValueSerializer valueSerializer, SerializeAttribute attribute)
L38 public abstract object Get();
L40 public abstract void Set(object value);
L42 public bool DidChange()
L63 public void UpdateValue()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\ByAttributeMainToolbarElementRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L11 public MainToolbarElement[] GetAll()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\IMainToolbarElementRepository.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L5 public MainToolbarElement[] GetAll();
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\MainToolbar.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L10 public static class MainToolbar
L21 public static event Action OnInitialized;
L22 public static event Action OnRefresh;
L24 public static VisualElement UnityToolbarRoot { get; private set; }
L26 public static VisualElement LeftContainer { get; private set; }
L27 public static VisualElement CenterContainer { get; private set; }
L28 public static VisualElement RightContainer { get; private set; }
L29 public static VisualElement PlayModeButtonsContainer { get; private set; }
L31 public static bool IsAvailable => _innerToolbarObject != null;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\MainToolbarAutomaticExtender.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L14 public static class MainToolbarAutomaticExtender
L33 public static event Action OnRefresh;
L34 public static event Action OnAddedCustomContainersToToolbar;
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\MainToolbarCustomContainer.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L20 public MainToolbarCustomContainer(string id, FlexDirection flexDirection)
L80 public void AddToContainer(VisualElement child)
L85 public void ClearContainer()
L90 public VisualElement[] GetContainerChilds()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\MainToolbarElement.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public string Id { get; }
L8 public VisualElement VisualElement { get; }
L9 public ToolbarAlign Alignment { get; }
L10 public int Order { get; }
L11 public bool UseRecommendedStyles { get; }
L13 public MainToolbarElement(string id, VisualElement visualElement,
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\MainToolbarElementAttribute.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L6 public class MainToolbarElementAttribute : Attribute
L8 public string Id { get; }
L9 public ToolbarAlign Alignment { get; }
L10 public int Order { get; }
L11 public bool UseRecommendedStyles { get; }
L21 public MainToolbarElementAttribute(string id, ToolbarAlign alignment = ToolbarAlign.Left,
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\MainToolbarElementOverrideApplier.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L12 public VisualElement RemovedVisualElement;
L13 public VisualElement Parent;
L14 public int Index;
L28 public MainToolbarElementOverrideApplier(IMainToolbarElementOverrideRepository mainToolbarElementOverrideRepository)
L33 public void SetNativeElements(NativeToolbarElement[] nativeElements)
L41 public void SetCustomElements(MainToolbarElement[] mainToolbarElements)
L46 public void ApplyOverrides()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\NativeToolbarElement.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L7 public string Id { get; }
L8 public VisualElement VisualElement { get; }
L10 public NativeToolbarElement(string id, VisualElement visualElement)
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\Toolbar\ToolbarAlign.cs
NAMESPACE Paps.UnityToolbarExtenderUIToolkit
L3 public enum ToolbarAlign
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ToolBarExtension\BuildSettingWindow.cs
NAMESPACE <global>
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ToolBarExtension\EditorQuickToolBar.cs
NAMESPACE AlicizaX.Editor.Extension
L13 public class EditorQuickToolBar : IMGUIContainer
L17 public void InitializeElement()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ToolBarExtension\LocalizationDropdownField.cs
NAMESPACE <global>
L15 public class LocalizationDropdownField : IMGUIContainer
L21 public void InitializeElement()
L72 public static void InvokeOnValidateInScene()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ToolBarExtension\ResourceModeDropdownField.cs
NAMESPACE AlicizaX.Editor.Extension
L13 public class ResourceModeDropdownField : IMGUIContainer
L25 public void InitializeElement()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\ToolBarExtension\SwitchSceneToolBar.cs
NAMESPACE <global>
L10 public class SwitchSceneToolBar : IMGUIContainer
L14 public void InitializeElement()
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\EditorIcons.cs
NAMESPACE <global>
L10 public class EditorIcons : EditorWindow
L13 public static void EditorIconsOpen()
L395 public static string[] ico_list =
###FILE G:\UnityProject\Aliciza\Client\Packages\com.alicizax.unity.editor.extension\Editor\EditorToolFunctionAttribute.cs
NAMESPACE AlicizaX.Editor.Extension
L11 public class EditorToolFunctionAttribute : Attribute
L13 public string ToolMenuPath { get; private set; }
L14 public int MenuOrder { get; private set; }
L15 public MethodInfo MethodInfo { get; private set; }
L17 public EditorToolFunctionAttribute(string menu, int menuOrder = 0)
L23 public void SetMethodInfo(MethodInfo methodInfo)
L31 public static List<EditorToolFunctionAttribute> Attributes = new List<EditorToolFunctionAttribute>();

1156
Client/.tmp_api_ui.txt Normal file

File diff suppressed because it is too large Load Diff

8
Client/Assets/Books.meta Normal file
View File

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

View File

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

View File

@ -0,0 +1,83 @@
# EditorExtension Atlas 自动图集模块手册
## 模块概述
该模块位于 `Editor/Postprocessor/Atlas`,用于维护图集配置、响应 Sprite 导入/删除、标记脏图集并执行全量生成。
## 适用场景
- 以目录为单位自动生成 UI 图集。
- 不同平台使用不同压缩格式。
- 导入资源时自动更新图集状态。
## 快速上手
### 打开配置窗口
- 菜单:`Tools/Extension/图集工具/Configuration Panel`
### 全量生成
```csharp
EditorSpriteSaveInfo.ForceGenerateAll();
```
## 模块组成
- `AtlasConfiguration`:图集配置单例。
- `AtlasConfigWindow`:配置窗口。
- `EditorSpriteSaveInfo`:缓存、脏标记、全量生成。
- `SpritePostprocessor`:接入 Unity 导入流程。
## 可调用 API
### 类型:`AtlasConfiguration`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Postprocessor/Atlas/AtlasConfiguration.cs`
#### 公开配置字段
- `outputAtlasDir`
- `sourceAtlasRoot`
- `androidFormat`
- `iosFormat`
- `webglFormat`
- `padding`
- `enableRotation`
- `blockOffset`
- `tightPacking`
- `compressionQuality`
- `autoGenerate`
- `enableLogging`
- `enableV2`
- `excludeKeywords`
- `excludeFolders`
示例:
```csharp
AtlasConfiguration.Instance.autoGenerate = true;
AtlasConfiguration.Save(true);
```
### 类型:`AtlasConfigWindow`
#### `public static void ShowWindow()`
- 作用:打开图集配置窗口。
### 类型:`EditorSpriteSaveInfo`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Postprocessor/Atlas/EditorSpriteSaveInfo.cs`
#### `public static void ConvertToSprite(string assetPath)`
- 作用:把资源路径转换或校正为 Sprite 导入设置。
#### `public static void OnImportSprite(string assetPath)`
- 作用:处理 Sprite 导入。
#### `public static void OnDeleteSprite(string assetPath)`
- 作用:处理 Sprite 删除。
#### `public static void ForceGenerateAll()`
- 作用:全量生成图集。
#### `public static void ClearCache()`
- 作用:清理模块缓存。
#### `public static void MarkParentAtlasesDirty(string assetPath)`
- 作用:标记资源所在父图集为脏。
### 类型:`SpritePostprocessor`
- 说明:继承 `AssetPostprocessor`,作为导入事件入口,本身无额外公开调用接口。
## 注意事项
- 建议原图目录与输出目录严格分离。
- 开启自动生成时,排除目录和关键字要统一维护。

View File

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

View File

@ -0,0 +1,87 @@
# EditorExtension 基础工具模块手册
## 模块概述
基础工具模块由 `EditorIcons``EditorToolFunctionAttribute` 两部分组成:
- `EditorIcons`:浏览、检索、预览并导出 Unity 内置编辑器图标。
- `EditorToolFunctionAttribute`:把静态方法声明为“编辑器快捷工具”,供 `EditorQuickToolBar` 自动收集。
## 适用场景
- 快速查找 Unity 内置图标。
- 将团队常用编辑器方法集中到工具栏菜单。
- 避免为每个工具重复创建顶级菜单。
## 快速上手
### 打开图标浏览器
- 菜单:`Tools/Extension/Editor Icons`
### 声明工具函数
```csharp
using AlicizaX.Editor.Extension;
using UnityEngine;
public static class DemoEditorTools
{
[EditorToolFunction("Demo/打印当前场景", 10)]
public static void PrintScene()
{
Debug.Log(UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().path);
}
}
```
## 详细使用说明
### `EditorIcons`
- 支持关键字搜索。
- 支持大小图标切换。
- 支持单个导出 PNG。
- 支持批量导出全部图标到目录。
### `EditorToolFunctionAttribute`
- 仅扫描静态方法。
- 扫描时机为编辑器加载阶段。
- 扫描结果按 `MenuOrder` 升序排列。
- 建议被标记的方法不要带参数。
## 可调用 API
### 类型:`EditorIcons`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/EditorIcons.cs`
#### `public static void EditorIconsOpen()`
- 作用:打开图标浏览窗口。
- 参数:无。
- 返回值:`void`。
#### `public static string[] ico_list`
- 作用:内置图标名称列表。
- 示例:
```csharp
foreach (var iconName in EditorIcons.ico_list)
{
Debug.Log(iconName);
}
```
### 类型:`AlicizaX.Editor.Extension.EditorToolFunctionAttribute`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/EditorToolFunctionAttribute.cs`
#### `public EditorToolFunctionAttribute(string menu, int menuOrder = 0)`
- 作用:声明工具菜单路径与排序值。
- 参数:
- `menu`:菜单路径。
- `menuOrder`:排序值。
#### `public string ToolMenuPath { get; }`
- 作用:获取菜单路径。
#### `public int MenuOrder { get; }`
- 作用:获取排序值。
#### `public MethodInfo MethodInfo { get; }`
- 作用:获取实际绑定的方法信息。
#### `public void SetMethodInfo(MethodInfo methodInfo)`
- 作用:由收集器在扫描时写入目标方法。
## 集成建议
- 推荐把所有项目编辑器命令统一声明为 `EditorToolFunctionAttribute`
- 图标挑选可先通过 `EditorIcons` 查名,再用于按钮和菜单项。

View File

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

View File

@ -0,0 +1,55 @@
# EditorExtension 自定义工具栏项目模块手册
## 模块概述
`ToolBarExtension` 目录在 `Toolbar` 框架之上实现了一组项目级工具栏元素:
- `EditorQuickToolBar`
- `LocalizationDropdownField`
- `ResourceModeDropdownField`
- `SwitchSceneToolBar`
- `BuildSettingWindow`(当前源码为注释模板)
## 适用场景
- 快速切换语言、资源模式与场景。
- 把项目工具统一收口到主工具栏。
- 自动调度 `EditorToolFunctionAttribute` 标记的方法。
## 快速上手
这些类型均通过 `MainToolbarElementAttribute` 自动挂载,无需手动注册。
## 可调用 API
### 类型:`AlicizaX.Editor.Extension.EditorQuickToolBar`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/ToolBarExtension/EditorQuickToolBar.cs`
- `InitializeElement()`:初始化工具下拉按钮。
### 类型:`LocalizationDropdownField`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/ToolBarExtension/LocalizationDropdownField.cs`
- `InitializeElement()`:初始化语言切换下拉框。
- `InvokeOnValidateInScene()`:强制刷新场景中所有 `UXTextMeshPro` 的编辑器预览。
### 类型:`AlicizaX.Editor.Extension.ResourceModeDropdownField`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/ToolBarExtension/ResourceModeDropdownField.cs`
- `InitializeElement()`:初始化资源模式下拉框。
### 类型:`SwitchSceneToolBar`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/ToolBarExtension/SwitchSceneToolBar.cs`
- `InitializeElement()`:初始化场景切换按钮并监听场景切换。
### 类型:`BuildSettingWindow`
- 说明:当前源码整体注释,无生效公开 API可作为未来扩展模板。
## 详细使用说明
### `EditorQuickToolBar`
- 从 `EditorToolFunctionAttributeCollector.Attributes` 读取菜单项。
- 点击菜单后通过反射执行静态方法。
### `LocalizationDropdownField`
- 读取语言列表并写入 `EditorPrefs`
- 切换后会刷新场景里的 `UXTextMeshPro` 文本预览。
### `ResourceModeDropdownField`
- 提供 `Editor / Offline / Host / Webgl` 四种模式。
- 模式结果通过 `EditorPrefs` 持久化。
### `SwitchSceneToolBar`
- 默认扫描 `Assets/Bundles/``Assets/Scenes/` 下的场景。
- 切换前会检查当前场景未保存状态。

View File

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

View File

@ -0,0 +1,74 @@
# EditorExtension HybridCLR 模块手册
## 模块概述
`HybridCLR` 模块封装热更新 DLL 构建、AOT 补充 DLL 复制、热更 DLL 复制与宏开关。核心入口为 `BuildDLLCommand`
## 适用场景
- 一键编译并拷贝热更新 DLL。
- 启用/关闭 `ENABLE_HYBRIDCLR`
- 输出 `.dll.bytes` 供运行时加载。
## 快速上手
### 菜单
- `HybridCLR/Tools/Define Symbols/Disable HybridCLR`
- `HybridCLR/Tools/Define Symbols/Enable HybridCLR`
- `HybridCLR/Tools/BuildAssets And CopyTo AssemblyTextAssetPath`
### 代码
```csharp
using UnityEditor;
BuildDLLCommand.Enable();
BuildDLLCommand.BuildAndCopyDlls(EditorUserBuildSettings.activeBuildTarget);
```
## 工作流程
1. 通过 `Enable()` / `Disable()` 控制宏与 HybridCLR 设置。
2. `BuildAndCopyDlls()` 编译热更程序集。
3. `CopyAOTHotUpdateDlls()` 复制 AOT 与 HotUpdate DLL。
4. `AssetDatabase.Refresh()` 刷新资源库。
## 可调用 API
源码:`Packages/com.alicizax.unity.editor.extension/Editor/HybridCLR/BuildDLLCommand.cs`
### 类型:`BuildDLLCommand`
#### `public static string AssemblyTextAssetPath`
- 作用:目标输出目录。
#### `public static void Disable()`
- 作用:关闭 HybridCLR 宏与设置。
#### `public static void Enable()`
- 作用:启用 HybridCLR 宏与设置。
#### `public static void BuildAndCopyDlls()`
- 作用:按当前激活平台编译并复制 DLL。
#### `public static void GenerateAll()`
- 作用:执行 `PrebuildCommand.GenerateAll()`
#### `public static void BuildAndCopyDlls(BuildTarget target)`
- 作用:按指定平台编译并复制 DLL。
#### `public static void CopyAOTHotUpdateDlls(BuildTarget target)`
- 作用:统一复制 AOT 与 HotUpdate DLL。
#### `public static void CopyAOTAssembliesToAssetPath()`
- 作用:复制 AOT 补充程序集到输出目录。
#### `public static void CopyHotUpdateAssembliesToAssetPath()`
- 作用:复制 HotUpdate 程序集到输出目录。
## 示例
```csharp
[UnityEditor.MenuItem("Tools/HybridCLR/全部生成")]
public static void BuildAll()
{
BuildDLLCommand.GenerateAll();
BuildDLLCommand.BuildAndCopyDlls(UnityEditor.EditorUserBuildSettings.activeBuildTarget);
}
```
## 注意事项
- 依赖 HybridCLR 包和相关生成脚本完整可用。
- AOT 源目录通常需要先执行生成或构建流程后才存在。

View File

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

View File

@ -0,0 +1,103 @@
# EditorExtension ReferenceFinder 引用分析模块手册
## 模块概述
`ReferenceFinder` 用于分析项目资源的依赖与反向引用关系,支持缓存、树状展示和排序。
## 适用场景
- 查询资源被谁引用。
- 清理无用资源前做依赖确认。
- 排查深层依赖链和循环引用风险。
## 快速上手
```csharp
using TEngine.Editor;
ResourceReferenceInfo.FindRef();
```
## 模块结构
- `ResourceReferenceInfo`:入口与界面层。
- `ReferenceFinderData`:采集、缓存、状态管理。
- `AssetTreeView`:树状显示。
- `SortHelper`:排序逻辑。
## 可调用 API
### 类型:`TEngine.Editor.ReferenceFinderData`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/ReferenceFinder/ReferenceFinderData.cs`
#### 公开成员
- `AssetState`
- `MinThreadCount`
- `allAssets`
- `assetDict`
- `CollectDependenciesInfo()`
- `ReadAssetInfo()`
- `GetAsset(string dataPath, string assetPath)`
- `ReadFromCache()`
- `UpdateAssetState(string guid)`
- `GetInfoByState(AssetState state)`
- `ClearCache()`
- `GetRefCount(AssetDescription desc, AssetDescription parentDesc)`
#### `AssetDescription` 字段
- `assetDependencyHashString`
- `dependencies`
- `name`
- `path`
- `references`
- `state`
### 类型:`TEngine.Editor.ResourceReferenceInfo`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/ReferenceFinder/ResourceReferenceInfo.cs`
#### 公开成员
- `Data`
- `needUpdateAssetTree`
- `needUpdateState`
- `selectedAssetGuid`
- `mAssetTreeView`
- `FindRef()`
- `DrawOptionBar()`
### 类型:`AssetTreeView`
- `AssetTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader)`
- `SortExpandItem()`
- `CreateDefaultMultiColumnHeaderState(float treeViewWidth, bool isDepend)`
### 类型:`ClickColumn`
- `SortInColumn`
- `SortWithIndex`
- `ClickColumn(MultiColumnHeaderState state)`
- `SortByName()`
- `SortByPath()`
### 类型:`DragAreaGetObject`
- `GetObjects(string meg = null)`
### 类型:`SortHelper`
- `Init()`
- `ChangeSortType(...)`
- `SortByName()`
- `SortByPath()`
- `SortChild(...)`
- `NormalSort(...)`
- `FastSort(...)`
- `CompareWithName(...)`
- `CompareWithNameDesc(...)`
- `CompareWithPath(...)`
- `CompareWithPathDesc(...)`
### 其他公开类型
- `ListInfo`
- `SortType`
- `SortConfig`
## 示例
```csharp
var data = new TEngine.Editor.ReferenceFinderData();
data.CollectDependenciesInfo();
```
## 注意事项
- 大项目建议优先使用缓存。
- 资源大规模变更后建议先清缓存再重新采集。

View File

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

View File

@ -0,0 +1,42 @@
# EditorExtension TexturePacker 模块手册
## 模块概述
`TexturePacker` 提供一个轻量级编辑器窗口 `UnityTexturePackerEditor`,用于把多张纹理打包为一张大图并记录子图布局信息。
## 适用场景
- 临时合并散图。
- 验证贴图布局。
- 做非正式生产链路的编辑器打包。
## 快速上手
```csharp
UnityTexturePackerEditor.ShowWindow();
```
## 可调用 API
源码:`Packages/com.alicizax.unity.editor.extension/Editor/TexturePacker/UnityTexturePackEditor.cs`
### 类型:`UnityTexturePackerEditor`
#### `public static void ShowWindow()`
- 作用:打开 TexturePacker 窗口。
### 公开布局信息字段
- `name`
- `sourcePath`
- `x`
- `y`
- `w`
- `h`
- `sourceW`
- `sourceH`
### 公开导入备份字段
- `path`
- `isReadable`
- `type`
- `compression`
- `maxSize`
## 使用建议
- 如果项目已有正式 SpriteAtlas 流程,该工具更适合临时处理和验证。
- 执行前后应注意纹理导入配置恢复。

View File

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

View File

@ -0,0 +1,98 @@
# EditorExtension Toolbar 扩展框架手册
## 模块概述
`Toolbar` 模块用于向 Unity 主工具栏动态注入自定义 `VisualElement` / `IMGUIContainer`,支持自动发现、排序、对齐、推荐样式、分组与用户覆盖配置。
## 适用场景
- 给 Unity 顶部工具栏挂项目级入口。
- 统一管理开发、调试、资源、场景、构建工具。
- 让工具栏元素支持分组、显隐与个性化排序。
## 快速上手
```csharp
using Paps.UnityToolbarExtenderUIToolkit;
using UnityEngine.UIElements;
[MainToolbarElement("DemoToolbar", ToolbarAlign.Right, 100)]
public class DemoToolbarElement : IMGUIContainer
{
public void InitializeElement()
{
onGUIHandler = () => UnityEngine.GUILayout.Label("Demo");
}
}
```
## 工作机制
1. `MainToolbar` 定位 Unity 原生 Toolbar 容器。
2. `MainToolbarAutomaticExtender` 负责刷新与注入。
3. 特性仓储扫描带 `MainToolbarElementAttribute` 的类型。
4. 元素实例化后包装为 `MainToolbarElement`
5. 控制面板和覆盖配置负责用户态管理。
## 可调用 API
### 类型:`MainToolbarElementAttribute`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Toolbar/MainToolbarElementAttribute.cs`
- `MainToolbarElementAttribute(string id, ToolbarAlign alignment = ToolbarAlign.Left, int order = 0, bool useRecommendedStyles = true)`
- `Id`
- `Alignment`
- `Order`
- `UseRecommendedStyles`
### 类型:`MainToolbarElement`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Toolbar/MainToolbarElement.cs`
- `Id`
- `VisualElement`
- `Alignment`
- `Order`
- `UseRecommendedStyles`
- 构造函数 `MainToolbarElement(...)`
### 类型:`MainToolbar`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Toolbar/MainToolbar.cs`
- `OnInitialized`
- `OnRefresh`
- `UnityToolbarRoot`
- `LeftContainer`
- `CenterContainer`
- `RightContainer`
- `PlayModeButtonsContainer`
- `IsAvailable`
### 类型:`MainToolbarAutomaticExtender`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Toolbar/MainToolbarAutomaticExtender.cs`
- `OnRefresh`
- `OnAddedCustomContainersToToolbar`
### 类型:`MainToolbarControlPanelWindow`
源码:`Packages/com.alicizax.unity.editor.extension/Editor/Toolbar/ControlPanelWindow/MainToolbarControlPanelWindow.cs`
- `OpenWindow()`
### 类型:`MainToolbarElementController`
- `Id`
- `ControlledVisualElement`
- `HoldsAGroup`
- `HoldsANativeElement`
### 其他重要公开类型
- `ToolbarAlign`
- `GroupDefinition`
- `GroupElement`
- `ScriptableGroupDefinition`
- `MainToolbarElementDropdownAttribute`
- `MainToolbarElementOverride`
- `RecommendedStyle` 及派生类
- `Variable` / `SerializableVariable` 等变量序列化类型
## 打开控制面板
- 菜单:`Tools/Extension/Toolbar/Main Toolbar Control Panel`
- 代码:`MainToolbarControlPanelWindow.OpenWindow();`
## 注意事项
- `Id` 应稳定且全局唯一。
- 自定义元素建议在 `InitializeElement()` 中做依赖判空。

View File

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

View File

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

View File

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

View File

@ -0,0 +1,182 @@
# Event
## 模块概述
Event 模块提供轻量级、低分配的结构体事件系统适合模块解耦、状态广播、UI/玩法/流程间通知,以及编辑器内订阅行为监控。
设计重点:
- 使用 `struct` 事件降低 GC 压力
- 通过泛型容器按事件类型隔离订阅列表
- 使用调试注册表记录订阅、发布、扩容等行为
## 快速开始
1. 定义 `struct` 事件并实现 `IEventArgs`
2. 调用 `EventBus.Subscribe<T>()` 订阅
3. 调用 `EventBus.Publish(in evt)` 发布
4. 在对象失活或销毁时释放订阅句柄
```csharp
using AlicizaX;
public struct PlayerLevelUpEvent : IEventArgs
{
public int NewLevel;
}
public sealed class EventQuickStart
{
private EventRuntimeHandle _handle;
public void Initialize()
{
_handle = EventBus.Subscribe<PlayerLevelUpEvent>(OnLevelUp);
EventBus.Publish(new PlayerLevelUpEvent { NewLevel = 10 });
}
private void OnLevelUp(PlayerLevelUpEvent evt)
{
Log.Info($"Level => {evt.NewLevel}");
}
}
```
## 架构说明
```text
业务代码
├─ EventBus.Subscribe<T>()
├─ EventBus.Publish<T>()
└─ EventBus.Clear<T>()
EventContainer<T>
EventRuntimeHandle / 订阅槽
EventDebugRegistry
```
## 核心类型说明
### `IEventArgs`
- 所有事件载体的标记接口
- 事件类型必须是 `struct`
### `EventBus`
公开能力:
- `Subscribe<T>(Action<T> handler)`
- `Publish<T>(in T evt)`
- `GetSubscriberCount<T>()`
- `EnsureCapacity<T>(int capacity)`
- `Clear<T>()`
### `EventRuntimeHandle`
- 表示一次已建立的订阅
- 用于解绑或自动管理订阅生命周期
### `EventInitialSize<T>`
- 用于为某类事件声明初始订阅容量
- 高频事件建议预热容量
## API 参考
### `EventBus.Subscribe<T>(Action<T> handler) where T : struct, IEventArgs`
- 必填参数:`handler`
- 返回值:`EventRuntimeHandle`
- 泛型约束:`T : struct, IEventArgs`
- 说明:订阅某种事件
- 注意:建议保存返回句柄,便于后续解绑
### `EventBus.Publish<T>(in T evt) where T : struct, IEventArgs`
- 必填参数:`evt`
- 返回值:无
- 说明:同步发布事件
- 注意:回调会立即执行,发布链路中不要写过重逻辑
### `EventBus.GetSubscriberCount<T>()`
- 返回值:`int`
- 说明:返回当前事件订阅数量
### `EventBus.EnsureCapacity<T>(int capacity)`
- 必填参数:`capacity`
- 返回值:无
- 说明:预热内部容器容量
### `EventBus.Clear<T>()`
- 返回值:无
- 说明:清空某类事件订阅
## 完整使用示例
```csharp
using AlicizaX;
using UnityEngine;
public struct CoinChangedEvent : IEventArgs
{
public int CurrentValue;
public int Delta;
}
public sealed class EventExample : MonoBehaviour
{
private EventRuntimeHandle _handle;
private int _coin;
private void OnEnable()
{
EventBus.EnsureCapacity<CoinChangedEvent>(8);
_handle = EventBus.Subscribe<CoinChangedEvent>(OnCoinChanged);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.C))
{
_coin += 100;
EventBus.Publish(new CoinChangedEvent
{
CurrentValue = _coin,
Delta = 100
});
}
}
private void OnDisable()
{
_handle.Dispose();
}
private void OnCoinChanged(CoinChangedEvent evt)
{
Debug.Log($"Coin changed: {evt.CurrentValue} (+{evt.Delta})");
}
}
```
## 最佳实践
- 事件体尽量小,避免塞入大对象
- 高频事件预热容量
- 订阅与释放时机成对出现
## 常见错误
- 事件类型定义成 `class`
- 只订阅不解绑
## 性能注意事项
- `Publish` 为同步执行,避免重逻辑
- 结合编辑器事件监视器检查扩容次数和订阅抖动

View File

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

View File

@ -0,0 +1,186 @@
# Foundation
## 模块概述
Foundation 是整个框架的运行时基础层,负责:
- 应用根节点初始化
- 服务容器与作用域管理
- 公共异常、内存池、数据结构
- 全局访问入口与运行时基础配置
- 模块动态绑定与启动时配置注入
如果把整个包看成一棵树Foundation 就是树根;其他模块都建立在它提供的服务世界之上。
## 快速开始
### 最少步骤
1. 在启动场景挂载 `RootModule`
2. 让各功能模块组件与 `RootModule` 位于同一生命周期体系内
3. 使用 `GameApp``AppServices` 获取模块服务
### 最小示例
```csharp
using AlicizaX;
using UnityEngine;
public sealed class FoundationQuickStart : MonoBehaviour
{
private void Start()
{
RootModule root = GameApp.Base;
root.FrameRate = 120;
root.GameSpeed = 1f;
Debug.Log($"Has world: {AppServices.HasWorld}");
}
}
```
## 架构说明
```text
RootModule
└─ AppServiceRoot
└─ ServiceWorld
├─ App Scope
├─ Scene Scope
└─ Gameplay Scope
```
### 各部分职责
- `RootModule`:全局根节点,负责运行参数和全局清理
- `AppServiceRoot`:创建 `ServiceWorld` 并驱动 Tick
- `ServiceWorld`:持有多个 `ServiceScope`
- `ServiceScope`:某个作用域下的服务容器
- `AppServices`:统一静态访问门面
- `GameApp`:高频模块快捷入口
## 核心类型说明
### `RootModule`
关键属性:
- `FrameRate`:目标帧率
- `GameSpeed`:时间缩放
- `IsGamePaused`:是否暂停
- `RunInBackground`:后台运行
- `NeverSleep`:禁止休眠
关键方法:
- `PauseGame()`
- `ResumeGame()`
- `ResetNormalGameSpeed()`
### `AppServices`
常用成员:
- `HasWorld` / `HasScene` / `HasGameplay`
- `App` / `Scene` / `Gameplay`
- `EnsureWorld()` / `EnsureScene()` / `EnsureGameplay()`
- `Require<T>()`
- `TryGet<T>(out T service)`
- `Shutdown()`
### `GameApp`
公开入口:
- `Base`
- `Audio`
- `Localization`
- `ObjectPool`
- `Procedure`
- `Resource`
- `Scene`
- `Timer`
- `UI`
### `ModuleDynamicBind`
作用:
- 在非 Editor 环境中读取 `ModuleDynamicBindInfo`
- 对 `ResourceComponent`、`DebuggerComponent`、`LocalizationComponent` 注入启动配置
## API 参考
### `AppServices.Require<T>() where T : class, IService`
- 参数:无
- 返回值:`T`
- 泛型约束:`class, IService`
- 说明:强制获取已注册服务
- 异常:服务世界未创建或服务未注册时失败
### `AppServices.TryGet<T>(out T service) where T : class, IService`
- 输出参数:`service`
- 返回值:`bool`
- 说明:安全查询服务
### `AppServices.EnsureWorld(int appScopeOrder = ServiceDomainOrder.App)`
- 可选参数:`appScopeOrder`
- 返回值:`ServiceWorld`
### `RootModule.PauseGame()`
- 返回值:无
- 说明:保存当前速度并暂停
### `RootModule.ResumeGame()`
- 返回值:无
- 说明:恢复暂停前速度
## 完整使用示例
```csharp
using AlicizaX;
using UnityEngine;
public sealed class FoundationExample : MonoBehaviour
{
private void Start()
{
RootModule root = GameApp.Base;
root.FrameRate = 120;
root.RunInBackground = true;
root.NeverSleep = true;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
if (GameApp.Base.IsGamePaused)
GameApp.Base.ResumeGame();
else
GameApp.Base.PauseGame();
}
}
}
```
## 最佳实践
- 只保留一个 `RootModule`
- 首场景统一挂载框架组件
- 常用服务走 `GameApp`,扩展服务走 `AppServices`
## 常见错误
- 服务未注册就访问
- 多个 `RootModule` 并存
## 性能注意事项
- 不要频繁重建服务世界
- 高频访问模块时优先使用 `GameApp` 的缓存入口

View File

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

View File

@ -0,0 +1,98 @@
# GameObjectPool
## 模块概述
GameObjectPool 面向场景对象与预制体实例复用。它基于 `PoolConfig` 决定某个资源是否入池、如何匹配、如何预热,并可通过 `Resources` 或 AssetBundle/YooAsset 进行加载。
## 快速开始
1. 场景挂载 `GameObjectPoolManager`
2. 准备 `PoolConfigScriptableObject`
3. 确保 `ResourceComponent` 已注册
4. 使用 `PreloadAsync` / `GetGameObjectAsync` / `Release`
## 架构说明
```text
GameObjectPoolManager
├─ PoolConfigScriptableObject
├─ PoolConfig
├─ RuntimePrefabPool
└─ IResourceLoader
```
## 核心类与接口
### `GameObjectPoolManager`
主要能力:
- `GetGameObject(...)`
- `GetGameObjectAsync(...)`
- `Preload(...)`
- `PreloadAsync(...)`
- `Release(GameObject gameObject)`
- `ClearAllPools()`
- `ForceCleanup()`
### `PoolConfig`
决定:
- 资源匹配方式
- 预热数量
- 清理与过期策略
- 使用哪种资源加载器
## API 参考
### `GetGameObject(string assetPath, Transform parent = null)`
- 必填参数:`assetPath`
- 可选参数:`parent`
- 返回值:`GameObject`
- 异常:初始化未完成时会抛异常
### `GetGameObjectAsync(string assetPath, Transform parent = null, CancellationToken cancellationToken = default)`
- 必填参数:`assetPath`
- 可选参数:`parent`
- 可选参数:`cancellationToken`
- 返回值:`UniTask<GameObject>`
### `Release(GameObject gameObject)`
- 必填参数:`gameObject`
- 返回值:无
## 完整使用示例
```csharp
using AlicizaX;
using Cysharp.Threading.Tasks;
using UnityEngine;
public sealed class GameObjectPoolExample : MonoBehaviour
{
[SerializeField] private GameObjectPoolManager poolManager;
private async UniTaskVoid Start()
{
await poolManager.PreloadAsync("Assets/Bundles/Effects/Fx_Hit.prefab", 3);
GameObject fx = await poolManager.GetGameObjectAsync("Assets/Bundles/Effects/Fx_Hit.prefab", transform);
await UniTask.Delay(1000);
poolManager.Release(fx);
}
}
```
## 最佳实践
- 特效、子弹、临时场景装饰物优先走该模块
- 常见资源在初始化阶段预热
## 常见错误
- 在初始化完成前调用同步接口
- 对池对象手动 `Destroy`

View File

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

View File

@ -0,0 +1,204 @@
# ObjectPool
## 模块概述
ObjectPool 是面向纯 C# 对象的通用对象池模块适合缓存临时数据对象、资源包装对象、UI/资源扩展辅助对象和调试器内部缓存对象。
它与 `MemoryPool` 的区别:
- `MemoryPool` 更偏向单个对象快速申请/释放
- `ObjectPool` 更偏向带策略的池管理,支持容量、过期、优先级、锁定等行为
## 快速开始
1. 场景挂载 `ObjectPoolComponent`
2. 定义继承 `ObjectBase` 的对象类型
3. 使用 `GameApp.ObjectPool.CreatePool<T>()`
4. `Register` / `Spawn` / `Unspawn`
```csharp
using AlicizaX;
using AlicizaX.ObjectPool;
public sealed class CacheItem : ObjectBase
{
public string Key;
public override void Clear()
{
Key = null;
}
}
public sealed class ObjectPoolQuickStart
{
public void Run()
{
var pool = GameApp.ObjectPool.CreatePool<CacheItem>(ObjectPoolCreateOptions.Single("Cache"));
CacheItem item = MemoryPool.Acquire<CacheItem>();
item.Key = "A";
pool.Register(item, false);
CacheItem spawned = pool.Spawn();
pool.Unspawn(spawned);
}
}
```
## 架构说明
```text
ObjectPoolComponent
└─ ObjectPoolService
├─ IObjectPool<T>
├─ ObjectPoolBase
└─ ObjectBase
```
## 核心类型说明
### `IObjectPoolService`
负责:
- 创建对象池
- 查询对象池
- 销毁对象池
- 统一释放未使用对象
### `IObjectPool<T>`
常用公开方法:
- `Register`
- `Spawn`
- `Unspawn`
- `SetLocked`
- `SetPriority`
- `Release`
- `ReleaseAllUnused`
### `ObjectBase`
- 池内对象基类
- 需要正确实现 `Clear()`
### `ObjectPoolCreateOptions`
主要参数:
- `name`
- `allowMultiSpawn`
- `autoReleaseInterval`
- `capacity`
- `expireTime`
- `priority`
## API 参考
### `IObjectPoolService.CreatePool<T>(ObjectPoolCreateOptions options = default) where T : ObjectBase`
- 可选参数:`options`
- 返回值:`IObjectPool<T>`
- 泛型约束:`T : ObjectBase`
### `IObjectPool<T>.Register(T obj, bool spawned)`
- 必填参数:`obj`
- 必填参数:`spawned`
- 返回值:无
### `IObjectPool<T>.Spawn()`
- 返回值:`T`
- 说明:取出一个可用对象;无可用对象时通常返回 `null`
### `IObjectPool<T>.Unspawn(T obj)`
- 必填参数:`obj`
- 返回值:无
### `IObjectPool<T>.ReleaseAllUnused()`
- 返回值:无
- 说明:释放当前池中未使用对象
## 完整使用示例
```csharp
using AlicizaX;
using AlicizaX.ObjectPool;
using UnityEngine;
public sealed class DamageTextData : ObjectBase
{
public int Value;
public Color Color;
public void Init(int value, Color color)
{
Value = value;
Color = color;
}
public override void Clear()
{
Value = 0;
Color = default;
}
}
public sealed class ObjectPoolExample : MonoBehaviour
{
private IObjectPool<DamageTextData> _pool;
private void Start()
{
_pool = GameApp.ObjectPool.CreatePool<DamageTextData>(
new ObjectPoolCreateOptions(
name: "DamageText",
allowMultiSpawn: false,
autoReleaseInterval: 30f,
capacity: 64,
expireTime: 120f,
priority: 0));
for (int i = 0; i < 10; i++)
{
DamageTextData data = MemoryPool.Acquire<DamageTextData>();
data.Init(i, Color.red);
_pool.Register(data, false);
}
}
public void ShowDamage(int damage)
{
DamageTextData data = _pool.Spawn();
if (data == null)
{
data = MemoryPool.Acquire<DamageTextData>();
}
data.Init(damage, Color.yellow);
Debug.Log($"Damage => {data.Value}");
_pool.Unspawn(data);
}
}
```
## 最佳实践
- 对象应保持“可完全重置”
- 通过 `ObjectPoolCreateOptions` 明确池策略
- 大量短生命周期对象优先考虑对象池
## 常见错误
- 把 `GameObject` 放入该池
- `Clear()` 未重置字段
- 未区分 `Register(..., true/false)`
## 性能注意事项
- 大对象池请配置 `capacity``expireTime`
- 过多小池会增加管理成本

View File

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

View File

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

View File

@ -0,0 +1,157 @@
# EditorTools
## 模块概述
EditorTools 是框架的编辑器侧配套,覆盖 Inspector、自定义窗口、配置工具与代码生成流程目的是降低模块接入与排查成本。
与 UI 最相关的部分是:
- `UISettingEditorWindow`
- `UIGenerateQuick`
- `UIScriptGeneratorHelper`
- `UIGenerateConfiguration`
它们共同组成了 **UIHolder 自动生成工作流**
## 快速开始
### UI 绑定工具的基本使用流程
1. 打开 UI 生成配置窗口,配置 UI 规则
2. 把 UI 预制体放在配置的 `UIPrefabRootPath` 目录下
3. 按命名规范布置需要绑定的节点
4. 选中 UI 预制体根节点
5. 执行菜单 `GameObject/UI生成绑定`
6. 等待脚本编译完成
7. 生成器自动把 `XXXHolder` 挂回预制体,并回填控件字段
## UIHolder 自动生成说明
### 1. `UIHolder` 的定位
在本框架中:
- `UIHolder` 指的是继承自 `UIHolderObjectBase` 的绑定类
- 它主要用于保存控件引用和资源标签
- 它不是主要的业务逻辑承载类
推荐方式:
- **手写 Window / Widget 逻辑**
- **自动生成 Holder 绑定类**
### 2. 使用哪个工具生成
核心入口:
- 菜单:`GameObject/UI生成绑定`
对应代码入口位于:
- `Packages/com.alicizax.unity.framework/Editor/UI/GenerateWindow/UIGenerateQuick.cs:1`
当你执行该菜单时,生成器会:
- 检查当前选中的对象是否是 prefab
- 读取 `UIGenerateConfiguration`
- 校验 prefab 是否位于允许的 UI 根路径下
- 分析节点名并推断组件类型
- 输出 `UIHolder` 脚本
- 在脚本编译后自动挂到 prefab 上
- 自动把字段与节点/组件引用绑定完成
### 3. 命名规则如何影响生成
生成器会结合:
- `UIElementRegexConfigs`
- `ComCheckSplitName`
- `ComCheckEndName`
- `ArrayComSplitName`
来识别节点绑定信息。
例如默认配置会把:
- `Btn#Close@` 识别为按钮字段
- `Text#Title@` 识别为文本字段
- `Img#Icon@` 识别为图片字段
### 4. 生成结果是什么
生成出的 Holder 类通常:
- 继承 `UIHolderObjectBase`
- 自动带有 `UIResAttribute`
- 自动写入资源路径常量
- 自动生成字段与公开访问器
这使得 UI 逻辑层可以直接通过泛型 Holder 访问控件,而无需再手动查找。
## 相关工具与职责
### `UISettingEditorWindow`
作用:
- 维护 UI 生成配置
- 配置输出目录、命名空间、Prefab 根路径、资源加载方式
### `UIGenerateQuick`
作用:
- 提供快速菜单入口
- 校验当前对象是否可生成
### `UIScriptGeneratorHelper`
作用:
- 扫描节点
- 推断字段名和组件类型
- 生成代码
- 在脚本重载后自动挂载脚本并绑定字段
### `UIGenerateConfiguration`
作用:
- 保存生成规则与路径设置
- 支持不同项目或不同目录使用不同配置
## 使用示例
```csharp
// 推荐流程:
// 1. 设计 InventoryItem.prefab
// 2. 选中 prefab 根节点
// 3. 执行 “GameObject/UI生成绑定”
// 4. 得到 InventoryItemHolder : UIHolderObjectBase
// 5. 在业务代码中编写:
// public sealed class InventoryItemWidget : UIWidget<InventoryItemHolder> { ... }
```
## 最佳实践
- 把 UI 生成规则纳入项目模板,避免每个模块自行定义一套命名方式
- Holder 文件视为“生成产物”,不要手工长期维护
- 如果修改了 prefab 绑定节点,重新执行一次生成工具
- 逻辑类和生成类分离,减少合并冲突
## 常见错误
### 预制体不在配置的 UI 根路径下
- 现象:执行生成工具无结果
- 原因:`UIGenerateQuick.CheckCanGenerate` 校验失败
### 修改了预制体但没重新生成 Holder
- 现象:字段缺失或控件引用错误
- 处理:重新执行 `GameObject/UI生成绑定`
### 手动改了生成类名称或命名空间
- 现象:逻辑类泛型类型失配
- 处理:尽量不要手改生成文件,必要时同步更新生成配置与逻辑类引用

View File

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

View File

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

View File

@ -0,0 +1,54 @@
# Plugins
## 模块概述
`Plugins` 目录保存框架依赖的第三方程序集与源码生成插件,它们补充了框架运行时能力、兼容层与自动注册逻辑。
## 快速开始
通常不需要业务层主动初始化本模块。开发者需要做的是:
1. 确认 Unity 正常导入 DLL
2. 不随意删除或移动 `Plugins` 目录文件
3. 在 UI / Event 自动注册异常时优先检查生成器 DLL 是否生效
## 架构说明
```text
Plugins
├─ XLog.dll
├─ SharpZipLib
├─ System.Memory / Buffers / Unsafe
├─ EventSourceGenerator.dll
└─ UISourceGenerator.dll
```
## 主要内容
- `XLog.dll`:日志能力支持
- `ICSharpCode.SharpZipLib.dll`:压缩/解压相关能力
- `System.Buffers.dll`、`System.Memory.dll`、`System.Runtime.CompilerServices.Unsafe.dll`:底层兼容依赖
- `EventSourceGenerator.dll`:事件源码生成插件
- `UISourceGenerator.dll`UI 源码生成插件
## API / 作用说明
### `EventSourceGenerator.dll`
- 作用:辅助事件相关代码生成
### `UISourceGenerator.dll`
- 作用:辅助 UI 元数据与资源绑定注册
## 完整使用示例
```csharp
// 本模块通常不直接由业务代码调用。
// 若出现 UI/Event 自动注册异常,请先检查对应 DLL 在 Unity 中是否正常导入。
```
## 最佳实践
- 锁定插件版本
- 升级 Unity 后优先验证生成器与 IL2CPP 打包链路

View File

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

View File

@ -0,0 +1,134 @@
# Aliciza X Framework 快速入口
## 1. 框架简介
`com.alicizax.unity.framework` 是一套面向 Unity 项目的模块化基础框架,围绕 **根节点统一启动、服务容器统一获取、运行时模块按需组合** 的设计思想构建。
框架通过 `RootModule` 建立全局运行时入口,通过 `AppServices` / `GameApp` 暴露常用服务访问点,再由 UI、资源、音频、本地化、场景、流程、池化、定时器等模块分别承载具体业务能力。
### 核心设计理念
- **组合优先**:各模块以组件或服务形式注册,按项目需要启用。
- **职责分层**:区分 `Core / Runtime / Editor / Plugins`,运行时与编辑器逻辑边界清晰。
- **统一入口**:通过 `GameApp`、服务定位与根模块生命周期减少业务侧样板代码。
- **面向工程化**覆盖资源加载、UI 绑定、流程切换、调试监视、池化复用等常见项目基础设施。
## 2. 推荐阅读顺序
1. [Foundation](./Core/Foundation.md)
2. [Resource](./Runtime/Resource.md)
3. [Timer](./Runtime/Timer.md)
4. [UI](./Runtime/UI.md)
5. 其余业务模块
## 3. 模块目录
### Core
- [Foundation](./Core/Foundation.md):根模块、服务容器、通用基础设施与核心抽象。
- [Event](./Core/Event.md):结构体事件总线、事件订阅与调试监视。
- [ObjectPool](./Core/ObjectPool.md):通用对象池与可复用实例管理。
- [GameObjectPool](./Core/GameObjectPool.md):面向预制体/场景对象的 GameObject 级池化系统。
### Runtime
- [Audio](./Runtime/Audio.md):音频播放、分组音量、播放句柄与运行时控制。
- [Debugger](./Runtime/Debugger.md):运行时调试面板、监控入口与调试扩展。
- [Localization](./Runtime/Localization.md):本地化表、语言切换与文本刷新机制。
- [Procedure](./Runtime/Procedure.md):流程/状态节点切换与启动流程组织。
- [Resource](./Runtime/Resource.md):资源系统封装、包初始化、资源加载与实例化。
- [Scene](./Runtime/Scene.md):场景加载、场景域切换与场景生命周期协作。
- [Timer](./Runtime/Timer.md):统一定时器服务、延时/循环/取消与时间驱动逻辑。
- [UI](./Runtime/UI.md)UI 窗口、Widget、Holder 绑定、层级管理与动画过渡。
### Editor
- [EditorTools](./Editor/EditorTools.md)Inspector、事件监视器、UI 绑定生成器与本地化编辑工具。
### Plugins
- [Plugins](./Plugins/Plugins.md):第三方程序集、代码生成器与插件职责说明。
## 4. 整体协作关系
```text
RootModule
└── AppServiceRoot
└── AppServices / GameApp
├── Resource
├── Timer
├── UI
├── Audio
├── Localization
├── Procedure
├── ObjectPool / GameObjectPool
└── Scene
```
### 常见依赖关系
- `UI` 通常依赖 `Resource` 加载界面资源,并依赖 `Timer` 驱动过渡或延迟行为。
- `Scene` 常与 `Resource` 协作处理场景包加载,与 `Procedure` 协作组织关卡切换。
- `Localization` 常与 `UI``UX` 文本组件协作,负责语言刷新。
- `GameObjectPool` 常与 `Resource` 协作完成预制体异步加载与回收复用。
## 5. 最小接入步骤
### 场景基础组件
推荐在启动场景中至少挂载:
- `RootModule`
- `ResourceComponent`
- `TimerComponent`
- `UIComponent`
### 启动顺序建议
```text
RootModule -> ResourceComponent -> TimerComponent -> UIComponent -> 其他业务模块
```
### 最小示例
```csharp
using AlicizaX;
using AlicizaX.Resource.Runtime;
using Cysharp.Threading.Tasks;
using UnityEngine;
public sealed class BootstrapExample : MonoBehaviour
{
private async void Start()
{
IResourceService resourceService = GameApp.Resource;
await resourceService.InitPackageAsync();
await GameApp.UI.ShowUI<MainMenuWindow>();
}
}
```
## 6. 常见问题
### `GameApp.xxx` 为空
- 对应模块组件尚未挂载或未完成初始化。
- `RootModule` 尚未建立根服务容器。
- 获取时机早于模块注册阶段。
### UI 无法打开
- `UIComponent` 未配置 `UIRoot`
- UI 资源路径或 `UIResAttribute` 配置错误。
- UI 绑定代码未生成,或 `UIWidget<T>` 泛型未引用正确的 Holder 类型。
### 资源加载失败
- 资源包尚未初始化。
- 资源路径与包内地址不一致。
- 运行环境缺少对应包或依赖资源。
## 7. 下一步
- 从 [Foundation](./Core/Foundation.md) 理解根模块与服务注册方式。
- 从 [Resource](./Runtime/Resource.md) 理解资源系统初始化与加载链路。
- 从 [UI](./Runtime/UI.md) 理解 UIHolder 自动生成、`UIWidget<T>` 绑定与窗口生命周期。

View File

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

View File

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

View File

@ -0,0 +1,94 @@
# Audio
## 模块概述
Audio 模块负责统一音频分类、音量控制、音频池与播放行为。它把音频拆分为音乐、音效、UI 音效、语音等类别,并支持使用 `AudioMixer` 做混音控制。
## 快速开始
1. 场景挂载 `AudioComponent`
2. 配置 `AudioMixer`、实例根节点与 `AudioGroupConfig`
3. 通过 `GameApp.Audio` 播放音频
```csharp
using AlicizaX;
using AlicizaX.Audio.Runtime;
public sealed class AudioQuickStart
{
public void PlayClick()
{
GameApp.Audio.Play(AudioType.UISound, "Audio/UI/Click");
}
}
```
## 架构说明
```text
AudioComponent
└─ AudioService
├─ AudioCategory
├─ AudioAgent
├─ AudioGroupConfig
└─ AudioClipPool
```
## 核心类与接口
### `IAudioService`
主要属性:
- `Volume`
- `Enable`
- `MusicVolume` / `SoundVolume` / `UISoundVolume` / `VoiceVolume`
- `MusicEnable` / `SoundEnable` / `UISoundEnable` / `VoiceEnable`
- `AudioMixer`
- `InstanceRoot`
主要方法:
- `Initialize(...)`
- `Play(...)`
- `Stop(...)`
- `StopAll(...)`
- `PutInAudioPool(...)`
- `CleanSoundPool()`
## API 参考
### `Initialize(AudioGroupConfig[] audioGroupConfigs, Transform instanceRoot = null, AudioMixer audioMixer = null)`
- 必填参数:`audioGroupConfigs`
- 可选参数:`instanceRoot`
- 可选参数:`audioMixer`
- 返回值:无
### `Play(AudioType type, string path, bool bLoop = false, float volume = 1.0f, bool bAsync = false, bool bInPool = false)`
- 必填参数:`type`
- 必填参数:`path`
- 其余均为可选参数
- 返回值:`AudioAgent`
## 完整使用示例
```csharp
using AlicizaX;
using AlicizaX.Audio.Runtime;
public sealed class AudioExample
{
public void PlayBgm()
{
GameApp.Audio.MusicVolume = 0.8f;
GameApp.Audio.Play(AudioType.Music, "Audio/Bgm/MainTheme", true, 1f, true, true);
}
}
```
## 最佳实践
- 常用短音效建议预热
- 背景音乐和 UI 音效分混音组管理

View File

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

View File

@ -0,0 +1,68 @@
# Debugger
## 模块概述
Debugger 模块提供运行时调试面板可查看日志、FPS、系统信息、场景信息、对象池、运行时内存等。调试窗口采用树状注册方式支持扩展自定义页面。
## 快速开始
1. 场景挂载 `DebuggerComponent`
2. 选择激活策略 `DebuggerActiveWindowType`
3. 通过 `RegisterDebuggerWindow` 扩展自定义页面
## 架构说明
```text
DebuggerComponent
└─ DebuggerService
├─ IDebuggerWindowGroup
└─ IDebuggerWindow
```
## 核心类与接口
### `IDebuggerService`
公开能力:
- `ActiveWindow`
- `DebuggerWindowRoot`
- `RegisterDebuggerWindow(...)`
- `UnregisterDebuggerWindow(...)`
- `GetDebuggerWindow(...)`
- `SelectDebuggerWindow(...)`
## API 参考
### `RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow, params object[] args)`
- 必填参数:`path`
- 必填参数:`debuggerWindow`
- 可选参数:`args`
- 返回值:无
### `UnregisterDebuggerWindow(string path)`
- 返回值:`bool`
## 完整使用示例
```csharp
using AlicizaX.Debugger.Runtime;
using UnityEngine;
public sealed class SimpleDebuggerWindow : IDebuggerWindow
{
public void Initialize(params object[] args) { }
public void Shutdown() { }
public void OnEnter() { }
public void OnLeave() { }
public void OnUpdate(float elapseSeconds, float realElapseSeconds) { }
public void OnDraw() => GUILayout.Label("Custom debug page");
}
```
## 最佳实践
- 自定义窗口只放诊断信息
- 发布环境建议仅开发版开启

View File

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

View File

@ -0,0 +1,97 @@
# Localization
## 模块概述
Localization 模块负责语言管理、本地化表装载、键值查询与格式化输出。它支持启动时加载内置表与资源表,也支持运行时异步切换语言。
## 快速开始
1. 挂载 `LocalizationComponent`
2. 设置默认语言
3. 配置启动表或资源路径
4. 使用 `GameApp.Localization.GetString()`
```csharp
using AlicizaX;
public sealed class LocalizationQuickStart
{
public string GetTitle()
{
return GameApp.Localization.GetString("UI_Title");
}
}
```
## 架构说明
```text
LocalizationComponent
└─ LocalizationService
├─ GameLocaizationTable
├─ LocalizationLanguage
└─ LocalizationChangeEvent
```
## 核心类与接口
### `ILocalizationService`
公开能力:
- `Language`
- `Initialize(string language)`
- `ChangedLanguage(string language)`
- `SwitchLanguageAsync(string language, CancellationToken cancellationToken = default)`
- `GetString(...)`
- `TryGetRawString(...)`
- `CoverAddLocalizationConfig(...)`
- `IncreAddLocalizationConfig(...)`
- `ReloadLocalizationConfig(...)`
## API 参考
### `Initialize(string language)`
- 必填参数:`language`
- 返回值:无
### `SwitchLanguageAsync(string language, CancellationToken cancellationToken = default)`
- 必填参数:`language`
- 可选参数:`cancellationToken`
- 返回值:`UniTask`
### `GetString(string key, params object[] args)`
- 必填参数:`key`
- 可选参数:`args`
- 返回值:`string`
## 完整使用示例
```csharp
using AlicizaX;
using Cysharp.Threading.Tasks;
using UnityEngine;
public sealed class LocalizationExample : MonoBehaviour
{
private async void Start()
{
Debug.Log(GameApp.Localization.GetString("UI_Start"));
await GameApp.Localization.SwitchLanguageAsync("English");
Debug.Log(GameApp.Localization.GetString("UI_Start"));
}
}
```
## 最佳实践
- 统一 Key 命名规则
- 语言切换事件中只做刷新,不做重资源初始化
## 常见错误
- Key 不存在却未做兜底
- 资源服务未注册时依赖资源路径表

View File

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

View File

@ -0,0 +1,103 @@
# Procedure
## 模块概述
Procedure 模块用于组织游戏主流程,如启动、登录、主城、战斗、结算等状态切换。它以 `ProcedureBase` 为模板方法基类,把生命周期拆成初始化、进入、离开、更新、销毁。
## 快速开始
1. 挂载 `ProcedureComponent`
2. 定义多个继承 `ProcedureBase` 的流程
3. 调用 `InitializeProcedure`
4. 通过 `SwitchProcedure<T>()` 切换
## 架构说明
```text
ProcedureComponent
└─ ProcedureService
├─ IProcedure
└─ ProcedureBase
```
## 核心类与接口
### `IProcedureService`
公开能力:
- `CurrentProcedureType`
- `InitializeProcedure(...)`
- `ClearAllProcedures()`
- `ContainsProcedure(Type procedureType)`
- `TrySwitchProcedure(Type procedureType)`
### `ProcedureBase`
生命周期模板:
- `OnInit()`
- `OnEnter()`
- `OnLeave()`
- `OnUpdate()`
- `OnDestroy()`
## API 参考
### `InitializeProcedure(IEnumerable<IProcedure> availableProcedures, Type defaultProcedureType)`
- 必填参数:`availableProcedures`
- 必填参数:`defaultProcedureType`
- 返回值:无
### `TrySwitchProcedure(Type procedureType)`
- 必填参数:`procedureType`
- 返回值:`bool`
### `CurrentProcedureType`
- 返回值:`Type`
## 完整使用示例
```csharp
using System;
using AlicizaX;
public sealed class BootProcedure : ProcedureBase
{
protected override void OnEnter()
{
SwitchProcedure<LoginProcedure>();
}
}
public sealed class LoginProcedure : ProcedureBase
{
protected override void OnEnter()
{
Log.Info("Enter LoginProcedure");
}
}
public sealed class ProcedureExample
{
public void Initialize()
{
GameApp.Procedure.InitializeProcedure(
new IProcedure[] { new BootProcedure(), new LoginProcedure() },
typeof(BootProcedure));
}
}
```
## 最佳实践
- 一个流程只负责一个清晰状态
- 初始化逻辑放 `OnInit`,进入/退出逻辑放 `OnEnter` / `OnLeave`
## 常见错误
- 未初始化就切换流程
- 把长时间并行任务塞入流程本身

View File

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

View File

@ -0,0 +1,673 @@
# Resource
## 模块概述
Resource 模块基于 YooAsset 封装了资源包初始化、版本管理、资源查询、同步/异步加载、实例化、缓存回收与低内存处理能力。
它是多个模块的底层依赖:
- `UI`:加载窗口和 Widget 预制体
- `Audio`:加载音频资源
- `Localization`:加载语言表
- `GameObjectPool`:加载池对象原始 prefab
- `Scene`:主场景与附加场景的资源加载链路
从当前实现来看,`ResourceService` 还额外提供了:
- 多包管理
- 同一路径并发加载合并
- 资源对象池缓存
- 低内存时统一回收入口
- 下载、版本、清单更新能力
## 快速开始
### 最少步骤
1. 在场景中挂载 `ResourceComponent`
2. 配置 `PlayMode`、默认包名和解密服务名
3. 游戏启动时调用 `InitPackageAsync`
4. 通过 `GameApp.Resource``AppServices.Require<IResourceService>()` 加载资源
### 最小示例
```csharp
using AlicizaX;
using UnityEngine;
public sealed class ResourceQuickStart : MonoBehaviour
{
private async void Start()
{
await GameApp.Resource.InitPackageAsync();
Texture2D icon = await GameApp.Resource.LoadAssetAsync<Texture2D>("UI/Common/Icon");
Debug.Log(icon != null);
}
}
```
## 架构说明
```text
ResourceComponent
└─ ResourceService
├─ YooAsset PackageMap
├─ AssetInfo Cache
├─ AssetObject Pool
├─ Loading Operation Map
├─ Download / Version / Manifest
└─ ResourceExtComponent / AssetsReference
```
### 关键协作关系
- `ResourceComponent`:负责注册服务、配置运行模式并接管低内存回收节奏
- `ResourceService`:负责包初始化、加载、缓存和释放
- `AssetsReference`:负责把实例对象与源资源句柄关联起来,在对象销毁时自动释放源资源引用
- `ResourceExtComponent`:负责追踪资源绑定目标并分帧回收无引用资源
### 运行模式
当前实现支持以下 `PlayMode`
- `EditorSimulateMode`
- `OfflinePlayMode`
- `HostPlayMode`
- `WebPlayMode`
不同模式决定初始化参数:
- **EditorSimulateMode**:编辑器模拟构建目录
- **OfflinePlayMode**:本地内置资源
- **HostPlayMode**:内置资源 + 缓存 + 远端下载
- **WebPlayMode**Web 环境资源拉取方式
### 并发加载合并机制
`ResourceService` 内部使用 `_assetLoadingOperations` 合并同一路径的并发加载请求。
这意味着:
- 多个系统同时加载同一个资源时,不会重复发起多次底层加载
- 后来的请求会等待第一条加载链路完成,再复用结果
这对 UI 和公共图集资源特别有价值。
## 核心类与接口
### `IResourceService`
该接口同时覆盖:
- 包初始化
- 包版本与清单管理
- 资源存在性检查
- 同步/异步加载
- 场景对象实例化
- 缓存清理
- 低内存回收
### `ResourceComponent`
它是 Resource 模块在场景中的入口组件,主要职责:
- 注册 `ResourceService`
- 配置默认包名 `PackageName`
- 设置运行模式 `PlayMode`
- 设置解密服务名 `decryptionServices`
- 设置资源对象池参数
- 接管 `Application.lowMemory` 事件
### `ResourceService`
从当前实现看,`ResourceService` 维护以下关键状态:
- `DefaultPackageName`
- `PlayMode`
- `PackageMap`
- `_assetInfoMap`
- `_assetLoadingOperations`
- `_assetPool`
### `AssetsReference`
这是实例对象与源资源句柄的桥接组件。
作用:
- 当你通过 `LoadGameObject` / `LoadGameObjectAsync` 实例化资源时
- 框架会在实例对象上自动挂一个 `AssetsReference`
- 当该实例对象销毁时,对应源资源引用会自动 `UnloadAsset`
这就是为什么:
- `LoadGameObject` 返回的实例对象通常不需要你手动 `UnloadAsset`
### `ResourceExtComponent`
主要用于:
- 追踪已绑定给 UI、Sprite 或其他目标对象的资源
- 自动清理已经失去引用的资源包装对象
- 以分帧方式做回收,降低一次性遍历成本
## API 参考
以下内容按使用频率分组说明。
### 一、初始化与运行配置
#### `void Initialize()`
- 参数:无
- 返回值:无
- 说明:初始化 YooAsset、默认包与资产池
- 备注:通常由 `ResourceComponent.Start()` 自动调用
#### `UniTask<bool> InitPackageAsync(string packageName = "", string hostServerURL = "", string fallbackHostServerURL = "")`
- 可选参数:`packageName`
- 可选参数:`hostServerURL`
- 可选参数:`fallbackHostServerURL`
- 返回值:`UniTask<bool>`
说明:
- 初始化指定资源包
- 如果 `packageName` 为空,则使用 `DefaultPackageName`
- 在 Host/Web 模式下通常需要传入远端地址
异常与边界:
- 如果同一个包正在初始化或已成功初始化,会记录错误并直接返回失败结果
- 初始化失败时任务会抛出异常
#### `string DefaultPackageName { get; set; }`
- 说明:默认资源包名
- 推荐:整个项目统一默认包名约定
#### `EPlayMode PlayMode { get; set; }`
- 说明:资源系统运行模式
- 注意Editor 与真机配置往往不同
#### `string DecryptionServices { get; set; }`
- 说明:解密服务类型名
- 注意:该值应是可被反射创建的类型全名
#### `bool AutoUnloadBundleWhenUnused { get; set; }`
- 说明:初始化参数中的自动卸载选项
### 二、版本与下载管理
#### `string GetPackageVersion(string customPackageName = "")`
- 可选参数:`customPackageName`
- 返回值:包版本字符串
#### `RequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks = false, int timeout = 60, string customPackageName = "")`
- 可选参数:`appendTimeTicks`
- 可选参数:`timeout`
- 可选参数:`customPackageName`
- 返回值:`RequestPackageVersionOperation`
#### `UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion, int timeout = 60, string customPackageName = "")`
- 必填参数:`packageVersion`
- 可选参数:`timeout`
- 可选参数:`customPackageName`
- 返回值:`UpdatePackageManifestOperation`
#### `ResourceDownloaderOperation CreateResourceDownloader(string customPackageName = "")`
- 可选参数:`customPackageName`
- 返回值:`ResourceDownloaderOperation`
说明:
- 会使用当前 `DownloadingMaxNum``FailedTryAgain`
### 三、资源查询
#### `HasAssetResult HasAsset(string location, string packageName = "")`
- 必填参数:`location`
- 可选参数:`packageName`
- 返回值:`HasAssetResult`
说明:
- 用于判断资源是否存在、是否在本地、是否需要远端下载
注意:
- 如果 `location` 为空会抛异常
#### `bool CheckLocationValid(string location, string packageName = "")`
- 必填参数:`location`
- 可选参数:`packageName`
- 返回值:`bool`
#### `AssetInfo GetAssetInfo(string location, string packageName = "")`
- 必填参数:`location`
- 可选参数:`packageName`
- 返回值:`AssetInfo`
说明:
- 内部带有 `_assetInfoMap` 缓存
- 同一路径重复获取成本较低
### 四、同步加载
#### `T LoadAsset<T>(string location, string packageName = "") where T : UnityEngine.Object`
- 必填参数:`location`
- 可选参数:`packageName`
- 返回值:`T`
- 泛型约束:`T : UnityEngine.Object`
说明:
- 同步加载资源
- 首次加载会进入资源池缓存
- 重复获取相同资源时会优先从 `_assetPool` 中复用
#### `GameObject LoadGameObject(string location, Transform parent = null, string packageName = "")`
- 必填参数:`location`
- 可选参数:`parent`
- 可选参数:`packageName`
- 返回值:`GameObject`
说明:
- 同步加载 prefab 并实例化
- 实例对象会自动挂 `AssetsReference`
- 销毁实例时会自动释放源资源引用
### 五、异步加载
#### `UniTask<T> LoadAssetAsync<T>(string location, CancellationToken cancellationToken = default, string packageName = "") where T : UnityEngine.Object`
- 必填参数:`location`
- 可选参数:`cancellationToken`
- 可选参数:`packageName`
- 返回值:`UniTask<T>`
#### `UniTask<GameObject> LoadGameObjectAsync(string location, Transform parent = null, CancellationToken cancellationToken = default, string packageName = "")`
- 必填参数:`location`
- 可选参数:`parent`
- 可选参数:`cancellationToken`
- 可选参数:`packageName`
- 返回值:`UniTask<GameObject>`
### 六、回调式加载
#### `UniTask LoadAssetAsync(string location, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData, string packageName = "")`
#### `UniTask LoadAssetAsync(string location, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData, string packageName = "")`
`LoadAssetCallbacks` 中的回调签名:
- 成功:`(string assetName, object asset, float duration, object userData)`
- 失败:`(string assetName, LoadResourceStatus status, string errorMessage, object userData)`
- 进度:`(string assetName, float progress, object userData)`
适合:
- 旧式回调链
- 想同时观察进度与错误
- 不方便直接 `await` 的场景
### 七、句柄接口
#### `AssetHandle LoadAssetSyncHandle<T>(string location, string packageName = "") where T : UnityEngine.Object`
#### `AssetHandle LoadAssetAsyncHandle<T>(string location, string packageName = "") where T : UnityEngine.Object`
适合:
- 需要直接管理底层句柄
- 需要和 YooAsset 句柄 API 配合
### 八、释放与回收
#### `void UnloadAsset(object asset)`
- 必填参数:`asset`
- 返回值:无
说明:
- 本质上是把资源对象从 `_assetPool``Unspawn`
#### `void UnloadUnusedAssets()`
- 返回值:无
说明:
- 释放资源对象池中未使用的对象
- 并对所有已成功初始化的包执行 `UnloadUnusedAssetsAsync`
#### `void ForceUnloadAllAssets()`
- 返回值:无
说明:
- 强制卸载所有资源
- WebGL 下会直接警告并退出
#### `void ForceUnloadUnusedAssets(bool performGCCollect)`
- 必填参数:`performGCCollect`
- 返回值:无
说明:
- 委托给 `ResourceComponent` 控制实际的系统资源回收时机
## 常见用法
### 1. 初始化默认包
```csharp
using AlicizaX;
using AlicizaX.Resource.Runtime;
using UnityEngine;
public sealed class ResourceInitExample : MonoBehaviour
{
private async void Start()
{
bool ok = await GameApp.Resource.InitPackageAsync();
Debug.Log($"Init default package success: {ok}");
}
}
```
### 2. 初始化远端包
```csharp
using AlicizaX;
using UnityEngine;
public sealed class HostModeInitExample : MonoBehaviour
{
private async void Start()
{
await GameApp.Resource.InitPackageAsync(
packageName: "DefaultPackage",
hostServerURL: "https://cdn.example.com/game",
fallbackHostServerURL: "https://backup.example.com/game");
}
}
```
### 3. 同步加载配置资源
```csharp
using AlicizaX;
using UnityEngine;
public sealed class SyncLoadExample : MonoBehaviour
{
private void Start()
{
TextAsset config = GameApp.Resource.LoadAsset<TextAsset>("Config/GameBalance");
Debug.Log(config != null ? config.text : "Config missing");
}
}
```
### 4. 异步加载图片资源
```csharp
using AlicizaX;
using UnityEngine;
public sealed class AsyncLoadExample : MonoBehaviour
{
private async void Start()
{
Sprite sprite = await GameApp.Resource.LoadAssetAsync<Sprite>("UI/Common/Atlas/Icon_Star");
Debug.Log(sprite != null);
}
}
```
### 5. 加载并实例化 GameObject
```csharp
using AlicizaX;
using UnityEngine;
public sealed class InstantiateExample : MonoBehaviour
{
private GameObject _hero;
private async void Start()
{
_hero = await GameApp.Resource.LoadGameObjectAsync("Character/Hero.prefab", transform);
}
private void OnDestroy()
{
if (_hero != null)
{
Destroy(_hero);
}
}
}
```
说明:
- 这里不需要对 `_hero` 再调用 `UnloadAsset`
- 销毁实例时 `AssetsReference` 会自动释放源资源引用
### 6. 使用回调式加载并监听进度
```csharp
using AlicizaX;
using AlicizaX.Resource.Runtime;
using UnityEngine;
public sealed class CallbackLoadExample : MonoBehaviour
{
private async void Start()
{
var callbacks = new LoadAssetCallbacks(
(assetName, asset, duration, userData) =>
{
Debug.Log($"Load success: {assetName}, duration: {duration:F3}s");
},
(assetName, status, errorMessage, userData) =>
{
Debug.LogError($"Load failed: {assetName}, {status}, {errorMessage}");
},
(assetName, progress, userData) =>
{
Debug.Log($"Progress {assetName}: {progress:P0}");
});
await GameApp.Resource.LoadAssetAsync(
"UI/Common/Icon",
priority: 0,
loadAssetCallbacks: callbacks,
userData: null);
}
}
```
### 7. 下载资源版本并更新清单
```csharp
using AlicizaX;
using UnityEngine;
public sealed class UpdateManifestExample : MonoBehaviour
{
private async void Start()
{
var versionOp = GameApp.Resource.RequestPackageVersionAsync();
await versionOp.ToUniTask();
if (versionOp.Status == YooAsset.EOperationStatus.Succeed)
{
string version = versionOp.PackageVersion;
var manifestOp = GameApp.Resource.UpdatePackageManifestAsync(version);
await manifestOp.ToUniTask();
Debug.Log($"Manifest updated to: {version}");
}
}
}
```
### 8. 创建下载器
```csharp
using AlicizaX;
using UnityEngine;
public sealed class DownloaderExample : MonoBehaviour
{
private async void Start()
{
var downloader = GameApp.Resource.CreateResourceDownloader();
downloader.BeginDownload();
await downloader.ToUniTask();
Debug.Log($"Download status: {downloader.Status}");
}
}
```
## 运行行为细节
### 1. 重复加载同一路径会优先复用缓存
当前实现通过 `_assetPool` 保存 `AssetObject`,同一路径的资源会复用池内对象。
好处:
- 减少重复加载
- 降低频繁生成/销毁底层句柄的开销
### 2. 并发同路径加载会合并请求
如果同一路径资源正在加载中:
- 后续请求不会重复发起底层加载
- 会等待首个请求完成后再复用结果
### 3. `LoadGameObject``LoadAsset<T>` 的释放语义不同
#### `LoadAsset<T>`
- 返回的是资源对象本身
- 如有需要可以显式 `UnloadAsset(asset)`
#### `LoadGameObject`
- 返回的是实例化后的场景对象
- 源 prefab 资源句柄通过 `AssetsReference` 绑定到实例对象
- 通常直接 `Destroy(instance)` 即可
### 4. 低内存行为
触发 `OnLowMemory()` 时:
- 会调用 `_forceUnloadUnusedAssetsAction`
- 实际清理由 `ResourceComponent` 驱动
### 5. `AssetInfo` 有内部缓存
多次 `GetAssetInfo` 会命中 `_assetInfoMap`
适合:
- 频繁查询资源合法性
- UI 打开前做路径校验
### 6. 失败行为
以下情况通常会导致异常或错误日志:
- 资源路径为空
- 包不存在
- 资源定位无效
- 初始化失败
## 最佳实践
- 统一资源路径规范,避免大小写和目录命名混乱
- 默认优先异步加载
- 把“包初始化 / 版本更新 / 资源下载 / 资源使用”分成不同阶段处理
- UI、音频、图集等高复用资源尽量走缓存复用
- 对需要长期驻留的资源,业务层要明确生命周期,不要频繁反复加载
## 常见错误
### 1. 包未初始化就加载资源
现象:
- 资源查找失败
- 返回空对象或直接异常
规避:
- 确保启动流程中先执行 `InitPackageAsync`
### 2. 默认包名与实际包名不一致
现象:
- 路径正确但查不到资源
规避:
- 统一 `DefaultPackageName`
- 多包场景显式传入 `packageName`
### 3. 手动 `UnloadAsset` 已实例化场景对象
现象:
- 语义不清晰
- 可能导致资源生命周期混乱
规避:
- `LoadGameObject` 返回的实例优先 `Destroy`
### 4. 解密服务类型名错误
现象:
- 初始化时反射失败
规避:
- `DecryptionServices` 必须是可反射创建的完整类型名
## 性能注意事项
- 避免在主线程大量同步加载
- 常用资源优先缓存复用
- 合理设置:
- `AssetAutoReleaseInterval`
- `AssetCapacity`
- `AssetExpireTime`
- `AssetPriority`
- 高并发异步加载时,优先复用路径和包配置,发挥内部合并机制优势

View File

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

View File

@ -0,0 +1,477 @@
# Scene
## 模块概述
Scene 模块负责:
- 主场景加载
- Additive 子场景加载
- 延迟激活与解除挂起
- 子场景卸载
- 主场景状态追踪
- 场景作用域Scene Scope建立与重置
它不是 Unity 默认 `SceneManager` 的简单封装,而是把场景切换与框架服务作用域绑定在一起。
这意味着:
- **加载主场景时,会重置 Scene Scope**
- **加载 Additive 子场景时,不会重置主场景状态**
- **主场景和子场景在框架内是两套不同语义**
## 快速开始
### 最少步骤
1. 在场景中挂载 `SceneComponent`
2. 确保 `ResourceComponent` 已可用
3. 通过 `GameApp.Scene.LoadSceneAsync(...)` 加载场景
4. 如需卸载 Additive 场景,调用 `UnloadAsync(...)`
### 最小示例
```csharp
using AlicizaX;
using UnityEngine.SceneManagement;
public sealed class SceneQuickStart
{
public async void Load()
{
await GameApp.Scene.LoadSceneAsync("Scene/Battle", LoadSceneMode.Single);
}
}
```
## 架构说明
```text
SceneComponent
└─ SceneService
└─ SceneDomainStateService
├─ CurrentMainSceneName
├─ CurrentMainSceneHandle
├─ SubScene Map
└─ Handling Scene Set
```
### 关键协作关系
- `SceneComponent`:注册 `SceneService` 并确保 Scene Scope 存在
- `SceneService`:处理加载、激活、卸载与状态切换
- `SceneDomainStateService`:记录当前主场景、子场景和处理中场景
- `IResourceService`:主场景切换完成后触发资源回收
### 主场景与子场景的区别
#### 主场景Main Scene
- 通过 `LoadSceneMode.Single` 加载
- 加载前会重置 Scene Scope
- 加载完成后更新 `CurrentMainSceneName`
- 切换完成后会触发一次资源回收
#### 子场景Sub Scene / Additive
- 通过 `LoadSceneMode.Additive` 加载
- 记录在 `_subScenes` 字典中
- 可通过 `UnloadAsync(location)` 卸载
## 核心类与接口
### `ISceneService`
公开能力:
- `CurrentMainSceneName`
- `LoadSceneAsync(...)`
- `LoadScene(...)`
- `ActivateScene(string location)`
- `UnSuspend(string location)`
- `IsMainScene(string location)`
- `UnloadAsync(string location, Action<float> progressCallBack = null)`
- `Unload(string location, Action callBack = null, Action<float> progressCallBack = null)`
- `IsContainScene(string location)`
### `ISceneStateService`
偏状态查询接口,主要用于:
- 查询当前主场景
- 查询某个场景是否已记录在当前 Scene Scope 中
### `SceneDomainStateService`
当前实现中负责维护:
- `CurrentMainSceneName`
- `CurrentMainSceneHandle`
- `_subScenes`
- `_handlingScenes`
用途:
- 避免同一场景重复并发加载/卸载
- 为 `IsContainScene` / `IsMainScene` 提供判断基础
## API 参考
### 一、场景加载
#### `UniTask<Scene> LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, uint priority = 100, bool gcCollect = true, Action<float> progressCallBack = null)`
- 必填参数:`location`
- 可选参数:`sceneMode`
- 可选参数:`suspendLoad`
- 可选参数:`priority`
- 可选参数:`gcCollect`
- 可选参数:`progressCallBack`
- 返回值:`UniTask<UnityEngine.SceneManagement.Scene>`
参数说明:
- `location`:场景资源定位地址
- `sceneMode``Single` 或 `Additive`
- `suspendLoad`:是否挂起加载后的激活
- `priority`:加载优先级
- `gcCollect`:主场景切换后是否执行资源回收
- `progressCallBack`:加载进度回调
行为说明:
- `Single`:会重置当前 Scene Scope
- `Additive`:会作为子场景注册
- 如果同一场景正在处理,当前实现会记录错误并返回默认值
#### `void LoadScene(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, uint priority = 100, Action<Scene> callBack = null, bool gcCollect = true, Action<float> progressCallBack = null)`
- 注意:这个方法**不是同步加载**
- 本质上仍是异步加载,只是使用回调而不是 `await`
推荐:
- 新代码优先使用 `LoadSceneAsync`
### 二、场景激活与挂起
#### `bool ActivateScene(string location)`
- 必填参数:`location`
- 返回值:`bool`
说明:
- 对应场景已被挂起时,尝试激活它
- 可用于 `suspendLoad = true` 的场景
#### `bool UnSuspend(string location)`
- 必填参数:`location`
- 返回值:`bool`
说明:
- 解除场景挂起
- 语义接近 `ActivateScene`
### 三、场景查询
#### `bool IsMainScene(string location)`
- 必填参数:`location`
- 返回值:`bool`
说明:
- 判断给定场景是否为当前主场景
- 内部结合 `SceneDomainStateService``SceneManager.GetActiveScene()` 做判断
#### `bool IsContainScene(string location)`
- 必填参数:`location`
- 返回值:`bool`
说明:
- 判断当前主场景或子场景列表中是否包含该场景
#### `string CurrentMainSceneName`
- 返回值:主场景名
### 四、场景卸载
#### `UniTask<bool> UnloadAsync(string location, Action<float> progressCallBack = null)`
- 必填参数:`location`
- 可选参数:`progressCallBack`
- 返回值:`UniTask<bool>`
说明:
- 用于卸载 Additive 子场景
- 当前实现**不用于直接卸载主场景**
#### `void Unload(string location, Action callBack = null, Action<float> progressCallBack = null)`
- 必填参数:`location`
- 可选参数:`callBack`
- 可选参数:`progressCallBack`
- 返回值:无
说明:
- 回调式异步卸载
## 常见用法
### 1. 加载主场景
```csharp
using AlicizaX;
using UnityEngine.SceneManagement;
public sealed class LoadMainSceneExample
{
public async void GoBattle()
{
await GameApp.Scene.LoadSceneAsync("Scene/Battle", LoadSceneMode.Single);
}
}
```
### 2. Additive 加载子场景
```csharp
using AlicizaX;
using UnityEngine.SceneManagement;
public sealed class AdditiveSceneExample
{
public async void OpenSubScene()
{
await GameApp.Scene.LoadSceneAsync("Scene/PhotoRoom", LoadSceneMode.Additive);
}
}
```
### 3. 卸载 Additive 子场景
```csharp
using AlicizaX;
public sealed class UnloadSubSceneExample
{
public async void CloseSubScene()
{
if (GameApp.Scene.IsContainScene("Scene/PhotoRoom"))
{
bool ok = await GameApp.Scene.UnloadAsync("Scene/PhotoRoom");
UnityEngine.Debug.Log($"Unload result: {ok}");
}
}
}
```
### 4. 带进度的场景加载
```csharp
using AlicizaX;
using UnityEngine;
using UnityEngine.SceneManagement;
public sealed class SceneProgressExample
{
public async void LoadWithProgress()
{
await GameApp.Scene.LoadSceneAsync(
"Scene/Battle",
LoadSceneMode.Single,
suspendLoad: false,
priority: 100,
gcCollect: true,
progressCallBack: progress =>
{
Debug.Log($"Scene progress: {progress:P0}");
});
}
}
```
### 5. 挂起加载后手动激活
```csharp
using AlicizaX;
using UnityEngine.SceneManagement;
public sealed class SuspendLoadExample
{
public async void LoadThenActivate()
{
await GameApp.Scene.LoadSceneAsync(
"Scene/Battle",
LoadSceneMode.Single,
suspendLoad: true);
GameApp.Scene.ActivateScene("Scene/Battle");
}
}
```
### 6. 使用回调式加载
```csharp
using AlicizaX;
using UnityEngine;
using UnityEngine.SceneManagement;
public sealed class SceneCallbackExample
{
public void LoadLobby()
{
GameApp.Scene.LoadScene(
"Scene/Lobby",
LoadSceneMode.Single,
suspendLoad: false,
priority: 100,
callBack: scene =>
{
Debug.Log($"Loaded scene: {scene.name}");
},
gcCollect: true,
progressCallBack: progress =>
{
Debug.Log($"Loading: {progress:P0}");
});
}
}
```
### 7. 查询当前主场景
```csharp
using AlicizaX;
using UnityEngine;
public sealed class SceneStateExample : MonoBehaviour
{
private void Update()
{
Debug.Log($"Main Scene: {GameApp.Scene.CurrentMainSceneName}");
}
}
```
## 运行行为细节
### 1. 主场景加载会重置 Scene Scope
这是本模块最重要的设计点之一。
当调用:
```csharp
GameApp.Scene.LoadSceneAsync("Scene/Battle", LoadSceneMode.Single)
```
内部会:
1. `Context.ResetScene()`
2. 重新注册 `SceneDomainStateService`
3. 标记新主场景进入加载中
这意味着:
- 旧的 Scene Scope 服务会被重建
- 与旧主场景强绑定的场景级服务也应重新初始化
### 2. Additive 场景不会重置主场景作用域
使用 `LoadSceneMode.Additive` 时:
- 场景会被加入 `_subScenes`
- 主场景状态保留
- 适合加载摄影间、剧情副场景、临时房间等
### 3. `UnloadAsync` 只对 Additive 子场景有效
当前实现中:
- 只有 `_subScenes` 中登记的场景才会走卸载逻辑
- 主场景切换依赖新的 `LoadScene(Single)`,而不是单独 `Unload` 主场景
### 4. 同一场景并发处理会被拦截
`SceneDomainStateService` 会使用 `_handlingScenes` 记录“正在加载/卸载”的场景。
效果:
- 避免同一路径重复加载或重复卸载
- 减少状态错乱
### 5. 主场景加载完成后会触发资源回收
当主场景切换完成后,会调用:
```csharp
Context.Require<IResourceService>().ForceUnloadUnusedAssets(gcCollect);
```
因此:
- 场景切换是资源回收的重要时间点
- `gcCollect` 参数会影响切场景后的回收强度
### 6. `LoadScene` 方法名容易误导
虽然名字像“同步加载”,但当前实现中:
- `LoadScene(...)` 仍然是异步加载
- 区别只是它通过回调返回结果,而不是 `await`
## 最佳实践
- 主场景切换统一交给流程层管理
- Additive 场景只用于临时叠加内容,不要滥用为主流程状态切换
- 若需要加载转场动画,可用 `suspendLoad = true` + 手动激活
- 场景切换后如有场景级服务初始化,放在新的 Scene Scope 生命周期里完成
## 常见错误
### 1. 试图用 `UnloadAsync` 卸载主场景
现象:
- 返回 `false` 或警告
正确方式:
- 通过加载新的 `Single` 主场景来替换
### 2. 把 `LoadScene(...)` 当同步函数使用
现象:
- 加载还没完成就执行后续依赖逻辑
规避:
- 优先使用 `LoadSceneAsync(...)`
- 或把后续逻辑写入回调中
### 3. 重复 Additive 加载同一场景
现象:
- 异步版可能直接抛异常
- 回调版会记录警告
规避:
- 在加载前先用 `IsContainScene(location)` 做检查
## 性能注意事项
- 场景切换本身是重量级操作,不要把短生命周期面板式内容做成 Additive 场景
- 进度回调每帧执行UI 刷新时应尽量轻量
- 主场景切换后伴随资源回收,切场景阶段要预估回收开销和 GC 波动

View File

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

View File

@ -0,0 +1,672 @@
# Timer
## 模块概述
Timer 模块提供统一定时器服务,适合处理:
- 延时执行
- 循环轮询
- UI 倒计时
- 技能延时结算
- 超时控制
- 轻量轮询逻辑
它由 `TimerComponent` 注册 `TimerService`,并通过 `GameApp.Timer``AppServices.Require<ITimerService>()` 暴露给业务层。
从实现上看,`TimerService` 使用时间轮来管理定时器,重点优化的是:
- 大量定时器的调度效率
- 低 GC 的回调执行
- 支持缩放时间和非缩放时间两套时间基准
## 快速开始
### 最少步骤
1. 在场景中挂载 `TimerComponent`
2. 调用 `GameApp.Timer.AddTimer(...)`
3. 保存返回的 `timerId`
4. 在对象销毁或逻辑结束时调用 `RemoveTimer(timerId)`
### 最小示例
```csharp
using AlicizaX;
using UnityEngine;
public sealed class TimerQuickStart : MonoBehaviour
{
private int _timerId;
private void Start()
{
_timerId = GameApp.Timer.AddTimer(OnTick, 1f, true);
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_timerId);
}
private void OnTick()
{
Debug.Log("Tick");
}
}
```
## 架构说明
```text
TimerComponent
└─ TimerService
├─ TimerHandler
├─ TimerHandlerNoArgs
├─ TimerGenericInvokerCache<T>
└─ HierarchicalTimeWheel
```
### 关键协作关系
- `TimerComponent`:负责在场景中注册 `TimerService`
- `TimerService`:真正执行定时调度
- `ITimerService`:业务层使用的统一接口
- `GameApp.Timer`:高频调用入口
### 时间基准
Timer 模块支持两种时间基准:
- **缩放时间**:使用 `Time.time`
- **非缩放时间**:使用 `Time.unscaledTime`
这由 `isUnscaled` 参数控制:
- `false`:受 `Time.timeScale` 影响
- `true`:不受 `Time.timeScale` 影响
## 核心类与接口
### `ITimerService`
公开能力:
- `AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args)`
- `AddTimer(TimerHandlerNoArgs callback, float time, bool isLoop = false, bool isUnscaled = false)`
- `AddTimer<T>(Action<T> callback, T arg, float time, bool isLoop = false, bool isUnscaled = false)`
- `Stop(int timerId)`
- `Resume(int timerId)`
- `IsRunning(int timerId)`
- `GetLeftTime(int timerId)`
- `Restart(int timerId)`
- `RemoveTimer(int timerId)`
- `RemoveAllTimer()`
### `TimerHandler`
定义:
```csharp
public delegate void TimerHandler(params object[] args);
```
适合:
- 参数数量不固定
- 通用回调
- 快速搭建原型
### `TimerHandlerNoArgs`
定义:
```csharp
public delegate void TimerHandlerNoArgs();
```
适合:
- 无参延时执行
- 最常见的循环 tick
### 泛型 `AddTimer<T>`
适合:
- 单参数且类型明确的回调
- 希望避免 `object[]` 拆装箱和手动转换
## API 参考
### `int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args)`
- 必填参数:`callback`
- 必填参数:`time`
- 可选参数:`isLoop`
- 可选参数:`isUnscaled`
- 可选参数:`args`
- 返回值:`timerId`
说明:
- 注册一个支持参数数组的定时器
- `time` 为延迟秒数
- `isLoop = true` 时会按相同间隔循环触发
适合:
- 参数个数可变
- 临时逻辑
- 不想额外声明泛型回调的场景
### `int AddTimer(TimerHandlerNoArgs callback, float time, bool isLoop = false, bool isUnscaled = false)`
- 必填参数:`callback`
- 必填参数:`time`
- 可选参数:`isLoop`
- 可选参数:`isUnscaled`
- 返回值:`timerId`
说明:
- 注册无参定时器
- 是最常用、最简洁的用法
### `int AddTimer<T>(Action<T> callback, T arg, float time, bool isLoop = false, bool isUnscaled = false)`
- 必填参数:`callback`
- 必填参数:`arg`
- 必填参数:`time`
- 可选参数:`isLoop`
- 可选参数:`isUnscaled`
- 返回值:`timerId`
- 泛型约束:无额外约束
说明:
- 注册单参数强类型定时器
- 比 `object[] args` 更清晰、更安全
### `void Stop(int timerId)`
- 必填参数:`timerId`
- 返回值:无
说明:
- 把指定定时器标记为停止运行
- 对无效 `timerId` 为安全无操作
### `void Resume(int timerId)`
- 必填参数:`timerId`
- 返回值:无
说明:
- 恢复一个已停止的定时器
- 对无效 `timerId` 为安全无操作
### `bool IsRunning(int timerId)`
- 必填参数:`timerId`
- 返回值:`bool`
说明:
- 返回该定时器当前是否处于运行状态
- 对无效 `timerId` 返回 `false`
### `float GetLeftTime(int timerId)`
- 必填参数:`timerId`
- 返回值:剩余秒数
说明:
- 返回定时器剩余触发时间
- 对无效 `timerId` 返回 `0`
### `void Restart(int timerId)`
- 必填参数:`timerId`
- 返回值:无
说明:
- 重新调度该定时器
- 对无效 `timerId` 为安全无操作
### `void RemoveTimer(int timerId)`
- 必填参数:`timerId`
- 返回值:无
说明:
- 从系统中移除指定定时器
- 是最推荐的结束方式
### `void RemoveAllTimer()`
- 返回值:无
说明:
- 清空当前全部定时器
- 通常只建议在服务销毁、场景彻底重置或特殊测试环境下使用
## 常见用法
### 1. 一次性延时执行
```csharp
using AlicizaX;
using UnityEngine;
public sealed class DelayExample : MonoBehaviour
{
private int _delayTimer;
private void Start()
{
_delayTimer = GameApp.Timer.AddTimer(OnDelayFinish, 2f);
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_delayTimer);
}
private void OnDelayFinish()
{
Debug.Log("2 seconds later");
}
}
```
### 2. 循环计时器
```csharp
using AlicizaX;
using UnityEngine;
public sealed class LoopTimerExample : MonoBehaviour
{
private int _loopTimer;
private int _counter;
private void Start()
{
_loopTimer = GameApp.Timer.AddTimer(OnLoop, 0.5f, true);
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_loopTimer);
}
private void OnLoop()
{
_counter++;
Debug.Log($"Loop count: {_counter}");
if (_counter >= 5)
{
GameApp.Timer.RemoveTimer(_loopTimer);
}
}
}
```
### 3. 带参数的定时器
```csharp
using AlicizaX;
using UnityEngine;
public sealed class TimerArgsExample : MonoBehaviour
{
private int _timerId;
private void Start()
{
_timerId = GameApp.Timer.AddTimer(OnRewardDelay, 3f, false, false, "Gold", 100);
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_timerId);
}
private void OnRewardDelay(params object[] args)
{
string rewardType = (string)args[0];
int amount = (int)args[1];
Debug.Log($"Reward => {rewardType}, amount => {amount}");
}
}
```
### 4. 泛型参数定时器
```csharp
using AlicizaX;
using UnityEngine;
public sealed class GenericTimerExample : MonoBehaviour
{
private int _timerId;
private void Start()
{
_timerId = GameApp.Timer.AddTimer<int>(OnDamageDelay, 200, 1.5f);
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_timerId);
}
private void OnDamageDelay(int damage)
{
Debug.Log($"Delayed damage: {damage}");
}
}
```
### 5. 不受暂停影响的 UI 倒计时
```csharp
using AlicizaX;
using UnityEngine;
public sealed class UnscaledCountdownExample : MonoBehaviour
{
private int _timerId;
private float _left = 5f;
private void Start()
{
_timerId = GameApp.Timer.AddTimer(OnTick, 1f, true, true);
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_timerId);
}
private void OnTick()
{
_left -= 1f;
Debug.Log($"Countdown: {_left}");
if (_left <= 0f)
{
GameApp.Timer.RemoveTimer(_timerId);
}
}
}
```
### 6. 查询剩余时间
```csharp
using AlicizaX;
using UnityEngine;
public sealed class LeftTimeExample : MonoBehaviour
{
private int _timerId;
private void Start()
{
_timerId = GameApp.Timer.AddTimer(OnFinish, 10f);
}
private void Update()
{
float left = GameApp.Timer.GetLeftTime(_timerId);
Debug.Log($"Left: {left:F2}s");
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_timerId);
}
private void OnFinish()
{
Debug.Log("Finished");
}
}
```
### 7. 暂停、恢复与重启
```csharp
using AlicizaX;
using UnityEngine;
public sealed class PauseResumeTimerExample : MonoBehaviour
{
private int _timerId;
private void Start()
{
_timerId = GameApp.Timer.AddTimer(OnTick, 1f, true);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.S))
{
GameApp.Timer.Stop(_timerId);
}
if (Input.GetKeyDown(KeyCode.R))
{
GameApp.Timer.Resume(_timerId);
}
if (Input.GetKeyDown(KeyCode.T))
{
GameApp.Timer.Restart(_timerId);
}
}
private void OnDestroy()
{
GameApp.Timer.RemoveTimer(_timerId);
}
private void OnTick()
{
Debug.Log("Running timer");
}
}
```
### 8. 组件生命周期绑定
```csharp
using AlicizaX;
using UnityEngine;
public sealed class SafeTimerOwner : MonoBehaviour
{
private int _timerId = -1;
private void OnEnable()
{
_timerId = GameApp.Timer.AddTimer(OnHeartbeat, 2f, true);
}
private void OnDisable()
{
if (_timerId > 0)
{
GameApp.Timer.RemoveTimer(_timerId);
_timerId = -1;
}
}
private void OnHeartbeat()
{
Debug.Log("Heartbeat");
}
}
```
## 运行行为细节
这一部分基于当前 `TimerService` 实现整理,适合开发时理解边界行为。
### 1. 无效 `timerId` 的行为
以下方法对无效 `timerId` 都是安全的:
- `Stop`
- `Resume`
- `Restart`
- `RemoveTimer`
对应返回值行为:
- `IsRunning` 返回 `false`
- `GetLeftTime` 返回 `0`
### 2. 非循环定时器会在触发后自动移除
一次性定时器执行回调后,不需要手动调用 `RemoveTimer`
但如果组件生命周期不确定,仍建议在 `OnDestroy` / `OnDisable` 中做防守式移除。
### 3. 回调异常会被捕获
`TimerService` 内部会捕获回调异常并记录日志,不会因为单个定时器异常直接打断整个调度链。
### 4. `Stop` / `Resume` 的语义更像“运行标记”
源码层面:
- `Stop(timerId)` 只是把定时器标记为 `IsRunning = false`
- `Resume(timerId)` 只是把它重新标记为 `true`
注意点:
- 如果定时器已经到达触发时刻,但当时处于 `Stop` 状态,那么该次调度不会执行
- 对循环定时器来说,如果它在应触发的那一刻是停止状态,也不会自动重新挂回时间轮
因此更稳妥的经验是:
- **短暂停顿并在触发前恢复**:可以用 `Stop` / `Resume`
- **需要明确重新开始计时**:优先用 `Restart`
### 5. `Restart` 对循环定时器更直观
当前实现里:
- 循环定时器的 `Interval = time`
- 非循环定时器的 `Interval = 0`
这意味着:
- 对循环定时器调用 `Restart`,会从当前时刻重新按原间隔开始计时
- 对非循环定时器调用 `Restart`,会因为内部间隔是 `0`,变成“下一次 Tick 几乎立刻触发”
所以建议:
- **循环定时器**:可以使用 `Restart`
- **一次性定时器**:如果要重新延时,直接重新创建一个新的 timer 更清晰
## 最佳实践
### 推荐做法
- 把 `timerId` 与对象生命周期绑定
- UI 倒计时优先用 `isUnscaled = true`
- 对单参数回调优先使用泛型重载
- 对复杂业务优先在回调中触发业务方法,而不是把整段逻辑都堆进匿名函数
### 推荐封装方式
如果你的项目里大量使用定时器,建议封装一层:
- `StartOnce(float delay, Action action)`
- `StartLoop(float interval, Action action)`
- `StopAndClear(ref int timerId)`
这样可以减少重复样板代码和漏删问题。
## 常见错误
### 1. 循环定时器不移除
现象:
- 组件销毁后仍继续运行
规避:
- 在 `OnDisable``OnDestroy` 中移除
### 2. 暂停界面仍使用缩放时间
现象:
- 游戏暂停后倒计时也停住
规避:
- UI 倒计时使用 `isUnscaled = true`
### 3. 在非循环定时器上依赖 `Restart`
现象:
- 行为不像“重新开始原延时”,而是几乎立即触发
规避:
- 直接重新创建一次性定时器
### 4. `object[] args` 中频繁装箱拆箱
现象:
- 代码可读性差
- 更容易写错类型转换
规避:
- 单参数时优先用 `AddTimer<T>`
## 性能注意事项
- 少量长生命周期定时器成本很低
- 大量高频定时器建议业务上合并
- 能用泛型单参数回调时,优先别用 `object[]`
- 大量短周期循环定时器应谨慎使用,优先考虑合并成统一更新器
## 适用场景建议
### 适合使用 Timer 模块
- 秒级倒计时
- UI 展示延迟
- 技能或状态延后执行
- 轻量循环任务
### 不适合使用 Timer 模块
- 每帧复杂逻辑
- 高频实时物理计算
- 长链路异步流程编排
这些场景更适合:
- `Update`
- `Coroutine`
- `UniTask`
- 专门的状态机/调度器

View File

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

View File

@ -0,0 +1,552 @@
# UI
## 模块概述
UI 模块负责窗口创建、资源定位、层级管理、显示/关闭、缓存、过渡动画与界面绑定代码协作。
本模块里最容易误解的一点是:
- `UIHolderObjectBase`(通常简称 **UIHolder**)不是推荐手写的业务类
- 项目中的大多数 `UIHolder` 都应通过 **UI 绑定工具自动生成**
- 业务代码通常只编写 `UIWindow<T>`、`UIWidget<T>`、`UITabWindow<T>` 这类逻辑类
换句话说:
- **UIHolder 负责“控件引用和预制体桥接”**
- **UI 逻辑类负责“界面行为和生命周期”**
## 快速开始
1. 在场景中挂载 `UIComponent`
2. 为 `UIComponent.uiRoot` 指定 UI 根预制体
3. 在 `UISettingEditorWindow` 中配置 UI 生成规则
4. 选中 UI 预制体根节点,执行 `GameObject/UI生成绑定`
5. 让生成器自动生成 `UIHolder` 类并挂回预制体
6. 在逻辑类中使用 `UIWindow<T>``UIWidget<T>`,其中 `T` 就是生成出来的 `UIHolder` 类型
## 架构说明
```text
UIComponent
└─ UIService
├─ UIBase
├─ UIWindow<T>
├─ UIWidget<T>
├─ UITabWindow<T>
├─ UIHolderObjectBase
├─ UIMetaRegistry
├─ UIResRegistry
└─ UIHolderFactory
```
### 角色分工
- `UIBase`UI 逻辑生命周期基类
- `UIWindow<T>`:顶层窗口逻辑
- `UIWidget<T>`:挂在窗口或其他 Widget 下的子部件逻辑
- `UITabWindow<T>`:支持 Tab 页懒加载与切换的窗口基类
- `UIHolderObjectBase`:预制体绑定脚本基类,负责暴露控件引用、`RectTransform`、转场播放器
- `UIHolderFactory`:根据注册信息加载预制体并创建对应 Holder
### `UIBase`、`UIHolderObjectBase`、`UIWidget<T>` 的关系
```text
UI 预制体
└─ 挂载生成的 XXXHolder : UIHolderObjectBase
UIWidget<XXXHolder> / UIWindow<XXXHolder>
通过泛型参数 T 访问 baseui
```
说明:
- `UIHolderObjectBase` 挂在预制体上,持有控件引用
- `UIWindow<T>` / `UIWidget<T>` 的泛型参数 `T` 指向该 Holder 类型
- 在逻辑类内部可以通过 `baseui` 访问生成好的控件字段
## UIHolder 的作用
`UIHolderObjectBase` 的职责不是写业务逻辑,而是充当:
- **控件引用容器**:保存按钮、文本、图片、节点等引用
- **预制体桥接层**:让 UI 逻辑层不直接依赖层级查找
- **生命周期事件承载层**:暴露 `OnWindowInitEvent`、`OnWindowAfterShowEvent` 等事件
- **转场入口**:自动寻找并驱动 `IUITransitionPlayer`
因此推荐做法是:
- 业务不手写具体 `XXXHolder`
- 由 UI 绑定工具从预制体结构自动生成
## UIHolder 自动生成工作流
### 1. 配置生成规则
先在编辑器中配置 `UIGenerateConfiguration`,核心配置包括:
- `UIPrefabRootPath`UI 预制体根目录
- `GenerateHolderCodePath`:生成代码输出目录
- `NameSpace`:生成类所在命名空间
- `LoadType``Resources` 或 `AssetBundle`
这些配置通常通过 `UISettingEditorWindow` 维护。
### 2. 按命名规则搭建 UI 预制体
生成器会扫描 UI 节点名和组件类型。例如默认规则会识别:
- `Btn` → 按钮组件
- `Text``TextMeshProUGUI`
- `Img``Image`
- `Tf``Transform`
- `Rect``RectTransform`
例如:
- `Btn#Close@`
- `Text#Title@`
- `Img#Icon@`
生成器会根据这些节点名推断字段名和字段类型。
### 3. 选中 UI 预制体根节点
支持两种常见操作方式:
- 在 Project 中选中 prefab 资源
- 或在 Prefab Mode 中编辑当前预制体
### 4. 执行绑定工具
菜单入口:
- `GameObject/UI生成绑定`
执行后生成器会:
1. 读取当前 UI 生成配置
2. 校验预制体路径是否位于配置的 UI 根目录
3. 扫描可绑定节点
4. 生成 `XXXHolder` 代码文件
5. 脚本编译后自动把生成的 `XXXHolder` 挂到目标预制体根节点
6. 自动回填对应字段引用
这意味着:
- **正常情况下不需要手动创建 Holder 脚本**
- **也不需要手工把字段拖到 Inspector**
### 5. 生成代码的结果
生成的 `UIHolder` 类本质上:
- 继承自 `UIHolderObjectBase`
- 带有 `UIResAttribute`
- 包含自动生成的控件字段
形态类似:
```csharp
using AlicizaX.UI.Runtime;
[UIRes(InventoryItemHolder.ResTag, EUIResLoadType.AssetBundle)]
public class InventoryItemHolder : UIHolderObjectBase
{
public const string ResTag = "UI/Inventory/InventoryItem.prefab";
[UnityEngine.SerializeField] private UnityEngine.UI.Button uiBtnClose;
[UnityEngine.SerializeField] private TMPro.TextMeshProUGUI uiTextTitle;
public UnityEngine.UI.Button BtnClose => uiBtnClose;
public TMPro.TextMeshProUGUI TextTitle => uiTextTitle;
}
```
> 上面是示意结构;实际字段名由生成规则决定。
## 在 `UIWidget<T>` 中如何引用生成的 UIHolder
关键点:
- `T` 就是生成工具输出的 Holder 类型
- 逻辑类不需要自己声明控件字段
- 通过 `baseui` 访问自动生成的 Holder 成员
例如:
```csharp
using AlicizaX.UI.Runtime;
using UnityEngine;
public sealed class InventoryItemWidget : UIWidget<InventoryItemHolder>
{
protected override void OnInitialize()
{
baseui.BtnClose.onClick.AddListener(OnClickClose);
}
protected override void OnOpen()
{
baseui.TextTitle.text = "Potion";
}
private void OnClickClose()
{
Close();
Destroy();
}
}
```
这里的含义是:
- `InventoryItemHolder` 由 UI 绑定工具生成
- `InventoryItemWidget` 是手写业务逻辑
- `UIWidget<InventoryItemHolder>` 把逻辑和绑定类关联起来
## 核心类与接口
### `IUIService`
负责:
- 初始化 UI 根节点
- 打开/关闭窗口
- 查询已打开窗口
- 获取层级根节点
- 注入 `ITimerService`
### `UIBase`
关键生命周期:
- `OnInitialize()`
- `OnOpen()`
- `OnClose()`
- `OnDestroy()`
- `OnUpdate()`
以及对应异步版本:
- `OnInitializeAsync()`
- `OnOpenAsync()`
- `OnCloseAsync()`
并提供:
- `CreateWidgetAsync<T>()`
- `CreateWidgetSync<T>()`
- `RemoveWidget(UIBase widget)`
### `UIWindow<T>`
适合顶层窗口,通常用于:
- 主界面
- 设置页
- 背包页
- 弹窗
常用能力:
- `CloseSelf()`
- 强制关闭
- 打开后顶层排序与层级遮挡处理
### `UIWidget<T>`
适合子部件,通常用于:
- 列表项
- 面板块
- 详情条目
- 页签子页面
公开方法:
- `Open(params object[] userDatas)`
- `Close()`
- `Destroy()`
### `UITabWindow<T>`
用于页签式窗口,支持:
- 预注册 Tab
- 按需懒加载
- `SwitchTab(int index, params object[] userDatas)`
### `UIHolderObjectBase`
核心成员:
- `Target`
- `RectTransform`
- `Visible`
- `OnWindowInitEvent`
- `OnWindowBeforeShowEvent`
- `OnWindowAfterShowEvent`
- `OnWindowBeforeClosedEvent`
- `OnWindowAfterClosedEvent`
- `OnWindowDestroyEvent`
### `UIHolderFactory`
`UIHolderFactory` 是 UI 资源实例化与 Holder 绑定的桥梁,作用是:
- 根据 `UIResRegistry` 中登记的资源信息定位 UI 预制体
- 调用 `IResourceService``Resources` 加载 UI 资源
- 实例化预制体并获取对应的 `UIHolderObjectBase`
- 把生成的 Holder 绑定到 `UIWindow<T>` / `UIWidget<T>` 对应的逻辑实例上
你通常**不会在业务层频繁直接调用它**,因为:
- 打开窗口时,`UIService` 会在内部调用 `UIHolderFactory`
- 创建 Widget 时,`UIBase.CreateWidgetAsync<T>()` / `CreateWidgetSync<T>()` 也会在内部调用它
可以把它理解为:
```text
UI 逻辑类
-> UIService / UIBase
-> UIHolderFactory
-> 加载预制体
-> 找到生成的 XXXHolder
-> 绑定到 UIWindow<T> / UIWidget<T>
```
#### 典型作用场景
1. `ShowUI<InventoryWindow>()`
- `UIService` 找到 `InventoryWindow` 对应的元数据
- `UIHolderFactory` 根据 `InventoryWindowHolder``UIResAttribute` 加载预制体
- 创建并返回 `InventoryWindowHolder`
- 把 Holder 绑定给 `InventoryWindow`
2. `CreateWidgetAsync<InventoryItemWidget>(parent)`
- `UIBase` 创建 `InventoryItemWidget` 的元数据
- `UIHolderFactory` 加载 `InventoryItemHolder` 对应的 Widget 预制体
- 把 Holder 绑定给 `InventoryItemWidget`
#### 直接调用示例
虽然业务层通常不需要直接调用,但在工具代码、调试代码或特殊预加载场景下,可以这样使用:
```csharp
using AlicizaX.UI.Runtime;
using Cysharp.Threading.Tasks;
using UnityEngine;
public sealed class UIHolderFactoryExample : MonoBehaviour
{
[SerializeField] private Transform previewRoot;
private async UniTaskVoid Start()
{
InventoryItemHolder holder = await UIHolderFactory.CreateUIHolderAsync<InventoryItemHolder>(previewRoot);
if (holder != null)
{
holder.TextName.text = "Preview Item";
holder.TextCount.text = "99";
}
}
}
```
同步版本示例:
```csharp
using AlicizaX.UI.Runtime;
using UnityEngine;
public sealed class UIHolderFactorySyncExample : MonoBehaviour
{
[SerializeField] private Transform previewRoot;
private void Start()
{
InventoryItemHolder holder = UIHolderFactory.CreateUIHolderSync<InventoryItemHolder>(previewRoot);
if (holder != null)
{
holder.TextName.text = "Sync Preview";
holder.TextCount.text = "1";
}
}
}
```
#### 注意事项
- `T` 必须是正确的生成型 `UIHolder`,且继承自 `UIHolderObjectBase`
- 对应 Holder 需要已具备 `UIResAttribute`,通常由绑定工具自动生成
- 如果资源路径错误、预制体未挂对应 Holder`UIHolderFactory` 绑定会失败
- 正常业务打开窗口和创建 Widget 时,优先走 `GameApp.UI.ShowUI<T>()`、`CreateWidgetAsync<T>()`,不建议绕过框架直接大量使用工厂
## API 参考
### `IUIService.Initialize(Transform root, bool isOrthographic)`
- 必填参数:`root`
- 必填参数:`isOrthographic`
- 返回值:无
- 说明:初始化 UI 根、Canvas、Camera 与各层级节点
### `UniTask<T> ShowUI<T>(params object[] userDatas) where T : UIBase`
- 可选参数:`userDatas`
- 返回值:`UniTask<T>`
- 泛型约束:`T : UIBase`
- 说明:异步打开窗口
- 推荐:默认优先使用该方法
### `T ShowUISync<T>(params object[] userDatas) where T : UIBase`
- 返回值:`T`
- 说明:同步打开窗口
- 注意:仅在资源已就绪时使用
### `void CloseUI<T>(bool force = false) where T : UIBase`
- 可选参数:`force`
- 返回值:无
- 说明:关闭指定窗口
### `CreateWidgetAsync<T>(Transform parent, bool visible = true) where T : UIBase`
- 必填参数:`parent`
- 可选参数:`visible`
- 返回值:`UniTask<T>`
- 泛型约束:`T : UIBase`
- 说明:从父 UI 创建 Widget
### `RemoveWidget(UIBase widget)`
- 必填参数:`widget`
- 返回值:`UniTask`
- 说明:从父 UI 中移除并销毁 Widget
## 完整使用示例
### 示例 1窗口逻辑 + 自动生成 Holder
```csharp
using AlicizaX.UI.Runtime;
using UnityEngine;
[Window(UILayer.UI, fullScreen: true, cacheTime: 10)]
public sealed class InventoryWindow : UIWindow<InventoryWindowHolder>
{
protected override async Cysharp.Threading.Tasks.UniTask OnInitializeAsync()
{
baseui.BtnClose.onClick.AddListener(CloseSelf);
InventoryItemWidget item = await CreateWidgetAsync<InventoryItemWidget>(baseui.TfContent, false);
item.Open("Potion", 10);
}
protected override void OnOpen()
{
baseui.TextTitle.text = "Inventory";
}
}
```
说明:
- `InventoryWindowHolder` 推荐由 UI 绑定工具生成
- `InventoryWindow` 由业务手写
### 示例 2Widget 使用生成的 Holder
```csharp
using AlicizaX.UI.Runtime;
using UnityEngine;
public sealed class InventoryItemWidget : UIWidget<InventoryItemHolder>
{
private string _itemName;
private int _count;
protected override void OnInitialize()
{
baseui.BtnUse.onClick.AddListener(OnClickUse);
}
protected override void OnOpen()
{
_itemName = (string)UserDatas[0];
_count = (int)UserDatas[1];
baseui.TextName.text = _itemName;
baseui.TextCount.text = _count.ToString();
}
protected override void OnClose()
{
baseui.TextName.text = string.Empty;
baseui.TextCount.text = string.Empty;
}
private void OnClickUse()
{
Debug.Log($"Use item: {_itemName}");
Close();
Destroy();
}
}
```
### 示例 3TabWindow
```csharp
using AlicizaX.UI.Runtime;
[Window(UILayer.UI, fullScreen: true)]
public sealed class SettingWindow : UITabWindow<SettingWindowHolder>
{
protected override void OnInitialize()
{
InitTabVirtuallyView<GraphicsTabWidget>(baseui.TfTabRoot);
InitTabVirtuallyView<AudioTabWidget>(baseui.TfTabRoot);
baseui.BtnGraphics.onClick.AddListener(() => SwitchTab(0));
baseui.BtnAudio.onClick.AddListener(() => SwitchTab(1));
}
protected override void OnOpen()
{
SwitchTab(0);
}
}
```
## 最佳实践
- **不要手写大多数 UIHolder**,优先使用自动生成
- 窗口逻辑类只处理状态和行为,控件引用统一放进 Holder
- `OnInitialize` 做一次性事件绑定,`OnOpen` 做参数刷新
- 默认使用异步打开,避免首帧阻塞
- 列表项和重复块优先拆成 `UIWidget<T>`
## 常见错误
### 手工编写 UIHolder 导致与生成器冲突
- 现象:字段名、命名空间或资源路径不一致
- 规避:把 Holder 视为生成产物,由工具维护
### 在 `OnOpen` 中重复注册按钮事件
- 风险:窗口每次打开都会重复绑定
- 正确做法:放到 `OnInitialize`
### 把 `UIWidget<T>` 当顶层窗口直接 `ShowUI`
- `UIWidget<T>` 应由父 `UIBase` 通过 `CreateWidgetAsync<T>()``CreateWidgetSync<T>()` 创建
## 性能注意事项
- 首次打开大窗口优先预热资源或异步显示
- 使用自动生成 Holder 可以避免大量运行时查找和手工拖引用错误
- 高频销毁/重建的块状内容优先用 `UIWidget<T>`

View File

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

View File

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

View File

@ -0,0 +1,94 @@
# UIExtension InputGlyph 输入图标模块手册
## 模块概述
`InputGlyph` 提供输入设备检测、绑定解析、图标数据库查询、UI Image/TMP 输出和重绑定后自动刷新能力。
## 适用场景
- 显示键盘、手柄按键图标。
- 文本中嵌入按键提示。
- 输入重绑定后自动刷新 UI 提示。
## 快速上手
1. 创建 `InputGlyphDatabase` 并放到 `Resources/InputGlyphDatabase.asset`
2. 给目标对象挂 `InputGlyph`
3. 选择动作来源与输出模式。
## 详细使用说明
- `InputGlyph` 会监听 `InputDeviceWatcher``InputBindingManager.BindingsChanged`
- 输出为 `Image` 时设置 `targetImage.sprite`
- 输出为 `Text` 时写入 TMP `<sprite>` 标签或回退显示文本。
## 可调用 API
### 类型:`InputGlyph`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/InputGlyph.cs`
- 枚举:`ActionSourceMode`、`OutputMode`
- 类型:`DeviceCategoryEvent`
- `category`
- `onMatched`
- `onNotMatched`
### 类型:`InputGlyphBehaviourBase`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/InputGlyphBehaviourBase.cs`
- 说明:抽象基类,负责设备变化与绑定变化监听。
### 类型:`GlyphService`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/Core/GlyphService.cs`
- `GetBindingControlPath(InputAction action, string compositePartName = null, InputDeviceWatcher.InputDeviceCategory? deviceOverride = null)`
- `GetBindingControlPath(InputActionReference actionReference, string compositePartName = null, InputDeviceWatcher.InputDeviceCategory? deviceOverride = null)`
- `TryGetTMPTagForActionPath(InputAction action, string compositePartName, InputDeviceWatcher.InputDeviceCategory device, out string tag, out string displayFallback, InputGlyphDatabase db = null)`
- `TryGetTMPTagForActionPath(InputActionReference actionReference, string compositePartName, InputDeviceWatcher.InputDeviceCategory device, out string tag, out string displayFallback, InputGlyphDatabase db = null)`
- `TryGetUISpriteForActionPath(InputAction action, string compositePartName, InputDeviceWatcher.InputDeviceCategory device, out Sprite sprite, InputGlyphDatabase db = null)`
- `TryGetUISpriteForActionPath(InputActionReference actionReference, string compositePartName, InputDeviceWatcher.InputDeviceCategory device, out Sprite sprite, InputGlyphDatabase db = null)`
- `TryGetTMPTagForActionPath(string controlPath, InputDeviceWatcher.InputDeviceCategory device, out string tag, out string displayFallback, InputGlyphDatabase db = null)`
- `TryGetUISpriteForActionPath(string controlPath, InputDeviceWatcher.InputDeviceCategory device, out Sprite sprite, InputGlyphDatabase db = null)`
- `GetDisplayNameFromInputAction(InputAction action, string compositePartName = null, InputDeviceWatcher.InputDeviceCategory? deviceOverride = null)`
- `GetDisplayNameFromControlPath(string controlPath)`
- `TryGetBindingControl(InputAction action, string compositePartName, InputDeviceWatcher.InputDeviceCategory? deviceOverride, out InputBinding binding)`
### 类型:`InputActionReader`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/Core/InputActionReader.cs`
- `ReadValue<T>(string actionName)`
- `ReadValue(string actionName)`
- `TryReadValue<T>(string actionName, out T value)`
- `TryReadValue(string actionName, out object value)`
- `TryReadValueOnce<T>(UnityEngine.Object owner, string actionName, out T value)`
- `ReadButton(string actionName)`
- `ReadButtonOnce(UnityEngine.Object owner, string actionName)`
- `ReadButtonOnce(int instanceID, string actionName)`
- `ReadButtonOnce(string key, string actionName)`
- `ReadButtonToggle(UnityEngine.Object owner, string actionName)`
- `ReadButtonToggle(int instanceID, string actionName)`
- `ReadButtonToggle(string key, string actionName)`
- `ResetToggledButton(string key, string actionName)`
- `ResetToggledButton(string actionName)`
- `ResetToggledButtons()`
### 类型:`InputBindingManager`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/Core/InputBindingManager.cs`
- 公开字段:`actions`、`debugMode`
- 事件:`OnApply`、`OnRebindPrepare`、`OnRebindStart`、`OnRebindEnd`、`OnRebindConflict`、`BindingsChanged`
- 属性:`ActionMaps`、`PreparedRebinds`
- 方法:`FindBestBindingIndexForKeyboard(...)`、`Action(string actionName)`、`TryGetAction(...)`、`StartRebind(...)`、`CancelRebind()`、`ConfirmApply(...)`、`DiscardPrepared()`、`ResetToDefaultAsync()`、`GetBindingPath(...)`
- 公开嵌套类型:`ActionMap`、`Action`、`Binding`、`BindingPath`、`RebindContext`
### 类型:`InputDeviceWatcher`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/Core/InputDeviceWatcher.cs`
- 枚举:`InputDeviceCategory`
- 结构:`DeviceContext`
- 属性:`CurrentCategory`、`CurrentDeviceName`、`CurrentDeviceId`、`CurrentVendorId`、`CurrentProductId`、`CurrentContext`
- 事件:`OnDeviceChanged`、`OnDeviceContextChanged`
- 方法:`Initialize()`、`Dispose()`
### 类型:`InputGlyphDatabase`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/InputGlyph/Data/InputGlyphDatabase.cs`
- 字段:`tables`、`placeholderSprite`
- 方法:`GetTable(string deviceName)`、`GetTable(InputDeviceWatcher.InputDeviceCategory device)`、`GetPlatformIcon(...)`、`TryGetSprite(...)`、`FindSprite(...)`、`FindEntryByControlPath(...)`、`EditorRefreshCache()`、`EditorNormalizeControlPath(...)`
- 类型:`GlyphEntry`、`DeviceGlyphTable`
## 示例
```csharp
if (GlyphService.TryGetUISpriteForActionPath(actionRef, null, InputDeviceWatcher.CurrentCategory, out var sprite))
{
image.sprite = sprite;
}
```

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,22 @@
# UIExtension UXButton 按钮模块手册
## 模块概述
`UXButton``Button` 的增强版本,继承自 `UXSelectable`,统一了鼠标、键盘和手柄提交行为。
## 可调用 API
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Button/UXButton.cs`
### 类型:`UXButton`
- `onClick`
- `OnPointerEnter(PointerEventData eventData)`
- `OnPointerClick(PointerEventData eventData)`
- `OnSubmit(BaseEventData eventData)`
### 接口:`AlicizaX.UI.Extension.IButton`
- 按钮能力抽象接口。
## 快速上手
```csharp
var btn = gameObject.AddComponent<UnityEngine.UI.UXButton>();
btn.onClick.AddListener(() => UnityEngine.Debug.Log("Clicked"));
```

View File

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

View File

@ -0,0 +1,51 @@
# UIExtension UXController 数据驱动绑定模块手册
## 模块概述
`UXController``UXBinding` 组成 UI 状态驱动绑定系统,用于把控制器状态映射到 UI 属性值。
## 适用场景
- 页签状态切换。
- UI 主题或皮肤切换。
- 可见性、文本、颜色、尺寸等属性联动。
## 可调用 API
### 类型:`UXController`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Controller/UXController.cs`
- 属性:`Controllers`、`Bindings`、`ControllerCount`
- `ControllerDefinition` 属性:`Id`、`Name`、`Length`、`Description`、`SelectedIndex`
- 方法:`TryGetControllerById(...)`、`TryGetControllerByName(...)`、`GetControllerByName(...)`、`GetControllerAt(...)`、`GetControllerIndex(...)`、`SetControllerIndex(...)`、`SetControllerIndexByName(...)`、`ResetAllControllers()`
### 类型:`UXBinding`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Controller/UXBinding.cs`
- 属性:`Controller`、`Entries`
- 方法:`Initialize()`、`SetController(...)`、`CaptureDefaults()`、`ResetToDefaults()`、`PreviewEntry(...)`、`CaptureEntryValue(...)`、`CaptureEntryFallbackValue(...)`
- `BindingEntry` 属性:`ControllerId`、`ControllerIndex`、`Property`、`Value`、`FallbackMode`、`FallbackValue`、`HasCapturedDefault`
### 类型:`UXBindingValue`
- `BoolValue`
- `FloatValue`
- `StringValue`
- `ColorValue`
- `Vector2Value`
- `Vector3Value`
- `ObjectValue`
- `CopyFrom(UXBindingValue other)`
### 工具类:`UXBindingPropertyUtility`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Controller/UXBindingPropertyUtility.cs`
- `AllMetadata`
- `GetMetadata(...)`
- `IsSupported(...)`
- `GetSupportedProperties(...)`
- `CaptureValue(...)`
- `ApplyValue(...)`
### 枚举
- `UXBindingFallbackMode`
- `UXBindingValueKind`
- `UXBindingProperty`
## 快速上手
```csharp
controller.SetControllerIndex("TabState", 1);
```

View File

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

View File

@ -0,0 +1,16 @@
# UIExtension UXDraggable 拖拽模块手册
## 模块概述
`UXDraggable` 把拖拽生命周期包装为 `UnityEvent<PointerEventData>`,便于直接在 Inspector 或代码中订阅。
## 可调用 API
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Drag/UXDraggable.cs`
- `onDrag`
- `onBeginDrag`
- `onEndDrag`
## 快速上手
```csharp
var draggable = gameObject.AddComponent<UnityEngine.UI.UXDraggable>();
draggable.onBeginDrag.AddListener(_ => UnityEngine.Debug.Log("Begin"));
```

View File

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

View File

@ -0,0 +1,22 @@
# UIExtension UXGroup 与 UXToggle 模块手册
## 模块概述
`UXGroup``UXToggle` 提供增强的单选组与 Toggle 体系,兼容更好的导航和状态控制。
## 可调用 API
### 类型:`UXGroup`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Group/UXGroup.cs`
- 字段:`allowSwitchOff`、`defaultToggle`
- 方法:`NotifyToggleOn(...)`、`UnregisterToggle(...)`、`RegisterToggle(...)`、`ContainsToggle(...)`、`EnsureValidState()`、`AnyTogglesOn()`、`ActiveToggles()`、`GetFirstActiveToggle()`、`SetAllTogglesOff(...)`、`Next()`、`Preview()`
### 类型:`UXToggle`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Group/UXToggle.cs`
- 字段/属性:`toggleTransition`、`graphic`、`group`、`onValueChanged`、`isOn`
- 方法:`Rebuild(...)`、`LayoutComplete()`、`GraphicUpdateComplete()`、`SetIsOnWithoutNotify(...)`、`OnPointerEnter(...)`、`OnPointerClick(...)`、`OnSubmit(...)`
- 类型:`ToggleEvent : UnityEvent<bool>`
## 快速上手
```csharp
toggle.group = group;
toggle.onValueChanged.AddListener(v => UnityEngine.Debug.Log(v));
```

View File

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

View File

@ -0,0 +1,31 @@
# UIExtension UXHelper 辅助接口模块手册
## 模块概述
`UXHelper` 用于把 UI 扩展层与项目本地化、音频等外部系统解耦。
## 适用场景
- 接入项目本地化系统。
- 为 UI 组件统一注入帮助器。
## 快速上手
```csharp
public class DemoLocalizationHelper : IUXLocalizationHelper
{
public string GetString(string key) => key;
}
UXComponentExtensionsHelper.SetLocalizationHelper(new DemoLocalizationHelper());
```
## 可调用 API
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/UXHelper.cs`
### 类型:`UXComponentExtensionsHelper`
- `SetLocalizationHelper(IUXLocalizationHelper helper)`
- `SetAudioHelper(IUXAudioHelper helper)`
### 接口:`IUXLocalizationHelper`
- `GetString(string key)`
### 接口:`IUXAudioHelper`
- 说明:当前未定义公开方法,作为项目扩展点保留。

View File

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

View File

@ -0,0 +1,24 @@
# UIExtension UXHotkey 热键注册模块手册
## 模块概述
`UXHotkey` 模块统一管理 UI 热键触发器,支持作用域、层级阻断、批量绑定与调试输出。
## 可调用 API
### 类型:`HotkeyComponent`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Hotkey/HotkeyComponent.cs`
- `HotkeyAction`
### 接口:`IHotkeyTrigger`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Hotkey/IHotkeyTrigger.cs`
- `HotkeyAction { get; }`
### 类型:`UXHotkeyRegisterManager`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Hotkey/UXHotkeyRegisterManager.cs`
- `GetDebugInfo()`
- 扩展方法:`BindHotKey(...)`、`UnBindHotKey(...)`、`BindHotKeyBatch(...)`、`UnBindHotKeyBatch(...)`
- 公开辅助类型:`HotkeyRegistration`、`HotkeyScope`、`ActionRegistration`、`TriggerRegistration`
## 快速上手
```csharp
trigger.BindHotKey();
```

View File

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

View File

@ -0,0 +1,41 @@
# UIExtension UXImage 图像增强模块手册
## 模块概述
`UXImage` 扩展了 Unity `Image`,支持渐变、镜像、翻转填充和顶点重映射。
## 可调用 API
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Image/UXImage.cs`
### 类型:`UXImage`
- `gradient`
- `Direction`
- `m_OriginFlipMode`
- `m_FlipMode`
- `flipMode`
- `m_FlipWithCopy`
- `flipWithCopy`
- `flipEdge`
- `m_FlipEdgeHorizontal`
- `flipEdgeHorizontal`
- `m_FlipEdgeVertical`
- `flipEdgeVertical`
- `m_FlipFillCenter`
- `flipFillCenter`
- `m_FlipDirection`
- `flipDirection`
- `RemapVertex(ref UIVertex vertex, FlipMode flipMode, float Min1, float Max1, float Min2, float Max2)`
### 枚举
- `ColorType`
- `GradientDirection`
- `FlipPart`
- `FlipDirection`
- `FlipMode`
- `FlipEdge`
- `FlipEdgeHorizontal`
- `FlipEdgeVertical`
- `FlipFillCenter`
### 辅助类型
- `Vert2D`
- `Comparer`

View File

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

View File

@ -0,0 +1,37 @@
# UIExtension UXNavigation 导航模块手册
## 模块概述
`UXNavigation` 在新输入系统下增强 UI 导航,支持输入模式识别、导航作用域、默认选中项、上次选中记忆和跳过导航对象。
## 适用场景
- 手柄导航友好的菜单与弹窗。
- 多层 UI 叠加时管理焦点归属。
- 鼠标与手柄输入模式自动切换。
## 可调用 API
### 枚举:`UXInputMode`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Navigation/UXInputMode.cs`
- 表示当前输入模式。
### 类型:`UXInputModeService`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Navigation/UXInputModeService.cs`
- `CurrentMode`
- `OnModeChanged`
### 类型:`UXNavigationScope`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Navigation/UXNavigationScope.cs`
- 属性:`DefaultSelectable`、`RememberLastSelection`、`RequireSelectionWhenGamepad`、`BlockLowerScopes`
- 方法:`InvalidateSelectableCache()`
### 类型:`UXNavigationSkip`
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Navigation/UXNavigationSkip.cs`
- 标记对象跳过导航体系。
### 其他核心类型
- `UXNavigationRuntime`
- `UXNavigationLayerWatcher`
## 快速上手
```csharp
scope.DefaultSelectable = firstSelectable;
```

View File

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

View File

@ -0,0 +1,22 @@
# UIExtension UXSelectable 选择态增强模块手册
## 模块概述
`UXSelectable``Selectable` 的增强基类,支持对子图形做额外颜色/精灵过渡,并重写方向查找逻辑。
## 可调用 API
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Selectable/UXSelectable.cs`
### 类型:`TransitionData`
- `targetGraphic`
- `transition`
- `colors`
- `spriteState`
### 类型:`UXSelectable`
- `FindSelectableOnLeft()`
- `FindSelectableOnRight()`
- `FindSelectableOnUp()`
- `FindSelectableOnDown()`
## 使用建议
- 若控件的多个子节点需要跟随选择态变化,可优先通过 `TransitionData` 配置。

View File

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

View File

@ -0,0 +1,16 @@
# UIExtension UXTextMeshPro 文本模块手册
## 模块概述
`UXTextMeshPro` 扩展了 `TextMeshProUGUI`,用于接入项目本地化系统并支持编辑器预览刷新。
## 可调用 API
源码:`Packages/com.alicizax.unity.ui.extension/Runtime/UXComponent/Text/UXTextMeshPro.cs`
- `SetLocalization(string localizationID)`
## 快速上手
```csharp
text.SetLocalization("UI_Common_Confirm");
```
## 注意事项
- 需先通过 `UXComponentExtensionsHelper.SetLocalizationHelper()` 注入本地化帮助器。

View File

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

View File

@ -1,5 +1,6 @@
using AlicizaX;
using AlicizaX.UI;
using UnityEngine;
using UnityEngine.EventSystems;
public sealed class TestScrollItemRender : ItemRender<TestData, TestScrollViewHolder>
@ -16,17 +17,17 @@ public sealed class TestScrollItemRender : ItemRender<TestData, TestScrollViewHo
protected override void OnHolderAttached()
{
base.OnHolderAttached();
Holder.BtnTest.onClick.AddListener(OnInnerButtonClick);
baseui.BtnTest.onClick.AddListener(OnInnerButtonClick);
}
protected override void OnHolderDetached()
{
Holder.BtnTest.onClick.RemoveListener(OnInnerButtonClick);
baseui.BtnTest.onClick.RemoveListener(OnInnerButtonClick);
}
protected override void OnBind(TestData data, int index)
{
Holder.Text.text = data.Name;
baseui.Text.text = data.Name;
}
protected override void OnPointerClick(PointerEventData eventData)
@ -36,25 +37,25 @@ public sealed class TestScrollItemRender : ItemRender<TestData, TestScrollViewHo
protected override void OnPointerEnter(PointerEventData eventData)
{
Holder.Text.fontStyle = TMPro.FontStyles.Bold;
baseui.Text.fontStyle = TMPro.FontStyles.Bold;
// Log.Info(CurrentData.Name + " Pointer Enter");
}
protected override void OnPointerExit(PointerEventData eventData)
{
Holder.Text.fontStyle = TMPro.FontStyles.Normal;
baseui.Text.fontStyle = TMPro.FontStyles.Normal;
// Log.Info(CurrentData.Name + " Pointer Exit");
}
protected override void OnItemSelected(BaseEventData eventData)
{
Holder.Text.color = UnityEngine.Color.yellow;
baseui.Text.color = UnityEngine.Color.yellow;
Log.Info(CurrentData.Name + " Selected");
}
protected override void OnItemDeselected(BaseEventData eventData)
{
Holder.Text.color = UnityEngine.Color.black;
baseui.Text.color = UnityEngine.Color.black;
Log.Info(CurrentData.Name + " OnItemDeselected");
}
@ -71,11 +72,18 @@ public sealed class TestScrollItemRender : ItemRender<TestData, TestScrollViewHo
}
}
protected override bool OnMove(AxisEventData eventData)
{
if (eventData.moveDir == MoveDirection.Down || eventData.moveDir == MoveDirection.Up) return false;
Debug.Log($"{CurrentData.Name} Moved {eventData.moveDir}");
return true;
}
protected override void OnClear()
{
base.OnClear();
Holder.Text.fontStyle = TMPro.FontStyles.Normal;
Holder.Text.color = UnityEngine.Color.black;
baseui.Text.fontStyle = TMPro.FontStyles.Normal;
baseui.Text.color = UnityEngine.Color.black;
}
private void OnInnerButtonClick()

View File

@ -20,7 +20,7 @@ MonoBehaviour:
m_EnableRaycastTarget: 1
m_GetFontFeaturesAtRuntime: 1
m_missingGlyphCharacter: 0
m_warningsDisabled: 0
m_warningsDisabled: 1
m_defaultFontAsset: {fileID: 11400000, guid: 7cdd102360e32234383f8e3f40da47a9, type: 2}
m_defaultFontAssetPath: Fonts & Materials/
m_defaultFontSize: 36

View File

@ -10,7 +10,7 @@
"BuildPipeline": "EditorSimulateBuildPipeline",
"PackageName": "DefaultPackage",
"PackageVersion": "Simulate",
"PackageNote": "2026/3/31 16:14:42",
"PackageNote": "2026/4/1 13:11:49",
"AssetList": [
{
"Address": "Click",

@ -1 +1 @@
Subproject commit dc8c840d692e83d525655cf657fcc9d1ff069a36
Subproject commit b6dacac94d83a4e4ebe3adde64d323345d115a4a

View File

@ -19,7 +19,7 @@ MonoBehaviour:
width: 1920
height: 997
m_ShowMode: 4
m_Title: Console
m_Title: Inspector
m_RootView: {fileID: 4}
m_MinSize: {x: 875, y: 300}
m_MaxSize: {x: 10000, y: 10000}
@ -41,10 +41,10 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 360
width: 818
width: 503
height: 587
m_MinSize: {x: 51, y: 71}
m_MaxSize: {x: 4001, y: 4021}
m_MinSize: {x: 50, y: 50}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 14}
m_Panes:
- {fileID: 14}
@ -70,12 +70,12 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 818
width: 503
height: 947
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 26
controlID: 17
draggingID: 0
--- !u!114 &4
MonoBehaviour:
@ -174,7 +174,7 @@ MonoBehaviour:
m_MinSize: {x: 400, y: 100}
m_MaxSize: {x: 32384, y: 16192}
vertical: 0
controlID: 156
controlID: 48
draggingID: 0
--- !u!114 &8
MonoBehaviour:
@ -193,7 +193,7 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 818
width: 503
height: 360
m_MinSize: {x: 201, y: 221}
m_MaxSize: {x: 4001, y: 4021}
@ -219,14 +219,14 @@ MonoBehaviour:
- {fileID: 11}
m_Position:
serializedVersion: 2
x: 818
x: 503
y: 0
width: 512
width: 421
height: 947
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 8096, y: 16192}
vertical: 1
controlID: 71
controlID: 49
draggingID: 0
--- !u!114 &10
MonoBehaviour:
@ -245,10 +245,10 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 512
width: 421
height: 465
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 4000, y: 4000}
m_MinSize: {x: 202, y: 221}
m_MaxSize: {x: 4002, y: 4021}
m_ActualView: {fileID: 17}
m_Panes:
- {fileID: 17}
@ -271,10 +271,10 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 465
width: 512
width: 421
height: 482
m_MinSize: {x: 102, y: 121}
m_MaxSize: {x: 4002, y: 4021}
m_MinSize: {x: 100, y: 100}
m_MaxSize: {x: 4000, y: 4000}
m_ActualView: {fileID: 18}
m_Panes:
- {fileID: 18}
@ -295,9 +295,9 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 1330
x: 924
y: 0
width: 130
width: 529
height: 947
m_MinSize: {x: 232, y: 271}
m_MaxSize: {x: 10002, y: 10021}
@ -321,9 +321,9 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 1460
x: 1453
y: 0
width: 460
width: 467
height: 947
m_MinSize: {x: 275, y: 50}
m_MaxSize: {x: 4000, y: 4000}
@ -354,7 +354,7 @@ MonoBehaviour:
serializedVersion: 2
x: 1920
y: 438
width: 817
width: 502
height: 566
m_SerializedDataModeController:
m_DataMode: 0
@ -408,10 +408,10 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 21
width: 817
width: 502
height: 545
m_Scale: {x: 0.42552084, y: 0.42552084}
m_Translation: {x: 408.5, y: 272.5}
m_Scale: {x: 0.26145834, y: 0.26145834}
m_Translation: {x: 251, y: 272.5}
m_MarginLeft: 0
m_MarginRight: 0
m_MarginTop: 0
@ -419,12 +419,12 @@ MonoBehaviour:
m_LastShownAreaInsideMargins:
serializedVersion: 2
x: -960
y: -640.39166
y: -1042.2311
width: 1920
height: 1280.7833
height: 2084.4622
m_MinimalGUI: 1
m_defaultScale: 0.42552084
m_LastWindowPixelSize: {x: 817, y: 566}
m_defaultScale: 0.26145834
m_LastWindowPixelSize: {x: 502, y: 566}
m_ClearInEditMode: 1
m_NoCameraWarning: 1
m_LowResolutionForAspectRatios: 01000000000000000000
@ -522,7 +522,7 @@ MonoBehaviour:
serializedVersion: 2
x: 1920
y: 78
width: 817
width: 502
height: 339
m_SerializedDataModeController:
m_DataMode: 0
@ -1064,9 +1064,9 @@ MonoBehaviour:
m_PlayAudio: 0
m_AudioPlay: 0
m_Position:
m_Target: {x: 1003.8969, y: 1001.6229, z: 212.76372}
m_Target: {x: 1003.16583, y: 999.6796, z: 155.55556}
speed: 2
m_Value: {x: 1003.8969, y: 1001.6229, z: 212.76372}
m_Value: {x: 1003.16583, y: 999.6796, z: 155.55556}
m_RenderMode: 0
m_CameraMode:
drawMode: 0
@ -1163,9 +1163,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 2738
x: 2423
y: 78
width: 510
width: 419
height: 444
m_SerializedDataModeController:
m_DataMode: 0
@ -1180,9 +1180,9 @@ MonoBehaviour:
m_SceneHierarchy:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_SelectedIDs: 8c690000
m_LastClickedID: 0
m_ExpandedIDs: 8c4fffffb44fffff9651ffffba51ffffc251ffff928dffff9e8dffffc68dffffa88fffffcc8fffffd48fffff28fbfffff4ffffff
m_ExpandedIDs: 2a3dffff363dffff5e3dffff403fffff643fffff6c3fffff8a98ffffa498ffffb098ffffd898ffffba9affffde9affffe69affffc8a1ffffd4a1fffffca1ffffdea3ffff02a4ffff0aa4ffff1cfbfffff4ffffff
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
@ -1226,9 +1226,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 2738
x: 2423
y: 543
width: 510
width: 419
height: 461
m_SerializedDataModeController:
m_DataMode: 0
@ -1260,9 +1260,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 3250
x: 2844
y: 78
width: 128
width: 527
height: 926
m_SerializedDataModeController:
m_DataMode: 0
@ -1285,7 +1285,7 @@ MonoBehaviour:
m_SkipHidden: 0
m_SearchArea: 2
m_Folders:
- Assets/Bundles/UI
- Assets/YooAsset
m_Globs: []
m_OriginalText:
m_ImportLogFlags: 0
@ -1301,7 +1301,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs: e48c0000
m_LastClickedID: 36068
m_ExpandedIDs: 000000007e020000606a0000626a0000646a0000666a0000686a00006a6a00006c6a00006e6a0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000be6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000de6a0000e06a0000e26a0000e46a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f46a0000f66a0000f86a0000fa6a0000fc6a0000fe6a0000006b0000026b0000046b0000066b0000086b00000a6b00000c6b00000e6b0000106b0000126b0000146b0000166b0000186b00001a6b00001c6b00001e6b0000206b0000226b0000246b0000266b0000286b00002a6b0000
m_ExpandedIDs: 000000007e020000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000be6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000de6a0000e06a0000e26a0000e46a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f46a0000f66a0000f86a0000fa6a0000fc6a0000fe6a0000006b0000026b0000046b0000066b0000086b00000a6b00000c6b00000e6b0000106b0000126b0000146b0000166b0000186b00001a6b00001c6b00001e6b0000206b0000226b0000246b0000266b0000286b00002a6b00002c6b00002e6b0000306b0000326b0000346b0000366b0000386b00003a6b00003c6b0000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
@ -1329,18 +1329,18 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: ffffffff000000007e020000606a0000626a0000646a0000666a0000686a00006a6a00006c6a00006e6a0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000be6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000de6a0000e06a0000e26a0000e46a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f46a0000f66a0000f86a0000fa6a0000fc6a0000fe6a0000006b0000026b0000046b0000066b0000086b00000a6b00000c6b00000e6b0000106b0000126b0000146b0000166b0000186b00001a6b00001c6b00001e6b0000206b0000226b0000246b0000266b0000286b00002a6b0000306d0000
m_ExpandedIDs: ffffffff000000007e020000fe0c0000706a0000726a0000746a0000766a0000786a00007a6a00007c6a00007e6a0000806a0000826a0000846a0000866a0000886a00008a6a00008c6a00008e6a0000906a0000926a0000946a0000966a0000986a00009a6a00009c6a00009e6a0000a06a0000a26a0000a46a0000a66a0000a86a0000aa6a0000ac6a0000ae6a0000b06a0000b26a0000b46a0000b66a0000b86a0000ba6a0000bc6a0000c06a0000c26a0000c46a0000c66a0000c86a0000ca6a0000cc6a0000ce6a0000d06a0000d26a0000d46a0000d66a0000d86a0000da6a0000dc6a0000de6a0000e06a0000e26a0000e46a0000e66a0000e86a0000ea6a0000ec6a0000ee6a0000f06a0000f26a0000f66a0000f86a0000fa6a0000fc6a0000fe6a0000006b0000026b0000046b0000066b0000086b00000a6b00000c6b00000e6b0000106b0000126b0000146b0000166b0000186b00001a6b00001c6b00001e6b0000226b0000246b0000266b0000286b00002a6b00002e6b0000306b0000326b0000346b0000366b0000386b00003a6b00003c6b0000466d0000646d000030760000
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name: UILoadUpdateWindow
m_OriginalName: UILoadUpdateWindow
m_Name: TestScrollItemRender
m_OriginalName: TestScrollItemRender
m_EditFieldRect:
serializedVersion: 2
x: 0
y: 0
width: 0
height: 0
m_UserData: 27948
m_UserData: 1808
m_IsWaitingForDelay: 0
m_IsRenaming: 0
m_OriginalEventType: 0
@ -1405,9 +1405,9 @@ MonoBehaviour:
m_Tooltip:
m_Pos:
serializedVersion: 2
x: 3380
x: 3373
y: 78
width: 459
width: 466
height: 926
m_SerializedDataModeController:
m_DataMode: 0
@ -1422,7 +1422,7 @@ MonoBehaviour:
m_ObjectsLockedBeforeSerialization: []
m_InstanceIDsLockedBeforeSerialization:
m_PreviewResizer:
m_CachedPref: 282
m_CachedPref: 151
m_ControlHash: 1412526313
m_PrefName: Preview_InspectorPreview
m_LastInspectedObjectInstanceID: -1