【Unity3D技巧】一個簡單的Unity-UI框架的實現


如何使用

請直接導入UnityUIFramework這個UnityPackage,然后進入名為Test的Scene即可開始體驗各種特性,Enjoy!你可以通過訪問我的Github進行查閱和下載。

MainMenu

View,Context和UI的定義

UI是游戲中主要界面和它的子節點上的物體的統稱,如裝備列表界面中的裝備列表每個裝備通常會被制作成兩個Prefab,這兩個Prefab被我們稱作兩個UI,這兩個UI會對應兩個UIType,在UIType里面會存儲有這個UI全局唯一的名字和路徑,如下:

public class UIType {

    public string Path { get; private set; }

    public string Name { get; private set; }

    public UIType(string path)
    {
        Path = path;
        Name = path.Substring(path.LastIndexOf('/') + 1);
    }

    public override string ToString()
    {
        return string.Format("path : {0} name : {1}", Path, Name);
    }
}

View代指游戲中的主要界面,例如:主界面,裝備界面,裝備詳情界面等等。在View中包含了界面中處理數據的邏輯。

Context代指游戲中每個View的上下文,存儲了這個界面的各種數據狀態,每個特定的View會持有特定的Context,游戲中會通過棧的方式管理Context。

在本框架中,會把Context和View定義在同一個cs文件中,如下:

    public class OptionMenuContext :BaseContext
    {
        public OptionMenuContext() : base(UIType.OptionMenu){}
    }

    public class OptionMenuView : AnimateView
    {
        public override void OnEnter(BaseContext context)

        public override void OnExit(BaseContext context)

        public override void OnPause(BaseContext context)

        public override void OnResume(BaseContext context)
    }

View的創建和銷毀

所有界面上掛上的Mono腳本和關聯的Prefab統一以XXXView命名。

所有View的路徑統一放在UIType中進行管理,每當新創建一個View的時候,都需要在UIType中新添加一個成員變量指明View的路徑。

public static readonly UIType MainMenu = new UIType("View/MainMenuView");
public static readonly UIType OptionMenu = new UIType("View/OptionMenuView");
public static readonly UIType NextMenu = new UIType("View/NextMenuView");
public static readonly UIType HighScore = new UIType("View/HighScoreView");

在游戲中單獨出現的View會通過UIManager中的GetSingleUIDestroySingleUI來進行創建和銷毀。

View的跳轉

每個View都相應擁有相應的Context來保存該界面的狀態,View的跳轉通過ContextManger管理,ContextManager中以棧的形式儲存了已經經過的界面的Context。這樣在返回的時候就可以得到需要的狀態參數。

當需要進入下一個View的時候,調用ContextManger.Instance.Push(nextContext)即可,nextContext即為下一個View需要的上下文參數, 這是會調用當前View的OnPause函數,對當前View的上下文進行存儲,並調用下一個View的OnEnter函數,對下一個Viwe的上下文進行初始化

當需要返回上一個界面的時候,調用ContextManger.Instance.Push.Pop()即可。這是會調用當前界面的OnExit函數,接着調用下一個界面的OnResume函數。

View的動畫

如果在界面上使用3D的旋轉動畫,就很難使用DoTween或者iTween在代碼里面進行動畫控制,而且為了保持戰斗模塊和UI模塊設計的一致性。因此建議使用Animator對View的各種動畫進行控制,而View的動畫一般又和View的跳轉邏輯聯系緊密,所以建議將兩者進行綁定,一個View的動畫狀態機如下圖:

ViewAnimator

一個界面在沒有顯示的時候會處於Empty狀態,當接收到OnEnter的Trigger的時候,會播放OnEnter動畫,其他的狀態如圖所示,可以參考上圖以及項目中的狀態機。不同的界面可以使用相同的狀態機,只是在某些狀態上綁定的動畫會有所不同。

這樣做的另一個好處是,我們可以使用動畫時間的方式在動畫過程中做一些回調,這樣的在界面上對回調時機進行編輯,相比使用協程或者Dotween的OnFinished函數,有更好的可編輯性。

本地化

本地化是通過單例Localization和組件LocalizedText兩個來協同實現的,不同語言的文字會存儲在Resources/Localization中的不同JSON文件中,在單例Localization中配置后語言之后,即可讀入相應的JSON文件。

每個LocalizedText所在的GameObject上都需要與Text綁定,LocalizedText會根據自己的textID對Text中的text進行本地化

分辨率適配

UGUI中的分辨率適配是通過CanvasScaler來實現的,如下圖:
CanvasScaler

在這里,我建議使用Scale With Width Or Height這種Scale模式,同時,由於大多數游戲是橫屏游戲,通過使用高度固定,寬度隨之變化的模式。這樣我們就可以以一個固定的高度進行UI設計,只需要考慮UI在水平尺度上的延伸就可以了。

提升滑動列表的性能

在UGUI中Scroller和Grid都是很好用的組件,但是由於它們在實現過程中考慮了太多對齊,排序的問題,這就導致它們在處理無限列表問題的時候遇到了極大的性能瓶頸,相關資料參考:Performance issues on android with Scrollrect。在本框架中實現的自定義組件GridScroller可以在保證可編輯性的同時,提升了滑動列表的性能。

GridScroller的原理是:在滑動到某個item上的時候,會把之前的item進行回收,並且把它放到下一個位置進行再利用。在使用GridScroller的時候,你同樣要使用ScrollRect和GridLayout,GridScroller會從這兩個組件中讀取相應的屬性並且運用到UI邏輯中。

GridScroller對外界代碼提供了一個Init的接口,通過這個接口,外界模塊可以向GridScroller傳入一個onChange回調函數,這樣在GridScroller在刷新的時候,就會動態刷新相應的itemPrefab,實現用到時再加載的特性。

[RequireComponent(typeof(ScrollRect))]
public class GridScroller : MonoBehaviour {

    // public UI elements //
    [SerializeField]
    private Transform _itemPrefab;
    [SerializeField]
    private GridLayoutGroup _grid;

    // public fields //
    [SerializeField]
    private Movement _moveType = Movement.Horizontal;
    
    public delegate void OnChange(Transform trans, int index);
    
    public void Init(OnChange onChange, int itemCount, Vector2? normalizedPosition = null)
    {
        Clear();
        InitScroller();
        InitGrid();
        InitChildren(onChange, itemCount);
        InitTransform(normalizedPosition);
    }

對UI進行修飾

由於UGUI的Image,Text等屬性一般是不會設置Material的,我們可以通過寫腳本繼承BaseVertexEffect來對UI的Vertex進行修飾,項目中的Gradient Color和Blend Color就通過這種方式實現了顏色漸變和顏色運算的功能。通過重載ModifyVertices這個方法,你可以不實用Shader直接在腳本里對UI的渲染方式進行修飾。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM