1、效果展示
功能简述:点击开始抽奖按钮,进行抽奖,(可以外部修改的内容:每个奖品中奖的中奖的概率,奖品内容,抽奖次数,规则内容)抽奖次数小于0时,不能继续抽奖,点击右侧幸运抽奖按钮才能刷新次数,再次抽奖。点击查看规则按钮可以查看规则。
2、UI布局
将整个界面分为左右两部分,左边是抽奖部分,右边是规则和标题部分,把全部的脚本都挂载在Canvas上,然后将对应的内容赋值即可。
3、代码
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEditor.PackageManager;
/// <summary>
/// 抽奖脚本
/// </summary>
public class goLuckyDraw : MonoBehaviour
{
[SerializeField] GameObject mainRoot;
[SerializeField] GameObject ruleRoot;
public Image transparentBox;//蒙版
public List<Transform> boxList = new List<Transform>();//所有的位置对象
private Transform chooseBox;//蒙版要到达的位置
private bool isRotate = false;//控制点击频率
int index = 0;//转盘转到的位置记录
int num; //剩余抽奖次数
[SerializeField] Text numTxt; //剩余抽奖次数的文字
[SerializeField] Button rultBtn; //查看规则界面按钮
[SerializeField] Button CloserultBtn; //关闭规则界面按钮
public Button StartBtn;//开始按钮
public Button RestartBtn; //重新开始按钮
void Start()
{
//抽奖次数赋值
num = int.Parse(ConfigFile.LoadString("num"));
numTxt.text = "剩余抽奖次数为:" + num;
transparentBox.gameObject.SetActive(false);
//默认界面显示
ColseRulePanel();
//获取需要监听的按钮对象
StartBtn.onClick.AddListener(() =>
{
if (!isRotate)
{
StartLuckyDraw();
}
});
RestartBtn.onClick.AddListener(RestartEvent);
//按钮监听
rultBtn.onClick.AddListener(ShowRulePanel);
CloserultBtn.onClick.AddListener(ColseRulePanel);
}
#region 开始抽奖
//设置概率可以外部修改
List<int> AA=new List<int>();
private void StartLuckyDraw()
{
isRotate = true;
//获取概率的string格式,概率外部赋值
string probability = ConfigFile.LoadString("probability");
//将字符串分割
string[] temp = probability.Split('-');
//将字符串改为数字,然后添加到数字列表中
for (int i = 0; i < temp.Length; i++)
{
int num = int.Parse(temp[i]);
//Debug.Log(num);
AA.Add(num);
}
int _index = RandomNum(AA);
Debug.Log(AA);
chooseBox = boxList[_index];
transparentBox.gameObject.SetActive(true);
StartCoroutine(Move(_index));
//抽奖次数减一
num--;
Debug.Log(num);
numTxt.text = "剩余抽奖次数为:" + num;
if (num<=0)
{
StartBtn.enabled = false;
//num = int.Parse(ConfigFile.LoadString("num")); ;
numTxt.text = "您的抽奖次数已用尽,谢谢参与";
}
}
//控制概率
//rate:几率数组(%), total:几率总和(100%)
private int RandomNum(List<int> rate, int total = 100)
{
if (rate == null)
{
int r = UnityEngine.Random.Range(0, 7);
return r;
}
else
{
int r = UnityEngine.Random.Range(1, total + 1);
int t = 0;
for (int i = 0; i < rate.Count; i++)
{
t += rate[i];
if (r < t)
{
return i;
}
}
return 0;
}
}
#endregion
#region 抽奖旋转动画
IEnumerator Move(int _index)
{
float time = 0.1f;
//下次开始旋转的位置等于上次旋转到的位置
for (int i = index; i < boxList.Count; i++)
{
transparentBox.transform.DOLocalMove(boxList[i].localPosition, time);
yield return new WaitForSeconds(time);
}
index = _index;
//旋转两圈
for (int i = 0; i < boxList.Count; i++)
{
transparentBox.transform.DOLocalMove(boxList[i].localPosition, time);
yield return new WaitForSeconds(time);
}
for (int i = 0; i < boxList.Count; i++)
{
transparentBox.transform.DOLocalMove(boxList[i].localPosition, time);
yield return new WaitForSeconds(time);
}
//当旋转到指定的位置的时候结束
for (int i = 0; i < boxList.Count; i++)
{
if (transparentBox.transform.localPosition == chooseBox.localPosition)
{
transparentBox.transform.DOLocalMove(chooseBox.localPosition, time);
continue;
}
else
{
transparentBox.transform.DOLocalMove(boxList[i].localPosition, time);
yield return new WaitForSeconds(time);
}
}
isRotate = false;
}
#endregion
#region 规则界面得显示与隐藏
void ShowRulePanel()
{
ruleRoot.SetActive(true);
}
void ColseRulePanel()
{
ruleRoot.SetActive(false);
}
#endregion
#region 刷新,重新开始
public void RestartEvent()
{
Debug.Log(num);
if (num<=0)
{
Debug.Log("num为0,无法继续抽奖,点击按钮刷新次数");
num = int.Parse(ConfigFile.LoadString("num"));
numTxt.text = "刷新成功,剩余抽奖次数为:" + num;
StartBtn.enabled = true;
}
else
{
Debug.Log("num>0,刷新无用");
return;
}
}
#endregion
}
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 文字内容的外部加载
/// </summary>
public class TextManager : MonoBehaviour
{
public string filePath; //内容文件的名称
[SerializeField] Text contentTxt; //内容展示
[SerializeField] RectTransform content;
private void Start()
{
SetContentTxt();
}
private void Update()
{
content.sizeDelta = new Vector2(content.sizeDelta.x, contentTxt.GetComponent<RectTransform>().sizeDelta.y + 50);
}
private void SetContentTxt()
{
//标题或文件名称为空时 不执行
if (filePath.Equals(""))
{
Debug.Log("标题内容的string字段为空");
return;
}
//内容的文字替换
contentTxt.text = File.ReadAllText(Application.streamingAssetsPath + $"/ContentTxt/{filePath}.txt", Encoding.UTF8);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 图片外部加载
/// </summary>
public class ImageManage : MonoBehaviour
{
List<Sprite> imageList = new List<Sprite>(); //加载的图片的列表
[SerializeField] List<GameObject> images = new List<GameObject>(); //图片列表
[SerializeField] List<Text> texts = new List<Text>(); //图片名称列表
void Start()
{
LoadAllPic();
for (int i = 0; i < imageList.Count; i++)
{
//将图片赋值到预制体上
images[i].GetComponent<Image>().sprite = imageList[i];
}
}
string[] dirs;
//外部加载图片
void LoadAllPic()
{
string imgtype = "*.JPG|*.PNG";
string[] ImageType = imgtype.Split('|');
List<string> filePathList = new List<string>();
string[] dirs1 = Directory.GetFiles(Application.streamingAssetsPath + "/image/", ImageType[0]);
List<string> dirs1List = new List<string>(dirs1);
string[] dirs2 = Directory.GetFiles(Application.streamingAssetsPath + "/image/", ImageType[1]);
//当两种格式都存在时,将第二个数组中的内容加入到第一个数组中去
if (ImageType[0] != null && ImageType[1] != null)
{
for (int m = 0; m < dirs2.Length; m++)
{
string dir2 = dirs2[m];
dirs1List.Add(dir2);
}
dirs = dirs1List.ToArray();
}
//当只有jpg格式时,将数组内容赋值
else if (ImageType[0] != null && ImageType[1] == null)
dirs = dirs1;
//当只有png格式时,将数组内容赋值
else if (ImageType[0] == null && ImageType[1] != null)
dirs = dirs2;
for (int j = 0; j < dirs.Length; j++)
{
Texture2D tx = new Texture2D(100, 100);
tx.LoadImage(getImageByte(dirs[j]));
Sprite sprite = Sprite.Create(tx, new Rect(0, 0, tx.width, tx.height), new Vector2(-500, -500));
//获取sprite的名称
sprite.name = Path.GetFileNameWithoutExtension(dirs[j]);
//将名称用“-”分割
string[] names = sprite.name.Split('-');
//获取数字后面的名字并赋值
texts[j].text = names[1];
//将获取的图片加到图片列表中
imageList.Add(sprite);
}
}
private static byte[] getImageByte(string imagePath)
{
FileStream files = new FileStream(imagePath, FileMode.Open);
byte[] imgByte = new byte[files.Length];
files.Read(imgByte, 0, imgByte.Length);
files.Close();
return imgByte;
}
}
using System.Xml.Linq;
using UnityEngine;
using System;
/// <summary>
/// xml文件读取工具
/// </summary>
public class ConfigFile
{
static string path = Application.dataPath + "/StreamingAssets/ConfigFile.xml";
public static DateTime LoadDeadline()
{
XDocument document = XDocument.Load(path);
//获取到XML的根元素进行操作
XElement root = document.Root;
XElement ele = root.Element("WarningDeadline");
DateTime deadline = Convert.ToDateTime(ele.Value); //string格式有要求,必须是yyyy - MM - dd hh: mm: ss
return deadline;
}
//获取数据
public static string LoadString(string str)
{
XDocument document = XDocument.Load(path);
//获取到XML的根元素进行操作
XElement root = document.Root;
XElement ele = root.Element(str);
return ele.Value;
}
//更新数据
public static void UpdateDate(string name, string value)
{
XDocument document = XDocument.Load(path);
//获取到XML的根元素进行操作
XElement root = document.Root;
root.SetElementValue(name, value);
document.Save(path);
}
}
<?xml version="1.0" encoding="utf-8"?>
<Info>
<!--设置每个奖品的概率 一共8个数,8个数之和为100-->
<probability>10-20-0-20-10-10-10-20</probability>
<!--剩余抽奖次数-->
<num>2</num>
</Info>
4、外部修改内容
1、规则文本:放在StreamingAssets中的ContentTxt中,命名为0,格式为文本文档格式
2、奖品内容:放在StreamingAssets中的image中,名称为”n-name“,n是指数字,因为读取图片的时候是按顺序读取的,不加这个数字可能会让奖品顺序乱了,name是指奖品的名称,名称也会在程序中显示
3、抽奖概率和次数:放在StreamingAssets中的ConfigFile中,注意8个数的概率之和为100.