这段时间工作比较空闲,想做个抽奖系统,发现网上的抽奖系统看不懂,然后自己做了一个可以随意定义奖品概率,不管什么时候停下来指针最终都会转到指定的奖品哪。
废话不多说,动手一步一步来。
这个抽奖系统就使用了两张图片,一个指针,一个圆形的图片。
然后做一个预制体,图片就是圆形图片,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");