unity 转盘抽奖

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011484013/article/details/78055142

需求
转盘速度开始速度较慢,然后逐渐加速,达到最大速度保持一段时间,然后减速,保证指针最终可以选择到制定角度。

核心内容
1 计算转盘选择角度,使转盘最终可以在制定角度停止
这里写图片描述

首先需要获取旋转终点的坐标,通过坐标获取目标方向的向量
在单位圆上任意一点的坐标可以表示为(cos(angle),sin(angle))
目标点的方向向量为

Vector3 calculateDir(float endAngle){
        float radiansX =  Mathf.Cos( Mathf.PI *(endAngle + 90) / 180);
        float radiansY = Mathf.Sin( Mathf.PI *(endAngle + 90) / 180);
        return new Vector3 (radiansX, radiansY, 0);

    }

endAngle + 90:因为我们采用的是y轴,所以有90度偏差。

这里主要通过控制旋转对象的y方向 与 目标方向的夹角,进行旋转控制,通过Vector3.Angle (dir1, dir2)判断两个向量的夹角,当夹角小于某一值比如5,我们就可以认为已经旋转到了目标位置

但是如果Vector3.Angle返回的角度是在0-180度之间的,而我们需要的角度是在0-360度之间的,因此需要进行修正,

这里写图片描述
dir1是目标方向,dir2是旋转对象y方向
通过获取目标方向与旋转对象y方向的叉乘结果,如果结果大于0,不需要修正,小于0,需要进行取360度的补交修正。

2转盘速度控制,实现加速、匀速、减速的效果
转盘选择这里采用的是最简单的方式transform.Rotate (new Vector3 (0, 0, speed)) 的方法,通过转盘旋转的时间,动态修改speed的值。

加速:speed初始值为0,通过rotateTimer -= Time.deltaTime进行加速。
匀速:时间控制
if(moveState==1 && (rotateTimer>0 || getAngle()<270)){。。。}
rotateTimer是计时器,计算旋转保持的时间。
moveState是旋转的状态,1表示旋转持续,2表示减速旋转,主要充当标志作用,放置两种状态混淆。
getAngle()<270:当角度在270度以上的时候才开始逐渐减速,否则显示不出来减速的过程。

代码:

using UnityEngine;
using System.Collections;

/// <summary>
/// 通过目标点的角度,计算目标点的位置
/// 计算目标点的位置,计算目标点的方向向量
/// 旋转 转动对象
/// 
/// 速度控制
/// 减速
/// 
/// 判断当前y方向与目标向量的夹角
/// 如果夹角小于某一值,认为达到终点,停止旋转
/// 
/// </summary>
public class RotateTest : MonoBehaviour {

    public float endAngle=100;//旋转停止位置,相对y坐标方向的角度

    public Vector3 targetDir;//目标点的方向向量
    bool isMoving=false;//是否在旋转
    public float speed=0;//当前的旋转速度
    public float maxSpeed=10;//最大旋转速度
    public float minSpeed=0.8f;//最小旋转速度
    float rotateTimer=2;//旋转计时器
    public int moveState=0;//旋转状态,旋转,减速
    public int keepTime = 3;//旋转减速前消耗的时间


    //按照顺时针方向递增
    string[] rewards = {"8等奖","7等奖","6等奖","5等奖","4等奖","3等奖","2等奖","1等奖","10等奖","9等奖"};

    void Start () {
        targetDir = new Vector3 (0, 1, 0);
//      Vector3.Angle (targetDir,transform.up);
    }


    void Update () {
        if(Input.GetKeyDown(KeyCode.A)){
            StartMove ();
        }

        if(Input.GetKey(KeyCode.S)){

            transform.Rotate (new Vector3(0,0,maxSpeed));
        }

        if(isMoving){
            if(moveState==1 && (rotateTimer>0 || getAngle()<270)){//如果旋转时间小于旋转保持时间,或者大于旋转保持时间但是与停止方向角度小于270,继续保持旋转
                rotateTimer -= Time.deltaTime;
                if(speed<maxSpeed) speed +=  1;
                transform.Rotate (new Vector3(0,0,speed));
            }else{//减速旋转,知道停止在目标位置
                moveState = 2;
                if (speed > minSpeed)
                        speed -= 7*speed / 10;
                if (getAngle () > 10)
                        transform.Rotate (new Vector3 (0, 0, speed));
                else {//stop
                    endMove();
                }
            }



        }
    }

    #region 计算当前对象y方向与目标方向的夹角

    float getAngle ()
    {
        return calAngle (targetDir, transform.up);//计算y轴方向的旋转角度
    }
    //计算从dir1旋转到dir2的角度

    float calAngle (Vector3 dir1, Vector3 dir2)
    {
        float angle = Vector3.Angle (dir1, dir2);
        Vector3 normal = Vector3.Cross (dir1, dir2);
        //      Debug.Log ("normal="+normal);
        //      angle = normal.z > 0 ? angle : (180+(180-angle));
        angle = normal.z > 0 ? angle : (360 - angle);
        return angle;
    }

    #endregion

    /// <summary>
    /// 计算目标位置的向量
    /// Calculates the dir.
    /// </summary>
    /// <param name="endAngle">End angle.</param>
    Vector3 calculateDir(float endAngle){
        float radiansX =  Mathf.Cos( Mathf.PI *(endAngle + 90) / 180);
        float radiansY = Mathf.Sin( Mathf.PI *(endAngle + 90) / 180);
        return new Vector3 (radiansX, radiansY, 0);

    }

    void endMove(){

        speed = 0;
        isMoving = false;
        moveState = 0;
    }

    void StartMove(){
        if (isMoving)
            return;
        int index=Random.Range (0, 10) - 1;
        Debug.Log ("恭喜你获得"+rewards[index]);
        endAngle = index *  360/10;//获得目标位置相对y坐标方向的角度
        targetDir = calculateDir (endAngle);//获得目标位置方向向量
        rotateTimer = keepTime;
        isMoving = true;
        moveState = 1;
    }
    void OnGUI(){
        if(GUILayout.Button("move")){

            StartMove ();
        }
//      if(GUILayout.Button("rotate")){
//          recTeansform.DORotate (new Vector3(0,0,recTeansform.position.z+endAngle),2f,RotateMode.Fast);
//      }

        if(GUILayout.Button("dir")){
            Debug.Log("up angle:"+calAngle (targetDir,transform.up));
            Debug.Log("right angle:"+calAngle (targetDir,transform.right));
            Debug.Log("forward angle:"+calAngle (targetDir,transform.forward));
        }
    }




}

代码下载:http://download.csdn.net/download/u011484013/9989267

猜你喜欢

转载自blog.csdn.net/u011484013/article/details/78055142