NGUI 作為 Unity 早期主流 UI 框架,許多存量專案仍在維護中。本文提供一份完整、可直接落地的 NGUI 滑動翻頁實作,涵蓋觸控偵測、閾值判斷、Tween 位移動畫與頁碼狀態機,適合快速接手舊專案或學習 NGUI 事件機制的開發者。
PAGE_WIDTH = 2048),總頁數 ITEM_NUM。UIEventListener 監聽 OnPress 事件,記錄按下/抬起座標。TweenPosition 執行 EaseInOut 緩動動畫,動畫完成回調更新頁碼狀態。| 常數 | 預設值 | 用途 |
|---|---|---|
| ITEM_NUM | 2 | 總頁數 |
| PAGE_WIDTH | 2048 | 單頁寬度(像素) |
| DRAG_SPEED | 0.5f | 翻頁動畫時長(秒) |
| DRAG_OFFECT | 30 | 觸發翻頁的最小水平位移閾值 |
using UnityEngine;
using System.Collections;
public class PageView : MonoBehaviour
{
const int ITEM_NUM = 2;
const int PAGE_WIDTH = 2048;
const float DRAG_SPEED = 0.5f;
const int DRAG_OFFECT = 30;
float beganX, beganY;
int curIndex = 1;
bool isPlay = false, isPress = false;
bool isPageFoot = false, isHomePage = true;
string left = "left", right = "right";
GameObject[] Item_Objects;
void Start() => Init();
void Init()
{
Item_Objects = new GameObject[ITEM_NUM];
for (int i = 1; i <= ITEM_NUM; ++i)
{
Transform trans = transform.Find("item" + i);
if (trans != null)
{
GameObject spr = trans.Find("Background").gameObject;
spr.AddComponent();
UIEventListener.Get(spr).onPress = OnPressEvent;
Item_Objects[i - 1] = trans.gameObject;
}
}
}
void OnPressEvent(GameObject obj, bool isDown)
{
if (isDown)
{
beganX = UICamera.lastTouchPosition.x;
beganY = UICamera.lastTouchPosition.y;
isPress = true;
}
else
{
float endX = UICamera.lastTouchPosition.x;
float endY = UICamera.lastTouchPosition.y;
if (isPress && !isPlay)
{
float delta = endX - beganX;
if (delta > DRAG_OFFECT && !isHomePage) RightDrag();
else if (delta < -DRAG_OFFECT && !isPageFoot) LeftDrag();
}
isPress = false;
}
}
void LeftDrag()
{
isPlay = true;
float x = transform.localPosition.x - PAGE_WIDTH;
var tween = TweenPosition.Begin(gameObject, DRAG_SPEED, new Vector3(x, 0, 0));
tween.method = UITweener.Method.EaseInOut;
tween.callWhenFinished = "callback";
tween.name = left;
tween.Reset();
}
void RightDrag()
{
isPlay = true;
float x = transform.localPosition.x + PAGE_WIDTH;
var tween = TweenPosition.Begin(gameObject, DRAG_SPEED, new Vector3(x, 0, 0));
tween.method = UITweener.Method.EaseInOut;
tween.callWhenFinished = "callback";
tween.name = right;
tween.Reset();
}
void callback(UITweener tween)
{
isPlay = false;
if (tween.name == left) curIndex++;
else if (tween.name == right) curIndex--;
isHomePage = (curIndex == 1);
isPageFoot = (curIndex == ITEM_NUM);
}
}
範例掛載在各頁面的 Background 物件上,確保其有 BoxCollider 且屬於 UI Layer,否則 UICamera 無法偵測觸控。
NGUI 使用 UICamera.lastTouchPosition 取得螢幕座標(非世界座標),直接相減即可得到水平位移,無需轉換。
isPlay 標記防止動畫播放期間重複觸發;isPress 確保只有完整的 Press→Release 才判定翻頁。
isHomePage / isPageFoot 防止超出首尾頁;若需循環翻頁,可在回調中重排子物件位置並重置 curIndex。
將 ITEM_NUM、PAGE_WIDTH 改為 public 或從配置讀取,即可支援任意頁數。
callback 中發送事件或直接操作底部 Dot 圖集切換。SpringPanel 或自行實作速度衰減,配合 OnDrag 即時位移。ContextMenu 一鍵生成頁面預製體與自動計算寬度。NGUI 翻頁的核心在於「觸控位移判斷 + Tween 位移動畫 + 狀態機同步」。本範例邏輯清晰、耦合度低,直接拖入專案即可使用。若專案已遷移至 UGUI,建議參考上一篇 ScrollRect 方案;若維護舊專案,此實作足以應對大多數翻頁需求。