溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

unity實(shí)現(xiàn)簡(jiǎn)單抽獎(jiǎng)系統(tǒng)

發(fā)布時(shí)間:2020-09-09 19:39:00 來源:腳本之家 閱讀:221 作者:Oo小飛影oO 欄目:編程語(yǔ)言

這段時(shí)間工作比較空閑,想做個(gè)抽獎(jiǎng)系統(tǒng),發(fā)現(xiàn)網(wǎng)上的抽獎(jiǎng)系統(tǒng)看不懂,然后自己做了一個(gè)可以隨意定義獎(jiǎng)品概率,不管什么時(shí)候停下來指針最終都會(huì)轉(zhuǎn)到指定的獎(jiǎng)品哪。

廢話不多說,動(dòng)手一步一步來。

這個(gè)抽獎(jiǎng)系統(tǒng)就使用了兩張圖片,一個(gè)指針,一個(gè)圓形的圖片。

unity實(shí)現(xiàn)簡(jiǎn)單抽獎(jiǎng)系統(tǒng)

然后做一個(gè)預(yù)制體,圖片就是圓形圖片,image type選擇filled,fill amount控制這個(gè)圖片的面積大小,同時(shí)也是該圖片的概率,Text組件是該獎(jiǎng)品的名稱。

unity實(shí)現(xiàn)簡(jiǎn)單抽獎(jiǎng)系統(tǒng)

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

unity實(shí)現(xiàn)簡(jiǎn)單抽獎(jiǎng)系統(tǒng)

Bg就是那個(gè)灰色的圖片,Rotate是個(gè)空物體,用來掛在腳本的(DialRotate.cs和Slot.cs),cloneParent也是個(gè)空物體,作為預(yù)制體的父物體,要注意的是cloneParent中心那個(gè)藍(lán)色的圓圈要和Rotate的藍(lán)色的圈的位置一致,界面布局工作完成。

接下來到代碼了,Slot.cs腳本,一開始會(huì)實(shí)例化獎(jiǎng)品,K鍵和L鍵可以隨意修改獎(jiǎng)品名稱,概率(這里概率做了限制,需要使用的自己修改一下代碼即可),空格鍵會(huì)隨機(jī)拋出物品,并且開始旋轉(zhuǎn),鼠標(biāo)右鍵是停止轉(zhuǎn)動(dòng)(想什么時(shí)候停下來都行,最后都會(huì)得到所拋出的物體)DialRotate.cs腳本用于處理旋轉(zhuǎn)的。這兩個(gè)腳本涉及到一些數(shù)學(xué)計(jì)算,慢慢理解即可。

unity實(shí)現(xiàn)簡(jiǎn)單抽獎(jiǎng)系統(tǒng)

unity實(shí)現(xiàn)簡(jiǎn)單抽獎(jiǎng)系統(tǒng)

以下是這個(gè)工程的腳本,需要的話直接復(fù)制黏貼即可使用

Slot.cs 

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

public class Slot : MonoBehaviour {

  private DialRotate dialRotate;   
  /// <summary>
  /// 獎(jiǎng)品數(shù)據(jù)
  /// </summary>
  private class GrifData
  { 
   /// <summary>
  /// 獎(jiǎng)品的名稱
  /// </summary>
    public string mText;
    /// <summary>
    /// 圖片的Amount值
    /// </summary>
    public float point;
    /// <summary>
    /// 獎(jiǎng)品停留在指針時(shí)父物體要旋轉(zhuǎn)的角度
    /// </summary>
    public float angle;
    /// <summary>
    /// 該獎(jiǎng)品對(duì)應(yīng)UI面板上的名稱
    /// </summary>
    public string mtran;
    /// <summary>
    /// 該獎(jiǎng)品的ID
    /// </summary>
    public int gID;
  }
   /// <summary>
   /// 獎(jiǎng)品的描述信息
   /// </summary>
  private class GrifInfo
  {
    public Text mText;
    public string msg;
  }

  private List<GrifInfo> mListSD = new List<GrifInfo>();
  /// <summary>
  /// 獎(jiǎng)品的id和概率對(duì)應(yīng)
  /// </summary>
  private Dictionary<int, float> mPoints = new Dictionary<int, float>();
  /// <summary>
  /// 用于儲(chǔ)存獎(jiǎng)品信息(順序排列)(獎(jiǎng)品的id,名稱,所占的百分比)
  /// </summary>
  private List<GrifData> grigtData = new List<GrifData>();
  /// <summary>
  /// 這個(gè)也是用于儲(chǔ)存獎(jiǎng)品信息,不過是亂序排列(獎(jiǎng)品的id,名稱,所占的百分比)
  /// </summary>
  private List<GrifData> randomData = new List<GrifData>();
  /// <summary>
  /// 20種獎(jiǎng)品的Transform,(最多20個(gè)不用的獎(jiǎng)勵(lì))
  /// </summary>
  private List<Transform> mTransLs = new List<Transform>();

  private List<Color> mColors = new List<Color>();

  private Transform cloneParent;
  private GameObject clonePrefab;
  /// <summary>
  /// 抽獎(jiǎng)停止時(shí)父物體轉(zhuǎn)動(dòng)的角度
  /// </summary>
  public float tarAngle;
  /// <summary>
  /// 該獎(jiǎng)品對(duì)應(yīng)UI面板上的名稱
  /// </summary>
  public string tarName;
  public int giftID;
  /// <summary>
  /// 用于檢驗(yàn)概率有沒有為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 測(cè)試修改獎(jiǎng)品,概率
    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("薯?xiàng)l", 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("薯?xiàng)l", 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>
   /// 獲得隨機(jī)顏色
   /// </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>
  /// 清除獎(jiǎng)品的相關(guān)數(shù)據(jù)和設(shè)置新的顏色
  /// </summary>
  public void ClearData()
  {
    grigtData.Clear();
    foreach (Transform tr in mTransLs)
    {
      tr.GetComponent<Image>().color = GetColors();
      tr.gameObject.SetActive(false);
    }
  }
  /// <summary>
  /// 設(shè)置獎(jiǎng)勵(lì)信息
  /// </summary>
  /// <param name="text">名稱</param>
  /// <param name="point">所占的百分比</param>
  /// <param name="gID">該獎(jiǎng)品的ID</param>
  public void AddData(string text, float point, int gID)
  {
    if (point < 0.05f)
    {
      Debug.LogError("獎(jiǎng)品的概率不能小于5%");
    }
    if (point >1.0f)
    {
      Debug.LogError("獎(jiǎng)品的概率不能大于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>
  /// 設(shè)置獎(jiǎng)品轉(zhuǎn)盤的面積的大小顯示
  /// </summary>
  public void SetPriceRange()
  {
    float total = 0;
    for (int i = 0; i < checkProbability.Count; i++)
    {
      total += checkProbability[i];
    }
    if (total.ToString() !="1")
    {
      Debug.LogError("獎(jiǎng)品的概率總和不等于百分百,請(qǐng)從新設(shè)定概率");
      return;
    }
    transform.localEulerAngles = Vector3.zero;              
    // List<SData> temDate = mData.OrderBy(mData => mData.point).ToList(); //升序排序
    //亂序排列
    randomData.Clear();              
    int count = grigtData.Count;  //所設(shè)置的獎(jiǎng)品的個(gè)數(shù)
    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++)   //把設(shè)置了獎(jiǎng)品的顯示出來
    {
      Transform tr = mTransLs[i];
      tr.gameObject.SetActive(true);
      // Debug.Log(ramData[i].mText + "/n");
      //因?yàn)槔L制獎(jiǎng)勵(lì)區(qū)域是從轉(zhuǎn)盤的下面6點(diǎn)順時(shí)針方向開始繪制,而指針是在上面9點(diǎn),轉(zhuǎn)盤是順時(shí)針轉(zhuǎn)動(dòng),加多180度,
      
      //ramData[i].point/2 使得轉(zhuǎn)盤停下來時(shí)使得獎(jiǎng)品剛好處于指針的中間                       
      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(); //暫時(shí)預(yù)留,發(fā)獎(jiǎng)品不是單倍的時(shí)候有用
      grifInfo.mText = text;       //暫時(shí)預(yù)留,發(fā)獎(jiǎng)品不是單倍的時(shí)候有用
      grifInfo.msg = randomData[i].mText;  //暫時(shí)預(yù)留,發(fā)獎(jiǎng)品不是單倍的時(shí)候有用
      mListSD.Add(grifInfo);       //暫時(shí)預(yù)留,發(fā)獎(jiǎng)品不是單倍的時(shí)候有用
      tr.GetComponent<Image>().fillAmount = randomData[i].point; 
      //這個(gè)是旋轉(zhuǎn)所設(shè)置的獎(jiǎng)品的角度
      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>
  /// 設(shè)置獎(jiǎng)品的倍數(shù)
  /// </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>
  /// 獲得結(jié)果(得到概率)
  /// </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];   //該獎(jiǎng)品對(duì)應(yīng)的概率(Amount值)
      if (probability < nowSub)
      {
        tarAngle = randomData[i].angle; //該獎(jiǎng)品停止轉(zhuǎn)動(dòng)時(shí)需要轉(zhuǎn)動(dòng)的角度
        tarName = randomData[i].mtran;  //該獎(jiǎng)品的名稱
        giftID = randomData[i].gID;   //ID
        testStr ="獎(jiǎng)品名稱 = " + randomData[i].mText + " 獎(jiǎng)品概率 = " + (mPoints[randomData[i].gID] * 100 + " UI上的名稱 = " + tarName + " 獎(jiǎng)品的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, //開始轉(zhuǎn)動(dòng)
  ConstantSpeed, //勻速運(yùn)動(dòng)
  Stop,  //停止運(yùn)動(dòng)
}

public class DialRotate : MonoBehaviour {

  private RollType nowType = RollType.None;   
  private float tarAngle; //該獎(jiǎng)品停下來時(shí)父物體Z軸需要轉(zhuǎn)動(dòng)的角度
  /// <summary>
  /// 當(dāng)前Z軸的值
  /// </summary>
  private float nowAngle = 0;
  private string grifName;
  private float time;//計(jì)時(shí)器
  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; //這些數(shù)值影響轉(zhuǎn)盤的轉(zhuǎn)動(dòng)速度,自己看著喜歡調(diào)節(jié)即可
      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;  //勻速旋轉(zhuǎn)
      transform.localEulerAngles = new Vector3(0, 0, nowAngle);  
    } 
    else if (nowType == RollType.Stop)
    {
      //速度慢慢變小,轉(zhuǎn)盤慢慢的慢下來
      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("轉(zhuǎn)盤停止轉(zhuǎn)動(dòng)");
        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;   
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI