NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Modules/UISystem.md

435 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# UI系统优化建议
## 1. UI框架优化
### 1.1 当前实现
```csharp
// UIFightTeamController.cs 中的UI实现
public class UIFightTeamController : UIWindow
{
private List<uint> _displayList;
private List<GameObject> _headList;
private bool _isInit = false;
public override void OnInit()
{
UIFightTeamBinder.GetComponents(this);
_OnInit();
}
protected override void OnShowWindow(object data = null)
{
if (_isInit)
{
_isInit = false;
return;
}
_SetData();
_Refresh();
}
}
```
### 1.2 优化建议
1. UI组件化和对象池优化
```csharp
// UI组件基类
public abstract class UIComponent : MonoBehaviour
{
protected UIData _data;
protected bool _initialized;
public virtual void Init()
{
if (_initialized) return;
_initialized = true;
OnInit();
}
protected virtual void OnInit() { }
public virtual void SetData(UIData data)
{
_data = data;
Refresh();
}
public virtual void Refresh() { }
}
// UI对象池管理
public class UIPoolManager
{
private Dictionary<string, Queue<GameObject>> _pools = new();
private Dictionary<string, GameObject> _prefabs = new();
public T GetUI<T>(string prefabPath) where T : UIComponent
{
if (!_pools.ContainsKey(prefabPath))
_pools[prefabPath] = new Queue<GameObject>();
if (_pools[prefabPath].Count > 0)
{
var go = _pools[prefabPath].Dequeue();
go.SetActive(true);
return go.GetComponent<T>();
}
return CreateUI<T>(prefabPath);
}
public void ReturnUI(string prefabPath, GameObject ui)
{
ui.SetActive(false);
_pools[prefabPath].Enqueue(ui);
}
}
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// 战斗UI的ViewModel
public class FightTeamViewModel : ViewModel
{
private ObservableCollection<UnitViewModel> _units = new();
public ObservableCollection<UnitViewModel> Units => _units;
private UnitViewModel _selectedUnit;
public UnitViewModel SelectedUnit
{
get => _selectedUnit;
set
{
_selectedUnit = value;
NotifyPropertyChanged();
}
}
}
// UI View层
public class UIFightTeamView : UIWindow
{
private FightTeamViewModel _viewModel;
public override void OnInit()
{
_viewModel = new FightTeamViewModel();
InitializeBindings();
}
private void InitializeBindings()
{
// 数据绑定
_viewModel.PropertyChanged += OnViewModelPropertyChanged;
}
}
```
## 2. UI性能优化
### 2.1 列表优化
使用对象池和虚拟列表优化长列表:
```csharp
public class VirtualizedList<T> : MonoBehaviour where T : MonoBehaviour
{
[SerializeField] private RectTransform _viewport;
[SerializeField] private RectTransform _content;
[SerializeField] private T _itemPrefab;
private List<T> _activeItems = new();
private Queue<T> _pooledItems = new();
private List<IItemData> _dataList = new();
public void SetData(List<IItemData> dataList)
{
_dataList = dataList;
UpdateVisibleItems();
}
private void UpdateVisibleItems()
{
// 计算可见区域
var viewportBounds = new Bounds(_viewport.position, _viewport.rect.size);
// 回收不可见项
for (int i = _activeItems.Count - 1; i >= 0; i--)
{
var item = _activeItems[i];
if (!viewportBounds.Intersects(item.GetComponent<RectTransform>().bounds))
{
ReturnToPool(item);
_activeItems.RemoveAt(i);
}
}
// 创建可见项
foreach (var data in _dataList)
{
if (IsItemVisible(data) && !IsItemCreated(data))
{
CreateItem(data);
}
}
}
}
```
### 2.2 UI资源加载优化
使用异步加载和预加载机制:
```csharp
public class UIResourceManager : MonoBehaviour
{
private Dictionary<string, WeakReference<GameObject>> _uiCache = new();
private HashSet<string> _preloadList = new();
public async UniTask PreloadUI(string uiName)
{
if (_preloadList.Contains(uiName)) return;
var prefab = await LoadUIPrefabAsync(uiName);
_uiCache[uiName] = new WeakReference<GameObject>(prefab);
_preloadList.Add(uiName);
}
public async UniTask<GameObject> GetUI(string uiName)
{
if (_uiCache.TryGetValue(uiName, out var weakRef))
{
if (weakRef.TryGetTarget(out var cachedUI))
{
return cachedUI;
}
}
return await LoadUIPrefabAsync(uiName);
}
}
```
## 3. UI事件系统优化
### 3.1 当前问题
- GameObject查找性能开销
- 组件获取方式不优化
- 事件系统使用不规范
### 3.2 优化建议
1. 优化组件获取:
```csharp
public class UIUtils
{
// 缓存组件查找结果
private static Dictionary<int, Dictionary<Type, Component>> _componentCache = new();
public static T GetComponent<T>(GameObject go) where T : Component
{
var instanceId = go.GetInstanceID();
var type = typeof(T);
if (!_componentCache.ContainsKey(instanceId))
_componentCache[instanceId] = new Dictionary<Type, Component>();
if (!_componentCache[instanceId].ContainsKey(type))
_componentCache[instanceId][type] = go.GetComponent<T>();
return _componentCache[instanceId][type] as T;
}
public static void ClearCache(GameObject go)
{
var instanceId = go.GetInstanceID();
if (_componentCache.ContainsKey(instanceId))
_componentCache.Remove(instanceId);
}
}
```
2. 优化事件系统使用:
```csharp
public class UIEventHandler : MonoBehaviour
{
private List<UIEventRegistration> _registrations = new();
protected void RegisterEvent<T>(string eventName, Action<T> handler)
{
var registration = new UIEventRegistration
{
eventName = eventName,
unregisterAction = () => EventManager.Instance.Unregister(eventName, handler)
};
EventManager.Instance.Register(eventName, handler);
_registrations.Add(registration);
}
protected virtual void OnDestroy()
{
foreach (var registration in _registrations)
{
registration.unregisterAction?.Invoke();
}
_registrations.Clear();
}
}
```
### 3.2 优化建议
1. 实现UI事件管理器
```csharp
public class UIEventManager
{
private Dictionary<Type, HashSet<IUIEventHandler>> _eventHandlers = new();
public void Register<T>(IUIEventHandler handler) where T : IUIEvent
{
var type = typeof(T);
if (!_eventHandlers.ContainsKey(type))
{
_eventHandlers[type] = new HashSet<IUIEventHandler>();
}
_eventHandlers[type].Add(handler);
}
public void Unregister<T>(IUIEventHandler handler) where T : IUIEvent
{
var type = typeof(T);
if (_eventHandlers.TryGetValue(type, out var handlers))
{
handlers.Remove(handler);
}
}
public void Dispatch<T>(T uiEvent) where T : IUIEvent
{
var type = typeof(T);
if (_eventHandlers.TryGetValue(type, out var handlers))
{
foreach (var handler in handlers)
{
handler.Handle(uiEvent);
}
}
}
}
```
## 4. UI动画系统优化
### 4.1 实现动画状态机:
```csharp
public class UIAnimationStateMachine
{
private Dictionary<string, UIAnimationState> _states = new();
private UIAnimationState _currentState;
public async UniTask TransitionTo(string stateName, bool immediate = false)
{
if (_currentState != null)
{
await _currentState.Exit(immediate);
}
if (_states.TryGetValue(stateName, out var newState))
{
_currentState = newState;
await _currentState.Enter(immediate);
}
}
}
public class UIAnimationState
{
private List<UIAnimation> _animations = new();
public async UniTask Enter(bool immediate)
{
foreach (var anim in _animations)
{
if (immediate)
anim.Complete();
else
await anim.Play();
}
}
public async UniTask Exit(bool immediate)
{
foreach (var anim in _animations)
{
if (immediate)
anim.Complete();
else
await anim.Reverse();
}
}
}
```
## 5. UI响应式布局优化
### 5.1 实现响应式布局系统:
```csharp
public class ResponsiveLayout : MonoBehaviour
{
[SerializeField] private List<BreakPoint> _breakPoints = new();
[SerializeField] private List<LayoutConfig> _configs = new();
private void OnRectTransformDimensionsChange()
{
UpdateLayout();
}
private void UpdateLayout()
{
var currentWidth = GetComponent<RectTransform>().rect.width;
var config = GetConfigForWidth(currentWidth);
ApplyConfig(config);
}
private void ApplyConfig(LayoutConfig config)
{
// 应用布局配置
foreach (var element in config.elements)
{
ApplyElementLayout(element);
}
}
}
```
## 6. UI优化建议总结
### 6.1 架构优化
- 实现MVVM架构
- 统一UI事件系统
- 规范UI生命周期管理
### 6.2 性能优化
- 使用对象池
- 实现虚拟列表
- 优化UI资源加载
### 6.3 开发效率
- 完善UI工具链
- 标准化UI组件
- 自动化UI测试
### 6.4 后续优化方向
1. UI框架
- 实现完整的MVVM框架
- 优化UI导航系统
- 增加UI单元测试
2. 性能优化
- 实现UI合批
- 优化UI重建
- 减少UI重绘
3. 工具链
- UI编辑器扩展
- UI自动化测试
- UI性能分析工具