unity开发抽奖系统

这段时间工作比较空闲,想做个抽奖系统,发现网上的抽奖系统看不懂,然后自己做了一个可以随意定义奖品概率,不管什么时候停下来指针最终都会转到指定的奖品哪。。。

废话不多说,动手一步一步来。

这个抽奖系统就使用了两张图片,一个指针,一个圆形的图片。

unity开发抽奖系统_第1张图片

然后做一个预制体,图片就是圆形图片,image type选择filled,fill amount控制这个图片的面积大小,同时也是该图片的概率,Text组件是该奖品的名称。

unity开发抽奖系统_第2张图片

再接下来就做一下界面布局的工作

unity开发抽奖系统_第3张图片

Bg就是那个灰色的图片,Rotate是个空物体,用来挂在脚本的(DialRotate.cs和Slot.cs),cloneParent也是个空物体,作为预制体的父物体,要注意的是cloneParent中心那个蓝色的圆圈要和Rotate的蓝色的圈的位置一致,界面布局工作完成。

接下来到代码了,Slot.cs脚本,一开始会实例化奖品,K键和L键可以随意修改奖品名称,概率(这里概率做了限制,需要使用的自己修改一下代码即可),空格键会随机抛出物品,并且开始旋转,鼠标右键是停止转动(想什么时候停下来都行,最后都会得到所抛出的物体)DialRotate.cs脚本用于处理旋转的。这两个脚本涉及到一些数学计算,慢慢理解即可。

unity开发抽奖系统_第4张图片

unity开发抽奖系统_第5张图片

以下是这个工程的脚本,需要的话直接复制黏贴即可使用

Slot.cs

 

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;   

public class Slot : MonoBehaviour {

    private DialRotate dialRotate;      
    ///


    /// 奖品数据
    ///

    private class GrifData
    { 
     ///
    /// 奖品的名称
    ///

        public string mText;
        ///
        /// 图片的Amount值
        ///

        public float point;
        ///
        /// 奖品停留在指针时父物体要旋转的角度
        ///

        public float angle;
        ///
        /// 该奖品对应UI面板上的名称
        ///

        public string mtran;
        ///
        /// 该奖品的ID
        ///

        public int gID;
    }
     ///
     /// 奖品的描述信息
     ///

    private class GrifInfo
    {
        public Text mText;
        public string msg;
    }

    private List mListSD = new List();
    ///


    /// 奖品的id和概率对应
    ///

    private Dictionary mPoints = new Dictionary();
    ///
    /// 用于储存奖品信息(顺序排列)(奖品的id,名称,所占的百分比)
    ///

    private List grigtData = new List();
    ///
    /// 这个也是用于储存奖品信息,不过是乱序排列(奖品的id,名称,所占的百分比)
    ///

    private List randomData = new List();
    ///
    /// 20种奖品的Transform,(最多20个不用的奖励)
    ///

    private List mTransLs = new List();

    private List mColors = new List();

    private Transform cloneParent;
    private GameObject clonePrefab;
    ///


    /// 抽奖停止时父物体转动的角度
    ///

    public float tarAngle;
    ///
    /// 该奖品对应UI面板上的名称
    ///

    public string tarName;
    public int giftID;
    ///
    /// 用于检验概率有没有为100%
    ///

    private List checkProbability = new List();

    private void Start()
    {
        cloneParent = transform.Find("cloneParent");
        clonePrefab = Resources.Load("Clone");
        dialRotate = GetComponent();
        Init();
    }
    void Update()
    {
        #region 测试修改奖品,概率
        if (Input.GetKeyDown(KeyCode.K))
        {
            ClearData();
            if (checkProbability.Count > 0)
            {
                checkProbability.Clear();
            }
            if (mPoints.Count > 0)
            {
                mPoints.Clear();
            }
            AddData("111", 0.3f,1);
            AddData("222", 0.1f,2);
            AddData("333", 0.2f,4);
            AddData("444", 0.05f,5);
            AddData("555", 0.15f,6);
            AddData("666", 0.2f,7);
            SetPriceRange();
        }
        if (Input.GetKeyDown(KeyCode.J))
        {
            ClearData();
            if (checkProbability.Count > 0)
            {
                checkProbability.Clear();
            }
            if (mPoints.Count > 0)
            {
                mPoints.Clear();
            }
            AddData("薯条", 0.3f, 1);
            AddData("汉堡", 0.1f, 2);
            AddData("炸鸡", 0.2f, 4);
            AddData("啤酒", 0.05f, 5);
            AddData("可乐", 0.15f, 6);
            AddData("烤肉", 0.2f, 7);
            SetPriceRange();
        }
        #endregion
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartRotate();
        }
    }
    private void Init()
    {
        for (int i = 0; i < 20; i++)
        {
            GameObject go = Instantiate(clonePrefab) as GameObject;
            go.transform.SetParent(cloneParent);
            go.transform.localScale = Vector3.one;
            go.transform.localPosition = Vector3.zero;
            go.name = "" + i;
            mTransLs.Add(go.transform);
        }
        foreach (Transform tr in mTransLs)
        {
            tr.GetComponent().color = GetColors();
            tr.gameObject.SetActive(false);
        }
        AddData("薯条", 0.3f, 1);
        AddData("汉堡", 0.1f, 2);
        AddData("炸鸡", 0.2f, 4);
        AddData("啤酒", 0.05f, 5);
        AddData("可乐", 0.15f, 6);
        AddData("烤肉", 0.2f, 7);
        SetPriceRange();
    }
     ///


     /// 获得随机颜色
     ///

     ///
    private Color GetColors()
    {
        return new Color(Random.Range(0, 1.0f), Random.Range(0, 1.0f), Random.Range(0, 1.0f));
    }

    ///


    /// 清除奖品的相关数据和设置新的颜色
    ///

    public void ClearData()
    {
        grigtData.Clear();
        foreach (Transform tr in mTransLs)
        {
            tr.GetComponent().color = GetColors();
            tr.gameObject.SetActive(false);
        }
    }
    ///
    /// 设置奖励信息
    ///

    /// 名称
    /// 所占的百分比
    /// 该奖品的ID
    public void AddData(string text, float point, int gID)
    {
        if (point < 0.05f)
        {
            Debug.LogError("奖品的概率不能小于5%");
        }
        if (point >1.0f)
        {
            Debug.LogError("奖品的概率不能大于100%");
        }
        GrifData data = new GrifData();
        data.mText = text;
        data.point = point;
        data.gID = gID;
        grigtData.Add(data);
        if (mPoints.ContainsKey(gID))
        {
            //  mPoints[gID] = point;
            Debug.LogError("物品的ID不能一致,无法添加到字典");
            return;
        }
        mPoints.Add(gID, point);
        checkProbability.Add(point);
    }
    ///
    /// 设置奖品转盘的面积的大小显示
    ///

    public void SetPriceRange()
    {
        float total = 0;
        for (int i = 0; i < checkProbability.Count; i++)
        {
            total += checkProbability[i];
        }
        if (total.ToString() !="1")
        {
            Debug.LogError("奖品的概率总和不等于百分百,请从新设定概率");
            return;
        }
        transform.localEulerAngles = Vector3.zero;                           
       //  List temDate = mData.OrderBy(mData => mData.point).ToList(); //升序排序
        //乱序排列
        randomData.Clear();                            
        int count = grigtData.Count;   //所设置的奖品的个数
        for (int i = 0; i < count; i++)
        {
            int ra = Random.Range(0, grigtData.Count);
            randomData.Add(grigtData[ra]);
            grigtData.RemoveAt(ra);
        }
        if (mListSD.Count > 0)
        {
            mListSD.Clear(); //先清空
        }   
        float nowAmount = 0;
        Text text;
        for (int i = 0; i < count; i++)     //把设置了奖品的显示出来
        {
            Transform tr = mTransLs[i];
            tr.gameObject.SetActive(true);
           // Debug.Log(ramData[i].mText + "/n");
            //因为绘制奖励区域是从转盘的下面6点顺时针方向开始绘制,而指针是在上面9点,转盘是顺时针转动,加多180度,
            
            //ramData[i].point/2 使得转盘停下来时使得奖品刚好处于指针的中间                                              
            float target = 180 + (nowAmount + randomData[i].point/2) * 360;    
            if (target > 360)
                target -= 360;
            text = tr.Find("Text").GetComponent();
            text.text = randomData[i].mText;
            GrifInfo grifInfo = new GrifInfo(); //暂时预留,发奖品不是单倍的时候有用
            grifInfo.mText = text;              //暂时预留,发奖品不是单倍的时候有用
            grifInfo.msg = randomData[i].mText;    //暂时预留,发奖品不是单倍的时候有用
            mListSD.Add(grifInfo);              //暂时预留,发奖品不是单倍的时候有用
            tr.GetComponent().fillAmount = randomData[i].point;  
            //这个是旋转所设置的奖品的角度
            tr.localEulerAngles = new Vector3(0, 0, -nowAmount * 360); //0.1Amount = 36度
                                                                           
            nowAmount += randomData[i].point;
           // Debug.Log(" i = " + i + "target = " + target);                     
            randomData[i].angle = target;
            randomData[i].mtran = tr.name;
           // Debug.Log("target = " + target);
        }
    }
    ///
    /// 设置奖品的倍数
    ///

    ///
    public void SetMultiple(int multiple)
    {
        foreach (GrifInfo ss in mListSD)
        {
            if (multiple == 1)
            {
                ss.mText.text = ss.msg;
            }   
            else
            {
                ss.mText.text = ss.msg + " X" + multiple;
            }                                               
        }
    }
    ///
    /// 获得结果(得到概率)
    ///

    public void GetResult()
    {
        float probability = Random.Range(0.0f, 1.0f);
        float nowSub = 0;
        string testStr = "";                         
        for (int i = 0; i < randomData.Count; i++)
        {
            nowSub += mPoints[randomData[i].gID];     //该奖品对应的概率(Amount值)
            if (probability < nowSub)
            {
                tarAngle = randomData[i].angle;  //该奖品停止转动时需要转动的角度
                tarName = randomData[i].mtran;   //该奖品的名称
                giftID = randomData[i].gID;      //ID
                testStr ="奖品名称 = " + randomData[i].mText + "  奖品概率 = " + (mPoints[randomData[i].gID] * 100 + "  UI上的名称 = " + tarName + "  奖品的ID = " + giftID);
                Debug.Log(testStr);
                break;
            } 
        }           
    }
    private void StartRotate()
    {
        GetResult();
        dialRotate.StartQuan(tarAngle, tarName);
        Debug.Log("StartRotate() : tarAngle = " + tarAngle);
    }
}

 

-------------------------------------------------------------------分割线----------------------------------------------------------------------------

-------------------------------------------------------------------分割线----------------------------------------------------------------------------

-------------------------------------------------------------------分割线----------------------------------------------------------------------------

DialRotate.cs 

using UnityEngine;

public enum RollType
{
    None,
    Start,  //开始转动
    ConstantSpeed, //匀速运动
    Stop,   //停止运动
}

public class DialRotate : MonoBehaviour {

    private RollType nowType = RollType.None;     
    private float tarAngle;  //该奖品停下来时父物体Z轴需要转动的角度
    ///


    /// 当前Z轴的值
    ///

    private float nowAngle = 0;
    private string grifName;
    private float time;//计时器
    private float speed = 0;
    public float angleSpeed = 2;   
    
    void Update () {
        if (Input.GetMouseButtonDown(1))
        {
            if (nowType == RollType.ConstantSpeed)
            {     
                nowType = RollType.Stop;
              //  Debug.Log("tarAngle = " + tarAngle + " nowAngle = " + nowAngle);
                tarAngle += nowAngle + 360;       
                time = 0;
            }
        }

        if (nowType == RollType.Start)
        {   
            time += Time.deltaTime; 
            float x = angleSpeed * time * time; //这些数值影响转盘的转动速度,自己看着喜欢调节即可
            nowAngle -= x;
            speed += 4 * time;

            transform.localEulerAngles = new Vector3(0, 0, nowAngle);
            if (speed > 400)
            {
                nowType = RollType.ConstantSpeed;      
            }    
        }
        else if (nowType == RollType.ConstantSpeed)
        {
            nowAngle -= speed * Time.deltaTime;   //匀速旋转
            transform.localEulerAngles = new Vector3(0, 0, nowAngle);    
        } 
        else if (nowType == RollType.Stop)
        {
            //速度慢慢变小,转盘慢慢的慢下来
            speed = Mathf.Lerp(speed, Mathf.Min(speed, tarAngle * 0.25f), Time.deltaTime);
          //  Debug.Log("speed = " + speed);
            if (speed < 5)
            {
                speed = 5;
            }  
            float angle = speed * Time.deltaTime;
            tarAngle -= angle;   
            nowAngle -= angle;      
            if (tarAngle < 0)
            {
                Debug.Log("转盘停止转动");
                nowType = RollType.None;                                                                       
            }
            else
            {
                transform.localEulerAngles = new Vector3(0, 0, nowAngle);
            }                                                                   
        }                                  
        if (nowAngle < -360)
        {
            nowAngle += 360;
        }        
    }

    public void StartQuan(float tarAngle, string giftName)
    {
        if (nowType != RollType.None)
        {
            return;
        }
        grifName = giftName;
        this.tarAngle = 360 * 2 - tarAngle;     
        nowType = RollType.Start;

        time = 0;
        nowAngle = transform.localEulerAngles.z;   
        speed = 0;      
    }
}

-------------------------------------------------完毕---------------------

你可能感兴趣的:(unity,抽奖,抽奖系统,转盘)