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

10 KiB
Raw Blame History

UI系统优化建议

1. UI框架优化

1.1 当前实现

// 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组件化和对象池优化
// 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 列表优化

使用对象池和虚拟列表优化长列表:

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资源加载优化

使用异步加载和预加载机制:

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. 优化组件获取:
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);
    }
}
  1. 优化事件系统使用:
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事件管理器
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 实现动画状态机:

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 实现响应式布局系统:

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性能分析工具