Unity幸运转盘实战项目

 更新时间:2020年6月25日 10:36  点击:1273

幸运转盘主要是由两部分组成——转盘、指针,实现的方式也分两种,转盘动或者指针动,不过两者的原理都是一样的,这里就以指针动做了一个项目级的demo(由于后面的圆盘中间的那条竖线有点往左偏,所以导致那些圣诞老人的显示有些偏移)。< Demo 下载 >

 

在项目开发中,一般这个功能的实现过程是:

1、当点击开始的时候,转盘开始动, 同时向服务端发送协议;

2、服务端返回数据(前端计算好对应的角度),当转盘旋转一定时间后开始减速直至对应角度

当然也可以等服务端返回数据后再开始模拟旋转过程,但是由于受网络的影响,这一过程可能会较长,表现效果不是很好。

关于Unity的旋转,主要有下面几类接口:Transform.Rotate(),  Transform.RotateAround(),Transform.rotation, Transform.eulerAngles。 其中 Rotate() 和 RotateAround() 都是同一类接口(里面的具体重载这里就不细说了),都是指从当前位置做指定角度的偏移,而 rotation 和 eulerAngles 都是直接赋值的字段,rotation 是一个四元数类型, eulerAngles 则是一个欧拉角。很显然,我们在做旋转的时候不需要关心具体角度,使用 Rotate() 类型做定帧偏移是最合适的,通过设置偏移的角度就能实现变速转动,比较适合转盘开始阶段的加速过程和中间的匀速过程,而当我们知道停止的具体角度时,则可已利用差值运算能精准地实现减速过程并最终停到我们需要的位置。但是有一点需要注意,Unity里面角度是逆时针计算的,而我们日常生活中一般习惯于顺时针,所以,最终的角度还需要取反一下。废话不多说,见代码:

using UnityEngine;
using UnityEngine.UI;
 
public class LuckyTurntable : MonoBehaviour
{
 public enum State
 {
  None,  //待机状态
  Start,  //加速阶段
  Prepared, //等待数据阶段
  End,  //减速阶段
 }
 
 public delegate void OnFinishCallback();
 private event OnFinishCallback OnFinish;
 
 /// <summary>
 /// 设置完成时的回调
 /// </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>
 /// 转盘的状态
 /// </summary>
 public State CurState
 {
  get
  {
   return _state;
  }
  private set
  {
   _state = value;
   switch (value)
   {
    //不同阶段限制各按钮的点击状态
    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]这个区间
   _endAngle = -_endAngle - 360 * 2; //多N圈并取反,圈数能使减速阶段变得更长,显示更自然,逼真
  }
 }
 
 /// <summary>
 /// 加速持续时间
 /// </summary>
 private readonly float AcceleateTime = 1f;
 
 /// <summary>
 /// 减速前的最短持续时间
 /// </summary>
 private float _minTime = 3.0f;
 /// <summary>
 /// 角度缓存
 /// </summary>
 private float _tmpAngle = 0f;
 /// <summary>
 /// 时间统计
 /// </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)
  {
   //通过差值运算实现精准地旋转到指定角度(球型插值无法实现大于360°的计算)
   float k = 2f; //如果嫌减速太慢,可以加个系数修正一下
   _tmpAngle = Mathf.Lerp(_tmpAngle, EndAngle, Time.deltaTime * k);
 
   //这里只存在一个方向的旋转,所以不存在欧拉角万向节的问题,所以使用欧拉角和四元数直接赋值都是可以的
   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
  {
   //利用一个速度因子实现变加速的过程
   _factor = _time / AcceleateTime;
   _factor = _factor > 1 ? 1 : _factor;
   node.Rotate(Vector3.back, _factor * velocity * Time.deltaTime, Space.Self);
  }
 
  //当收到数据之后并且旋转了一定时间后开始减速
  if (CurState == State.Prepared && _time > _minTime)
  {
   CurState = State.End;
   _tmpAngle = GetCurClockwiseAngle();
  }
 }
 
 /// <summary>
 /// 将当前指针的欧拉角转换成顺时针统计角度
 /// </summary>
 /// <returns></returns>
 private float GetCurClockwiseAngle()
 {
  //由于读取到的值是[0, 180] U [-180, 0],左边由0至180递增,右边由180转变成-180,然后递增至0,所以需要转相应的转换
  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>
 /// 随机一个角度并停止
 /// </summary>
 private void OnRandomClick()
 {
  EndAngle = UnityEngine.Random.Range(0f, 360f);
  CurState = State.Prepared;
 }
}

功能代码基本都在上面了,如果想要Demo的话可 前往下载 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

[!--infotagslink--]

相关文章

  • Unity时间戳的使用方法

    这篇文章主要为大家详细介绍了Unity时间戳的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • 利用Javascript实现简单的转盘抽奖

    这篇文章主要介绍了利用Javascript实现的简单的转盘抽奖,文中分享了两种抽奖效果,一种是默认转动,一种是需要点击开始转动的,并给出了晚上的示例代码,需要的朋友可以参考借鉴,下面来一起看看吧。...2017-02-19
  • Unity中 ShaderGraph 实现旋涡传送门效果入门级教程(推荐)

    通过Twirl 旋转节点对Gradient Noise 梯度噪声节点进行操作,就可得到一个旋转的旋涡效果。具体实现代码跟随小编一起通过本文学习下吧...2021-07-11
  • Unity延时执行的多种方法小结

    本文主要介绍了4种延时执行的方法,主要包括Update计时器,Invoke,协程,DoTween,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-07-07
  • Unity shader实现遮罩效果

    这篇文章主要为大家详细介绍了Unity shader实现遮罩效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • unity 如何判断鼠标是否在哪个UI上(两种方法)

    这篇文章主要介绍了unity 判断鼠标是否在哪个UI上的两种实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-10
  • 利用unity代码C#封装为dll的步骤分享

    这篇文章主要给大家介绍了关于利用unity代码C#封装为dll的相关资料,文中通过图文将实现的方法介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • Unity实现换装系统

    这篇文章主要为大家详细介绍了Unity实现换装系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-04-11
  • Unity Shader实现径向模糊效果

    这篇文章主要为大家详细介绍了Unity Shader实现径向模糊效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-08-09
  • unity 实现摄像机绕某点旋转一周

    这篇文章主要介绍了unity 实现摄像机绕某点旋转一周,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • Unity实现截图功能

    这篇文章主要为大家详细介绍了Unity实现截图功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity中EventTrigger的几种使用操作

    这篇文章主要介绍了Unity中EventTrigger的几种使用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-10
  • Unity Shader实现2D水流效果

    这篇文章主要为大家详细介绍了Unity Shader实现2D水流效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity 按钮添加OnClick事件操作

    这篇文章主要介绍了Unity 按钮添加OnClick事件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-10
  • Unity使用EzySlice实现模型多边形顺序切割

    这篇文章主要为大家详细介绍了Unity使用EzySlice实现模型多边形顺序切割,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-11-03
  • unity 切换场景不销毁物体问题的解决

    这篇文章主要介绍了unity 切换场景不销毁物体问题的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-14
  • Unity Shader实现描边OutLine效果

    这篇文章主要为大家详细介绍了Unity Shader实现描边OutLine效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity Shader实现裁切效果

    这篇文章主要为大家详细介绍了Unity Shader实现裁切效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • unity实现车方向盘转动效果

    这篇文章主要为大家详细介绍了unity实现车方向盘转动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Unity实现汽车前后轮倒车轨迹计算

    这篇文章主要为大家详细介绍了Unity实现汽车前后轮倒车轨迹计算,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-13