unity实现简单抽奖系统
程序员文章站
2023-11-24 16:11:40
这段时间工作比较空闲,想做个抽奖系统,发现网上的抽奖系统看不懂,然后自己做了一个可以随意定义奖品概率,不管什么时候停下来指针最终都会转到指定的奖品哪。
废话不多说,动手一...
这段时间工作比较空闲,想做个抽奖系统,发现网上的抽奖系统看不懂,然后自己做了一个可以随意定义奖品概率,不管什么时候停下来指针最终都会转到指定的奖品哪。
废话不多说,动手一步一步来。
这个抽奖系统就使用了两张图片,一个指针,一个圆形的图片。
然后做一个预制体,图片就是圆形图片,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; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。