unity 转盘
设置pointer点对象,可以设置指针转动或者转盘转动,具体看代码
可以设置顺逆旋转
注意结构
数据的配置 自己可以选择自己的写法,这里因为比较简单就用scriptableobject弄一下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XYX;
public enum SpinState
{
None, //待机状态
Start, //加速阶段
Prepared, //等待数据阶段
End, //减速阶段
}
/// <summary>
/// 转盘
/// </summary>
public class TurnTableView : UIBase
{
[Tooltip("转动的东西")]
public Transform pointer;//转动点
public Animator arrowAnim;
public Sprite advImg;
public Sprite flower;
Transform[] Spins;//对应的slots,需要提前制定数量
Text spinNum;
Image spinImg;
protected override void Awake()
{
base.Awake();
root =transform.Find("root") as RectTransform;
Transform Spin = GetUIComponent<Image>("Spin").transform;
Spins = new Transform[Spin.childCount];
for (int i = 0; i < Spin.childCount; i++)
{
Spins[i] = Spin.GetChild(i);
Spin.GetChild(i).GetChild(1).GetComponent<Text>().text = GameManager.turnTable_SO.spinReward[i].num_Str;
}
spinNum = GetUIComponent<Text>("spinNum");
spinImg = GetUIComponent<Image>("spinImg");
CheckMySpinNumber();
}
//检查自己还能转多少
void CheckMySpinNumber()
{
spinImg.sprite = advImg;
if(GameDataManager.GetInstance().commonData.turnTabelData.rotateNum<=0)
{
GetUIComponent<Image>("getSpinBtn").GetComponent<TweenEffects>().StopTween(true);
spinImg.sprite = advImg;
spinNum.text = "+1";
}
else
{
GetUIComponent<Image>("getSpinBtn").GetComponent<TweenEffects>().StopTween(false);
spinImg.sprite = flower;
spinNum.text = GameDataManager.GetInstance().commonData.turnTabelData.rotateNum + "/"+ GameDataManager.GetInstance().commonData.turnTabelData.rotateNum;
}
spinImg.SetNativeSize();
}
public override void ShowView()
{
base.ShowView();
_spinstate = SpinState.None;
}
protected override void OnClickBUt(string btnName)
{
switch (btnName)
{
case "closeBtn":
if(_spinstate == SpinState.None)
HideView();
break;
case "spinBtn":
StartClickSpin();
break;
case "getSpinBtn":
if (SdkManager.GetInstance().m_sdk_state != Mode_SDK_State.Adv) return;
if (GameDataManager.GetInstance().commonData.turnTabelData.rotateNum <= 0)
{
SdkManager.GetInstance().ShowRewardVideoAd(()=> {
GameDataManager.GetInstance().commonData.turnTabelData.rotateNum += 1;
GameDataManager.GetInstance().SaveData(XYX_Tag.COMMON);
CheckMySpinNumber();
});
//TODO 直接看广告
}
break;
}
}
//开始
void StartClickSpin()
{
if (_spinstate == SpinState.None)
{
if (GameDataManager.GetInstance().commonData.turnTabelData.rotateNum <= 0)
{
UIManager.GetInstance().MessageBoxUI("次数用完了!");
return;
}
_spinstate = SpinState.Start;
arrowAnim.SetBool("show",true);
UIManager.GetInstance().FlyTxT("-1",Color.red, spinNum.transform.position);
StartCoroutine("RoateTimer");//必须停止的时间
_time = 0;
GameDataManager.GetInstance().commonData.turnTabelData.rotateNum--;
if (GameDataManager.GetInstance().commonData.turnTabelData.rotateNum < 0)
GameDataManager.GetInstance().commonData.turnTabelData.rotateNum = 0;
GameDataManager.GetInstance().SaveData(XYX_Tag.COMMON);
CheckMySpinNumber();
print("今日抽将次数 " + GameDataManager.GetInstance().commonData.turnTabelData.rotateNum);
}
}
public int testRewardIndex = 2;
/// <summary>
/// 停止转动的时间
/// </summary>
/// <returns></returns>
IEnumerator RoateTimer()
{
yield return new WaitForSeconds(GameManager.turnTable_SO.timerStop);
OnprobabilityStopArea(testRewardIndex);//test
// OnprobabilityStopArea();
}
// 根据几率来让指针停止到对应区域 可以写特殊关照
void OnprobabilityStopArea(int specialValue = -1)
{
if (specialValue < 0)
EndAngle = GameManager.turnTable_SO.spinReward[ProbabilityChoose()].angle;
else
{
spinRewardId = specialValue;
EndAngle = GameManager.turnTable_SO.spinReward[specialValue].angle;//特殊关照的item
}
// print("奖励角度==========:"+ EndAngle);
// print("奖励角度==========:" + GameManager.turnTable_SO.spinReward[specialValue].angle);
_spinstate = SpinState.Prepared;
}
int spinRewardId;
//几率选择-返回奖励数组编号
int ProbabilityChoose()
{
//概率总精度为100
float totalRank = 100;
//float totalRank = 0;
//for (int i = 0; i < GameManager.turnTable_SO.spinReward.Length; i++)
//{
// totalRank += GameManager.turnTable_SO.spinReward[i].probability;//总概率=1;
//}
spinRewardId = 0;
foreach (var item in GameManager.turnTable_SO.spinReward)
{
//产生一个0到100之间的随机数
float random = Random.Range(0, totalRank);
//将该随机数和奖品的概率比较
if (random <= item.probability)
{
spinRewardId = item.id;
Debug.Log(spinRewardId);
//抽奖结果
//为转盘指针随机生成旋转角度
// float angle = Random.Range(item.MinAngle, item.MaxAngle);
//旋转转盘指针,此处略
break;
}
else
{
totalRank -= item.probability;
}
}
return spinRewardId;
}
private void Update()
{
RotateState();
}
private float _time;//时间统计
private float _tmpAngle = 0f;//角度缓存
private float _minTime = 3.0f; //减速前的最短持续时间
private float _factor;
private SpinState _spinstate;//转盘的状态属性
void RotateState()
{
if (_spinstate == SpinState.None) return;
_time += Time.deltaTime;
if (_spinstate == SpinState.End)
{
//通过差值运算实现精准地旋转到指定角度(球型插值无法实现大于360°的计算)
float k = 2.5f; //如果嫌减速太慢,可以加个系数修正一下
_tmpAngle = Mathf.Lerp(_tmpAngle, EndAngle, Time.deltaTime * k);
// Debug.Log(_tmpAngle+"=="+EndAngle);
//这里只存在一个方向的旋转,所以不存在欧拉角万向节的问题,所以使用欧拉角和四元数直接赋值都是可以的
// pointer.rotation = Quaternion.Euler(0, 0, _tmpAngle);//顺
// pointer.rotation = Quaternion.Euler(0, 0, -_tmpAngle);//逆
pointer.rotation = Quaternion.Euler(0, 0, GameManager.turnTable_SO.rotateDirect * _tmpAngle);
// print("减速阶段");
if (1 >= Mathf.Abs(_tmpAngle - EndAngle))
{
GetReward();
_spinstate = SpinState.None;
}
}
else
{
_factor = _time / GameManager.turnTable_SO.AcceleateTime; //加速速度因子
_factor = _factor > 1 ? 1 : _factor;//最大为1
// pointer.Rotate(Vector3.forward, _factor * velocity * Time.deltaTime, Space.Self);//逆时针
// pointer.Rotate(Vector3.back, _factor * velocity * Time.deltaTime, Space.Self);//顺时针
pointer.Rotate(Vector3.back * GameManager.turnTable_SO.rotateDirect, _factor * GameManager.turnTable_SO.velocity * Time.deltaTime, Space.Self);
}
//当收到数据之后并且旋转了一定时间后开始减速
if (_spinstate == SpinState.Prepared && _time > _minTime)
{
_tmpAngle = GetCurClockwiseAngle();
// print("准备进入减速了" + _tmpAngle + "===" + EndAngle + "===" + pointer.eulerAngles.z);
_spinstate = SpinState.End;
}
}
float GetCurClockwiseAngle()// 将当前指针的欧拉角转换成顺时针统计角度
{
//读取到的值是 0-180,180- -180-0 [0, 180] U [-180, 0],左边由0至180递增,右边由180转变成-180,然后递增至0,所以需要转相应的转换
return (-GameManager.turnTable_SO.rotateDirect) * (360 - pointer.eulerAngles.z) % 360;
//return (-1) * (360 - pointer.eulerAngles.z) % 360;//顺
//return (1) * (360 - pointer.eulerAngles.z) % 360;//逆
}
void GetReward()
{
arrowAnim.SetBool("show",false);
Debug.Log("奖励!!"+spinRewardId);
UIManager.GetInstance().ShowView<RewardView>("RewardView", E_UI_Layer.Mid,(v)=> {
v.DrawReward(0, GameManager.turnTable_SO.spinReward[spinRewardId].num);
});
}
private float _endAngle = 0f;
/// <summary>
/// 最终停止的角度[0, 360]
/// </summary>
private float EndAngle
{
get { return _endAngle; }
set
{
_endAngle = Mathf.Abs(value);
// print("End Angle: " + value);
_endAngle = (_endAngle % 360); //将角度限定在[0, 360]这个区间
_endAngle = -_endAngle - 360 * GameManager.turnTable_SO.turnsNum; //多N圈并取反,圈数能使减速阶段变得更长
}
}
}