Unity幸運(yùn)轉(zhuǎn)盤實(shí)戰(zhàn)項(xiàng)目
幸運(yùn)轉(zhuǎn)盤主要是由兩部分組成——轉(zhuǎn)盤、指針,實(shí)現(xiàn)的方式也分兩種,轉(zhuǎn)盤動(dòng)或者指針動(dòng),不過兩者的原理都是一樣的,這里就以指針動(dòng)做了一個(gè)項(xiàng)目級(jí)的demo(由于后面的圓盤中間的那條豎線有點(diǎn)往左偏,所以導(dǎo)致那些圣誕老人的顯示有些偏移)。< Demo 下載 >
在項(xiàng)目開發(fā)中,一般這個(gè)功能的實(shí)現(xiàn)過程是:
1、當(dāng)點(diǎn)擊開始的時(shí)候,轉(zhuǎn)盤開始動(dòng), 同時(shí)向服務(wù)端發(fā)送協(xié)議;
2、服務(wù)端返回?cái)?shù)據(jù)(前端計(jì)算好對(duì)應(yīng)的角度),當(dāng)轉(zhuǎn)盤旋轉(zhuǎn)一定時(shí)間后開始減速直至對(duì)應(yīng)角度
當(dāng)然也可以等服務(wù)端返回?cái)?shù)據(jù)后再開始模擬旋轉(zhuǎn)過程,但是由于受網(wǎng)絡(luò)的影響,這一過程可能會(huì)較長(zhǎng),表現(xiàn)效果不是很好。
關(guān)于Unity的旋轉(zhuǎn),主要有下面幾類接口:Transform.Rotate(), Transform.RotateAround(),Transform.rotation, Transform.eulerAngles。 其中 Rotate() 和 RotateAround() 都是同一類接口(里面的具體重載這里就不細(xì)說了),都是指從當(dāng)前位置做指定角度的偏移,而 rotation 和 eulerAngles 都是直接賦值的字段,rotation 是一個(gè)四元數(shù)類型, eulerAngles 則是一個(gè)歐拉角。很顯然,我們?cè)谧鲂D(zhuǎn)的時(shí)候不需要關(guān)心具體角度,使用 Rotate() 類型做定幀偏移是最合適的,通過設(shè)置偏移的角度就能實(shí)現(xiàn)變速轉(zhuǎn)動(dòng),比較適合轉(zhuǎn)盤開始階段的加速過程和中間的勻速過程,而當(dāng)我們知道停止的具體角度時(shí),則可已利用差值運(yùn)算能精準(zhǔn)地實(shí)現(xiàn)減速過程并最終停到我們需要的位置。但是有一點(diǎn)需要注意,Unity里面角度是逆時(shí)針計(jì)算的,而我們?nèi)粘I钪幸话懔?xí)慣于順時(shí)針,所以,最終的角度還需要取反一下。廢話不多說,見代碼:
using UnityEngine;
using UnityEngine.UI;
public class LuckyTurntable : MonoBehaviour
{
public enum State
{
None, //待機(jī)狀態(tài)
Start, //加速階段
Prepared, //等待數(shù)據(jù)階段
End, //減速階段
}
public delegate void OnFinishCallback();
private event OnFinishCallback OnFinish;
/// <summary>
/// 設(shè)置完成時(shí)的回調(diào)
/// </summary>
/// <param name="onFinish"></param>
public void SetOnFinishCallback(OnFinishCallback onFinish)
{
OnFinish += onFinish;
}
/// <summary>
/// 最大速度
/// </summary>
public int velocity = 3000;
public Transform node;
public Button btnStart;
public Button btnStop;
public Button btnRandom;
public InputField input;
private State _state;
/// <summary>
/// 轉(zhuǎn)盤的狀態(tài)
/// </summary>
public State CurState
{
get
{
return _state;
}
private set
{
_state = value;
switch (value)
{
//不同階段限制各按鈕的點(diǎn)擊狀態(tài)
case State.None:
btnStart.enabled = true;
btnStop.enabled = false;
btnRandom.enabled = false;
break;
case State.Start:
btnStart.enabled = false;
btnStop.enabled = true;
btnRandom.enabled = true;
break;
case State.Prepared:
case State.End:
btnStart.enabled = false;
btnStop.enabled = false;
btnRandom.enabled = false;
break;
}
}
}
private float _endAngle = 0f;
/// <summary>
/// 最終停止的角度[0, 360]
/// </summary>
public float EndAngle
{
get
{
return _endAngle;
}
set
{
_endAngle = Mathf.Abs(value);
print("End Angle: " + value);
_endAngle = _endAngle % 360; //將角度限定在[0, 360]這個(gè)區(qū)間
_endAngle = -_endAngle - 360 * 2; //多N圈并取反,圈數(shù)能使減速階段變得更長(zhǎng),顯示更自然,逼真
}
}
/// <summary>
/// 加速持續(xù)時(shí)間
/// </summary>
private readonly float AcceleateTime = 1f;
/// <summary>
/// 減速前的最短持續(xù)時(shí)間
/// </summary>
private float _minTime = 3.0f;
/// <summary>
/// 角度緩存
/// </summary>
private float _tmpAngle = 0f;
/// <summary>
/// 時(shí)間統(tǒng)計(jì)
/// </summary>
private float _time;
/// <summary>
/// 速度變化因子
/// </summary>
private float _factor;
private void Start()
{
CurState = State.None;
btnStart.onClick.AddListener(OnStartClick);
btnStop.onClick.AddListener(OnStopClick);
btnRandom.onClick.AddListener(OnRandomClick);
}
private void Update()
{
if (CurState == State.None)
return;
_time += Time.deltaTime;
if (CurState == State.End)
{
//通過差值運(yùn)算實(shí)現(xiàn)精準(zhǔn)地旋轉(zhuǎn)到指定角度(球型插值無法實(shí)現(xiàn)大于360°的計(jì)算)
float k = 2f; //如果嫌減速太慢,可以加個(gè)系數(shù)修正一下
_tmpAngle = Mathf.Lerp(_tmpAngle, EndAngle, Time.deltaTime * k);
//這里只存在一個(gè)方向的旋轉(zhuǎn),所以不存在歐拉角萬向節(jié)的問題,所以使用歐拉角和四元數(shù)直接賦值都是可以的
node.rotation = Quaternion.Euler(0, 0, _tmpAngle);
//node.eulerAngles = new Vector3(0, 0, _tmpAngle);
if (1 >= Mathf.Abs(_tmpAngle - EndAngle))
{
CurState = State.None;
if (null != OnFinish)
{
OnFinish();
OnFinish = null;
}
}
}
else
{
//利用一個(gè)速度因子實(shí)現(xiàn)變加速的過程
_factor = _time / AcceleateTime;
_factor = _factor > 1 ? 1 : _factor;
node.Rotate(Vector3.back, _factor * velocity * Time.deltaTime, Space.Self);
}
//當(dāng)收到數(shù)據(jù)之后并且旋轉(zhuǎn)了一定時(shí)間后開始減速
if (CurState == State.Prepared && _time > _minTime)
{
CurState = State.End;
_tmpAngle = GetCurClockwiseAngle();
}
}
/// <summary>
/// 將當(dāng)前指針的歐拉角轉(zhuǎn)換成順時(shí)針統(tǒng)計(jì)角度
/// </summary>
/// <returns></returns>
private float GetCurClockwiseAngle()
{
//由于讀取到的值是[0, 180] U [-180, 0],左邊由0至180遞增,右邊由180轉(zhuǎn)變成-180,然后遞增至0,所以需要轉(zhuǎn)相應(yīng)的轉(zhuǎn)換
return (-1) * (360 - node.eulerAngles.z) % 360;
}
private void OnStartClick()
{
CurState = State.Start;
_time = 0;
}
/// <summary>
/// 讀取輸入框中的角度并停止
/// </summary>
private void OnStopClick()
{
try
{
EndAngle = float.Parse(input.text);
}
catch
{
EndAngle = 0f;
}
CurState = State.Prepared;
}
/// <summary>
/// 隨機(jī)一個(gè)角度并停止
/// </summary>
private void OnRandomClick()
{
EndAngle = UnityEngine.Random.Range(0f, 360f);
CurState = State.Prepared;
}
}
功能代碼基本都在上面了,如果想要Demo的話可 前往下載 。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:詳解C#設(shè)置Excel數(shù)據(jù)自適應(yīng)行高、列寬的2種情況
欄 目:C#教程
下一篇:Unity3D實(shí)現(xiàn)物體閃爍效果
本文標(biāo)題:Unity幸運(yùn)轉(zhuǎn)盤實(shí)戰(zhàn)項(xiàng)目
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/4781.html
您可能感興趣的文章
- 01-10Unity3d獲取系統(tǒng)時(shí)間
- 01-10Unity3D獲取當(dāng)前鍵盤按鍵及Unity3D鼠標(biāo)、鍵盤的基本操作
- 01-10Unity UGUI教程之實(shí)現(xiàn)滑頁效果
- 01-10C#使用Protocol Buffer(ProtoBuf)進(jìn)行Unity中的Socket通信
- 01-10C#在Unity游戲開發(fā)中進(jìn)行多線程編程的方法
- 01-10C#中Socket與Unity相結(jié)合示例代碼
- 01-10C#實(shí)現(xiàn)JSON解析器MojoUnityJson功能(簡(jiǎn)單且高效)
- 01-10Unity中C#和Java的相互調(diào)用實(shí)例代碼
- 01-10利用unity代碼C#封裝為dll的步驟分享
- 01-10Unity3D實(shí)現(xiàn)批量下載圖片功能


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文


