好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

unity实现简单抽奖系统

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

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

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

然后做一个预制体,图片就是圆形图片,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;  

   }

}

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

原文链接:https://blog.csdn.net/qq_37491893/article/details/84100365

dy("nrwz");

查看更多关于unity实现简单抽奖系统的详细内容...

  阅读:39次