3、轮盘抽奖——指针动型

作者: GameObjectLgy | 来源:发表于2020-08-23 18:57 被阅读0次

指针动型和盘动型原理也差不多,都是分成加速阶段,减速阶段,结束。这次增加了一个向服务器获取转盘结果数据的等待阶段。

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;
    }
}
2.png

参考资料

相关文章

  • 3、轮盘抽奖——指针动型

    指针动型和盘动型原理也差不多,都是分成加速阶段,减速阶段,结束。这次增加了一个向服务器获取转盘结果数据的等待阶段。...

  • iOS 抽奖轮盘效果实现思路

    iOS 抽奖轮盘效果实现思路 iOS 抽奖轮盘效果实现思路

  • 抽奖轮盘

  • 第六章:余下的订单

    叶青点了中间【抽奖】选择,轮盘立刻旋转起来。 “大大大~”叶青喊着,东西当然是越大越值钱。 所以当指针慢慢停在了【...

  • 轮盘抽奖--概率计算

  • 「♛BB Club」7月幸运大轮盘,快乐不停止,好礼不停送!今夜

    -「♛BB Club」7月幸运大轮盘,快乐不停止,好礼不停送!今夜你转了吗? BB club酒吧法国轮盘幸运大抽奖...

  • 纪念第一张万卡

    每次抽奖时都在看轮盘的指针会停在哪里,往往都是不偏不倚的停在收益加成卡10的位置上,而这一次,不知是来的太早还是太...

  • 抽奖轮盘去哪了

    这几天,不断有简友说抽奖轮盘找不到了,不能抽奖了! 这是什么情况? 上周我用苹果手机登录了简书,发现的确没有抽奖轮...

  • 新发现

    号外号外,天天抽奖有新发现。 今晚抽奖看到一个新发现。以前的天天抽奖那指针转动之前,总是指着借钻2。今天的指针指到...

  • 【四】Swift-指针&内存管理

    目录 一、指针 1.为什么说指针是不安全的 2.指针类型 3.原始指针的使用 4.泛型指针的使用 5.内存绑定 二...

网友评论

    本文标题:3、轮盘抽奖——指针动型

    本文链接:https://www.haomeiwen.com/subject/mbhwjktx.html