unity3d5.1物體橢圓旋轉選擇介面實現(一)
偶然在群裡看到有人拿了一張橢圓物體旋轉選擇介面來問怎麼實現(也不知道這樣描述對不對,反正是橢圓的,而且還是旋轉的,類似於關卡和角色選擇),於是
想了下自己寫了一個類似的功能,方法可能不是很完美,但是也算是一個思路吧,就當練練手熟悉unity。原圖如下:
附自己完成後的效果圖:
遺憾的是不會做動態圖片,也不知道大神寫部落格是怎麼弄執行程式碼時的動態效果圖,只能附上渣渣圖片了~
基本效果能夠達到一致,但是隻是直接移動,原本是想實現繞橢圓軌跡移動,這裡不得不說,unity動作機制幾乎沒有,原本api就難找,自己找半天連一個move的函
數都沒有,如果不去找一個外掛,只能通過update每一幀去手動設定GameObject的位置來達到move的效果,原本我以為是能夠像cocos那樣,最起碼,moveto,得有,
然後用貝塞爾模擬,可惜只能每幀重新整理的話就先不寫了。
一設計思路
-
方塊的擺佈:
首先需要明確的是方塊的排布問題,擺佈有多種方式,可以先將所有的方塊儲存到容器,之後按照一定的座標差值來遞增,遞減這些方塊的擺放位置,最後達到
該視覺效果,只是在排列的過程中需要長時間的除錯效果,因而沒有采用;同時也可以按照橢圓的軌跡來擺放,根據物件容器的遍歷,每次遞增或遞減一定角度
達到該效果,這個方式是比較方便的,只需要根據當前角度偏移量來計算出方塊對應的位置即可。當然,我們還需要考慮方塊的奇偶性,在方塊為奇數時,除去
第一個顯示在正中央的方塊,剛好還剩下偶數個方塊,左右正好排布一半,但是當方塊為偶數個時,除去第一個,還會剩下最後一個方塊。
- 方塊為奇數時: 該情況較為簡單,除去第一個,剩下的剛好對半分成,可以這樣考慮:將所有需要排布的方塊Object存放到一個數組sprites裡邊,取size=(length+1)/2
例如有七個方塊,前邊size個(四個)從中間開始往右遞增排布,即保證容器前size個是順次排布,剩下三個從中間(除去中間那個點)往左邊排布。
- 方塊為偶數時: 該情況稍微複雜一點,除去第一個,再分去左右對稱的,還會多出一個來,可以這樣考慮:將所有方塊存放到一個數組sprites裡,取size=length/2
例如有八個方塊,前邊size個(四個)從中間開始往右遞增排布,剩下三個從中間(除去中間那個點)往左邊排布,最後一個可以放到第一個的正對面。
-
顯示層級: 在cocos2dx中,子類節點都是通過掛載到父節點的形式新增到場景中,在addchild的時候提供一個zorder引數,即精靈的渲染層級,而
unity不同,查詢api找了半天,最後找到SetSiblingIndex函式,值越大越後顯示,沒次初始化和移動都必須重置顯示層級,所以需要單獨封裝函式。
- 方塊為奇數時: 該情況較為簡單,除去第一個,剩下的剛好對半分成,可以這樣考慮:將所有需要排布的方塊Object存放到一個數組sprites裡邊,取size=(length+1)/2
-
點選按鈕之後的回撥
- 向左按鈕:點擊向左按鈕時,右邊的方塊同一往左移一格位置,左邊的方塊統一往上移一格位置,左邊最後一個方塊移動到右邊最後一個方塊
- 向右按鈕:同理。
二開始動手開發
- 新建場景
- 新建專案:2d,3d無所謂,這裡是3d,但是要用一般是在2d,只是專案而已。
- 新增控制元件:首先新增七個Image物件(控制元件可以是按鈕,都行);新增left和right的button,擺佈沒有要求,隨意擺放,反正都是要做排序的。
- 如圖:(這裡panel是沒必要的,我多加的)
- 新增UI按橢圓順序排布指令碼
- 新建指令碼:Ellipse.cs指令碼,物件繫結到Canvas物件。
- 編寫程式碼:
執行後可以看到如圖效果(不要忘了把這幾個物件拖到腳本里,中心點是傳入的物件,所以有一個位置要擺好,擺在想要的中心點中,也可以自己改成手動輸入x,y,z)://儲存需要排序的精靈容器 public GameObject[] Sprites; public Transform centerPoint;//橢圓的中心點 public float anglecheap = 25;//每個方塊間的角度偏移 //儲存位置點 private List<Vector3> location = new List<Vector3>(); private float angle =270;//第一個保證是中心位置的,當前到的角度 private float firstangle = 270;//記錄第一個角度,用以左右對稱 private float r =90;//橢圓的兩個弦長 private float R = 150; int size = 0;//即物件陣列的一半,奇數為總長度+1/2,偶數為一半<pre name="code" class="csharp">// Use this for initialization void Start () {//初始化size if (Sprites.Length % 2 == 0) { size = Sprites.Length / 2; } else { size = (Sprites.Length + 1) / 2; } //排序分級顯示 makespriteSort(); //重置渲染層級 ResetDeep(); } //給這些精靈排序顯示 void makespriteSort() { //取出橢圓的中心點 Vector3 center = centerPoint.position; //判斷該陣列的個數奇偶性,如果是偶數,那麼需要留出一個來放到對面 if (Sprites.Length % 2 == 0) { //右半邊 for (int i = 0; i < size; i++) { Sprites[i].transform.position = getPosition(angle, center); // m_rightsprite.Add(Sprites[i]); angle += anglecheap; } //第一個已經得是左邊了 angle = firstangle - anglecheap; //左半邊 for (int i = size; i < Sprites.Length-1; i++) { Sprites[i].transform.position = getPosition(angle, center); angle -= anglecheap; // m_leftsprite.Add(Sprites[i]); } //最後一個 Sprites[Sprites.Length - 1].transform.position = getPosition(firstangle-180, center); // m_leftsprite.Add(Sprites[Sprites.Length - 1]); return; } //如果不是偶數,那麼出去中間那個,正好正常顯示 else { //右半邊 for (int i = 0;i<size; i++) { Sprites[i].transform.position = getPosition(angle, center); // m_rightsprite.Add(Sprites[i]); angle += anglecheap; } //第一個已經得是左邊了 angle = firstangle - anglecheap; //左半邊 for (int i = size;i < Sprites.Length; i++) { Sprites[i].transform.position = getPosition(angle, center); // m_leftsprite.Add(Sprites[i]); angle -= anglecheap; } return; } } //獲取當前角度的座標 Vector3 getPosition(float _angle,Vector3 _centerposition) { float hudu = (_angle/180f) * Mathf.PI; float cosx = Mathf.Cos(hudu); float sinx = Mathf.Sin(hudu); float x = _centerposition.x + R * cosx; float y = _centerposition.y + r * sinx; Vector3 point = new Vector3(x, y, 0); //新增到容器儲存 location.Add(point); return point; } //根據當前左右容器調整所有控制元件的渲染層級 void ResetDeep() { dep = 0; //右半邊 for (int i =size-1; i>=0; i--) { Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep); dep++; } dep = 0; //左半邊 for (int i = Sprites.Length - 1; i >=size; i--) { Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep); dep++; } }