首页 > 编程 > C# > 正文

unity实现简单抽奖系统

2020-01-24 00:09:59
字体:
来源:转载
供稿:网友

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

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

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

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

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

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

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

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

Slot.cs 

using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;  public class Slot : MonoBehaviour {  private DialRotate dialRotate;     /// <summary>  /// 奖品数据  /// </summary>  private class GrifData  {    /// <summary>  /// 奖品的名称  /// </summary>    public string mText;    /// <summary>    /// 图片的Amount值    /// </summary>    public float point;    /// <summary>    /// 奖品停留在指针时父物体要旋转的角度    /// </summary>    public float angle;    /// <summary>    /// 该奖品对应UI面板上的名称    /// </summary>    public string mtran;    /// <summary>    /// 该奖品的ID    /// </summary>    public int gID;  }   /// <summary>   /// 奖品的描述信息   /// </summary>  private class GrifInfo  {    public Text mText;    public string msg;  }  private List<GrifInfo> mListSD = new List<GrifInfo>();  /// <summary>  /// 奖品的id和概率对应  /// </summary>  private Dictionary<int, float> mPoints = new Dictionary<int, float>();  /// <summary>  /// 用于储存奖品信息(顺序排列)(奖品的id,名称,所占的百分比)  /// </summary>  private List<GrifData> grigtData = new List<GrifData>();  /// <summary>  /// 这个也是用于储存奖品信息,不过是乱序排列(奖品的id,名称,所占的百分比)  /// </summary>  private List<GrifData> randomData = new List<GrifData>();  /// <summary>  /// 20种奖品的Transform,(最多20个不用的奖励)  /// </summary>  private List<Transform> mTransLs = new List<Transform>();  private List<Color> mColors = new List<Color>();  private Transform cloneParent;  private GameObject clonePrefab;  /// <summary>  /// 抽奖停止时父物体转动的角度  /// </summary>  public float tarAngle;  /// <summary>  /// 该奖品对应UI面板上的名称  /// </summary>  public string tarName;  public int giftID;  /// <summary>  /// 用于检验概率有没有为100%  /// </summary>  private List<float> checkProbability = new List<float>();  private void Start()  {    cloneParent = transform.Find("cloneParent");    clonePrefab = Resources.Load<GameObject>("Clone");    dialRotate = GetComponent<DialRotate>();    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<Image>().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();  }   /// <summary>   /// 获得随机颜色   /// </summary>   /// <returns></returns>  private Color GetColors()  {    return new Color(Random.Range(0, 1.0f), Random.Range(0, 1.0f), Random.Range(0, 1.0f));  }  /// <summary>  /// 清除奖品的相关数据和设置新的颜色  /// </summary>  public void ClearData()  {    grigtData.Clear();    foreach (Transform tr in mTransLs)    {      tr.GetComponent<Image>().color = GetColors();      tr.gameObject.SetActive(false);    }  }  /// <summary>  /// 设置奖励信息  /// </summary>  /// <param name="text">名称</param>  /// <param name="point">所占的百分比</param>  /// <param name="gID">该奖品的ID</param>  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);  }  /// <summary>  /// 设置奖品转盘的面积的大小显示  /// </summary>  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<SData> 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.text = randomData[i].mText;      GrifInfo grifInfo = new GrifInfo(); //暂时预留,发奖品不是单倍的时候有用      grifInfo.mText = text;       //暂时预留,发奖品不是单倍的时候有用      grifInfo.msg = randomData[i].mText;  //暂时预留,发奖品不是单倍的时候有用      mListSD.Add(grifInfo);       //暂时预留,发奖品不是单倍的时候有用      tr.GetComponent<Image>().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);    }  }  /// <summary>  /// 设置奖品的倍数  /// </summary>  /// <param name="multiple"></param>  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;      }                            }  }  /// <summary>  /// 获得结果(得到概率)  /// </summary>  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轴需要转动的角度  /// <summary>  /// 当前Z轴的值  /// </summary>  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;     }}

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表