Unity3d使用 NGUI 做球形三維旋轉 UI
阿新 • • 發佈:2018-12-27
因為工作的需要研究了一下NGUI做球形三維旋轉的UI,初步作出了一個雛形,現在拿出來和大家分享,如果我有哪裡寫錯了或者做的不好請指出並給我一些建議。
我在這裡用的是2.6版本的NGUI,3.0版本的OnFinished較2.6版本有一點點的改進,如下
引用自 momo 的 http://unity3d.9tech.cn/news/2013/1114/38624.html。void Start () { TweenScale scale = GetComponent<TweenScale>(); EventDelegate.Add (scale.onFinished, OnFinished); } void OnFinished () { Debug.Log(TweenScale.current.name); }
首先,我的素材用的是5個按鈕做的,所以我按照正五邊形的位置進行擺放。如下圖所示:
然後下面是兩個程式碼類
程式碼類1,託拽到所有的按鈕上,主要的動畫操作也在這個類裡面進行。
using UnityEngine; using System.Collections; // 用來標記UI的位置,也就是說,在最前面的UI永遠為 pos0 public enum ThisPos { pos0, pos1, pos2, pos3, pos4 } public class RotationNGUI : MonoBehaviour { public ThisPos thePos = ThisPos.pos2; //是否向左滑動 bool isRight = false; //是否向右滑動 bool isLeft = false; // Tween 動畫的持續時間 float duration = 0.7f; // 預先按照 UI 做好的位置,並手動託拽到屬性檢視器面板中 public Transform tran0; public Transform tran1; public Transform tran2; public Transform tran3; public Transform tran4; // Use this for initialization void Start() { // 如果不手動拖預先做好的位置,也可以通過預先做的位置的 tag 獲取它 //tran0 = GameObject.FindGameObjectWithTag("0").transform; } // Update is called once per frame void Update() { UpdateUIState(); OnTweenUI(); } // 更新UI的狀態,最前面的狀態為0 並且逆時針遞增 void UpdateUIState() { if(transform.localPosition == tran0.localPosition) { thePos = ThisPos.pos0; } if(transform.localPosition == tran1.localPosition) { thePos = ThisPos.pos1; } if(transform.localPosition == tran2.localPosition) { thePos = ThisPos.pos2; } if(transform.localPosition == tran3.localPosition) { thePos = ThisPos.pos3; } if(transform.localPosition == tran4.localPosition) { thePos = ThisPos.pos4; } } // 變換UI的位置、深度和透明度 void OnTweenUI() { if(isLeft) { if(thePos == ThisPos.pos0) { // Change UISprite TweenAlpha to 0.6f and UISprite.Depth to 0 AlphaChange(0.85f, 0.6f, 0); // Change TweenTransform to front-left TransformChange(transform, tran4); } if(thePos == ThisPos.pos1) { // Change UISprite TweenAlpha to 0.85f and UISprite.Depth to 4 AlphaChange(0.6f, 0.85f, 4); // Change TweenTransform to forward TransformChange(transform, tran0); } if(thePos == ThisPos.pos2) { // Change UISprite TweenAlpha to 0.6f and UISprite.Depth to 0 AlphaChange(0.4f, 0.6f, 0); // Change TweenTransform to front-right TransformChange(transform, tran1); } if(thePos == ThisPos.pos3) { // Change UISprite TweenAlpha to 0.4f and UISprite.Depth to -1 AlphaChange(0.4f, 0.4f, -1); // Change TweenTransform to back-right TransformChange(transform, tran2); } if(thePos == ThisPos.pos4) { // Change UISprite TweenAlpha to 0.4f and UISprite.Depth to -1 AlphaChange(0.6f, 0.4f, -1); // Change TweenTransform to back-left TransformChange(transform, tran3); } isLeft = false; } if(isRight) { if(thePos == ThisPos.pos0) { // Change UISprite TweenAlpha to 0.6f and UISprite.Depth to 0 AlphaChange(0.85f, 0.6f, 0); // Change TweenTransform to front-right TransformChange(transform, tran1); } if(thePos == ThisPos.pos1) { // Change UISprite TweenAlpha to 0.4f and UISprite.Depth to -1 AlphaChange(0.6f, 0.4f, -1); // Change TweenTransform to back-right TransformChange(transform, tran2); } if(thePos == ThisPos.pos2) { // Change UISprite TweenAlpha to 0.4f and UISprite.Depth to -1 AlphaChange(0.4f, 0.4f, -1); // Change TweenTransform to back-left TransformChange(transform, tran3); } if(thePos == ThisPos.pos3) { // Change UISprite TweenAlpha to 0.6f and UISprite.Depth to 0 AlphaChange(0.4f, 0.6f, 0); // Change TweenTransform to front-left TransformChange(transform, tran4); } if(thePos == ThisPos.pos4) { // Change UISprite TweenAlpha to 0.85f and UISprite.Depth to 4 AlphaChange(0.6f, 0.85f, 4); // Change TweenTransform to forward TransformChange(transform, tran0); } isRight = false; } } // 用來控制 UI 背景的透明度和深度 void AlphaChange(float alphaForm, float alphaTo, int UIDepth) { UISprite sprite = gameObject.GetComponentInChildren<UISprite>(); sprite.depth = UIDepth; TweenAlpha alp = TweenAlpha.Begin(sprite.gameObject, duration, alphaTo); alp.from = alphaForm; } // 用來控制 UI 的 Transform 位置,包括了 position 、rotation、和 scale void TransformChange(Transform tranformForm, Transform tranformTo) { TweenTransform tran = TweenTransform.Begin(gameObject, duration, tranformTo); tran.from = tranformForm; tran.eventReceiver = gameObject; tran.callWhenFinished = "OnFinishedDestroyTheTween"; } // 當動畫結束時呼叫 void OnFinishedDestroyTheTween() { Destroy(GetComponentInChildren<TweenAlpha>()); Destroy(GetComponent<TweenTransform>()); } // 用作另一個類呼叫,也可以把 isLeft 和 isRight 變數 宣告為 public public void OnChangeDarg(bool Left) { if(Left) isLeft = true; else isRight = true; } }
程式碼類2 主要用於觸發動畫的類,把它託拽到兩個按鈕和 旋轉 UI 的父節點上,記住父節點需要加上Collider觸發器才能觸發 OnDrag 事件。using UnityEngine; using System.Collections; // 用來區別 按鈕和父節點 public enum DragButton { drag, buttonLeft, buttonRight } public class DragRotationPanel : MonoBehaviour { public DragButton ButtonState; //public Transform[] childs; //是否觸控 bool isTouch = false; //是否向左滑動 //是否正在滑動中 bool isOnDrag = false; // Use this for initialization void Start() { } // Update is called once per frame void Update () { } void OnClick() { if(!isTouch) { // 按下左邊的按鈕 if(ButtonState == DragButton.buttonLeft) { RotationNGUI[] rotNGUI = gameObject.transform.parent.GetComponentsInChildren<RotationNGUI>(); foreach(RotationNGUI rot in rotNGUI) { rot.OnChangeDarg(true); } } // 按下右邊的按鈕 if(ButtonState == DragButton.buttonRight) { RotationNGUI[] rotNGUI = gameObject.transform.parent.GetComponentsInChildren<RotationNGUI>(); foreach(RotationNGUI rot in rotNGUI) { rot.OnChangeDarg(false); } } isTouch = true; StartCoroutine(waitForNextTouch()); } } void OnDrag(Vector2 delta) { if(ButtonState == DragButton.drag) { //為了避免事件衝突 //這裡只判斷一個滑動的事件 if(!isTouch) { if(delta.x > 0.2f) { //向左滑動 //isRight = true; //isOnDrag = true; RotationNGUI[] rotNGUI = gameObject.transform.parent.GetComponentsInChildren<RotationNGUI>(); foreach(RotationNGUI rot in rotNGUI) { rot.OnChangeDarg(false); } } else if(delta.x < -0.2f) { //向右滑動 //isLeft = true; //isOnDrag = true; RotationNGUI[] rotNGUI = GetComponentsInChildren<RotationNGUI>(); foreach(RotationNGUI rot in rotNGUI) { rot.OnChangeDarg(true); } } isTouch = true; StartCoroutine(waitForNextTouch()); } } } // 協同,等 Tween 結束後 才可進行下一次操作,避免 Tween 的錯誤 IEnumerator waitForNextTouch() { yield return new WaitForSeconds(0.7f); isTouch = false; } }
最後,你做完的 UI 層次 應該像這樣的,如下圖OK,結束,非常完美!