1. 程式人生 > >Unity3d使用 NGUI 做球形三維旋轉 UI

Unity3d使用 NGUI 做球形三維旋轉 UI

因為工作的需要研究了一下NGUI做球形三維旋轉的UI,初步作出了一個雛形,現在拿出來和大家分享,如果我有哪裡寫錯了或者做的不好請指出並給我一些建議。

我在這裡用的是2.6版本的NGUI,3.0版本的OnFinished較2.6版本有一點點的改進,如下

void Start ()
{
    TweenScale scale = GetComponent<TweenScale>();
    EventDelegate.Add (scale.onFinished, OnFinished);
}
 
void OnFinished ()
{
    Debug.Log(TweenScale.current.name);
}
引用自 momo 的 http://unity3d.9tech.cn/news/2013/1114/38624.html

首先,我的素材用的是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,結束,非常完美!