欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

unity实现简单抽奖系统

程序员文章站 2023-12-11 08:16:34
这段时间工作比较空闲,想做个抽奖系统,发现网上的抽奖系统看不懂,然后自己做了一个可以随意定义奖品概率,不管什么时候停下来指针最终都会转到指定的奖品哪。 废话不多说,动手一...

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

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

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

unity实现简单抽奖系统

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

unity实现简单抽奖系统

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

unity实现简单抽奖系统

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

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

unity实现简单抽奖系统

unity实现简单抽奖系统

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

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;   
  }
}

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