100个 Unity小游戏系列三 -Unity 抽奖游戏专题一 转盘抽奖游戏

一 、效果展示

二、知识点

2.1 布局需要实现功能

1、转动的根目录为itemSpinRoot

2、创建对应的item

3、每个item转动的角度

2.2 代码

cs 复制代码
public class WheelDialog : UIBase
    {
        [SerializeField] Button btnClick;
        [SerializeField] Button btnClose;
        [SerializeField] Sprite[] itemImgs;

        [SerializeField] Transform itemParent;
        Transform itemSpinRoot;

        [Header("物体数量")][SerializeField] int ItemCount = 8;

        private float item_rangle;

        private RewardData[] rewardDatas;

        protected internal override void OnInit(UIView view)
        {
            base.OnInit(view);

            item_rangle = 360f / ItemCount;

           //转动的根目录为itemSpinRoot
            itemSpinRoot = itemParent.parent;

            btnClick.onClick.RemoveAllListeners();
            btnClick.onClick.AddListener(OnClickSpin);
            btnClose.onClick.RemoveAllListeners();
            btnClose.onClick.AddListener(OnCloseEvent);

            rewardDatas = LuckyManager.Instance.GetDefaultWheelData(ItemCount);
            //创建对应的item
            CreateItems(rewardDatas);
        }

        protected internal override void OnOpen(object userData)
        {
            base.OnOpen(userData);

            ResetWheels();
        }



        private void ResetWheels()
        {

        }

        private void CreateItems(RewardData[] wheel_tb)
        {
            Vector3 init_pos = itemParent.GetChild(0).transform.localPosition;
            if (wheel_tb.Length != ItemCount)
            {
                Debug.LogError("wheel_tb.Count !=  wheel_count !!!");
            }

            for (int i = 0; i < wheel_tb.Length; i++)
            {
                var reward_data = wheel_tb[i];
                var next_rot = Quaternion.Euler(0, 0, i * item_rangle);
                var next_pos = next_rot * init_pos;
                GameObject item;
                if (i + 1 <= itemParent.childCount)
                {
                    item = itemParent.GetChild(i).gameObject;
                }
                else
                {
                    item = Instantiate(itemParent.GetChild(0).gameObject, itemParent);
                }
                //每个item转动的角度
                item.transform.localPosition = next_pos;
                item.transform.localRotation = next_rot;

                var reward_text = item.GetComponentInChildren<TextMeshProUGUI>();
                var reward_img = item.GetComponentInChildren<Image>();
                reward_img.sprite = itemImgs[reward_data.type - 1];
                reward_img.SetNativeSize();
                reward_text.text = string.Format("{0}", reward_data.amount);

                item.GetComponentInChildren<ParticleSystem>().GetComponent<Renderer>().sortingOrder = m_Canvas.sortingOrder + 1;
            }
        }

        private void OnClickSpin()
        {
            if (IsRolling)
            {
                return;
            }

            StartSpin(SpinComplete);
        }

}

三、转动核心逻辑

3.1 知识点

1、DOTween实现转动角度方法实现

public static TweenerCore<float, float, FloatOptions> To(

DOGetter<float> getter,

DOSetter<float> setter,

float endValue,

float duration)

{

return DOTween.ApplyTo<float, float, FloatOptions>(getter, setter, endValue, duration);

}

2、设置转动模式

roll_act.SetEase(GetEase());

3.2 代码

cs 复制代码
 private void StartSpin(Action<RewardData> onSpinCompleted)
        {
            IsRolling = true;
            int rewardId = LuckyManager.Instance.CalculateRewardId(rewardDatas);
            var reward_data = LuckyManager.Instance.GetDataById(rewardDatas, rewardId, out int wheel_index);

            //初始角度
            float cur_angle = itemSpinRoot.localRotation.eulerAngles.z;
            int round_count = UnityEngine.Random.Range(4, 5);
            //最后要转动的角度
            float final_angle = -item_rangle * wheel_index + 360 * round_count;

            float duration = 2.5f;
            // DOTween实现转动角度方法实现1
            var roll_act = DOTween.To(() => cur_angle, (x) => cur_angle = x, final_angle, duration);
           //转动模式设置
            roll_act.SetEase(GetEase());
            roll_act.onUpdate = () =>
            {
                // DOTween实现转动角度方法实现2
                itemSpinRoot.localRotation = Quaternion.Euler(0, 0, cur_angle);
            };
            roll_act.OnComplete(() =>
            {
                IsRolling = false;

                onSpinCompleted.Invoke(reward_data);
            });
        }

四、完整代码

cs 复制代码
using UnityEngine;
using DG.Tweening;
using System;
using UnityEngine.UI;
using TMPro;


namespace Pillow.Lucky
{
    public class WheelDialog : UIBase
    {
        [SerializeField] Button btnClick;
        [SerializeField] Button btnClose;
        [SerializeField] Sprite[] itemImgs;

        [SerializeField] Transform itemParent;
        Transform itemSpinRoot;

        [Header("物体数量")][SerializeField] int ItemCount = 8;

        private float item_rangle;

        private RewardData[] rewardDatas;

        protected internal override void OnInit(UIView view)
        {
            base.OnInit(view);

            item_rangle = 360f / ItemCount;

           //转动的根目录为itemSpinRoot
            itemSpinRoot = itemParent.parent;

            btnClick.onClick.RemoveAllListeners();
            btnClick.onClick.AddListener(OnClickSpin);
            btnClose.onClick.RemoveAllListeners();
            btnClose.onClick.AddListener(OnCloseEvent);

            rewardDatas = LuckyManager.Instance.GetDefaultWheelData(ItemCount);
            //创建对应的item
            CreateItems(rewardDatas);
        }

        protected internal override void OnOpen(object userData)
        {
            base.OnOpen(userData);

            ResetWheels();
        }



        private void ResetWheels()
        {

        }

        private void CreateItems(RewardData[] wheel_tb)
        {
            Vector3 init_pos = itemParent.GetChild(0).transform.localPosition;
            if (wheel_tb.Length != ItemCount)
            {
                Debug.LogError("wheel_tb.Count !=  wheel_count !!!");
            }

            for (int i = 0; i < wheel_tb.Length; i++)
            {
                var reward_data = wheel_tb[i];
                var next_rot = Quaternion.Euler(0, 0, i * item_rangle);
                var next_pos = next_rot * init_pos;
                GameObject item;
                if (i + 1 <= itemParent.childCount)
                {
                    item = itemParent.GetChild(i).gameObject;
                }
                else
                {
                    item = Instantiate(itemParent.GetChild(0).gameObject, itemParent);
                }
                //每个item转动的角度
                item.transform.localPosition = next_pos;
                item.transform.localRotation = next_rot;

                var reward_text = item.GetComponentInChildren<TextMeshProUGUI>();
                var reward_img = item.GetComponentInChildren<Image>();
                reward_img.sprite = itemImgs[reward_data.type - 1];
                reward_img.SetNativeSize();
                reward_text.text = string.Format("{0}", reward_data.amount);

                item.GetComponentInChildren<ParticleSystem>().GetComponent<Renderer>().sortingOrder = m_Canvas.sortingOrder + 1;
            }
        }

        private void OnClickSpin()
        {
            if (IsRolling)
            {
                return;
            }

            StartSpin(SpinComplete);
        }

        private void StartSpin(Action<RewardData> onSpinCompleted)
        {
            IsRolling = true;
            int rewardId = LuckyManager.Instance.CalculateRewardId(rewardDatas);
            var reward_data = LuckyManager.Instance.GetDataById(rewardDatas, rewardId, out int wheel_index);

            //初始角度
            float cur_angle = itemSpinRoot.localRotation.eulerAngles.z;
            int round_count = UnityEngine.Random.Range(4, 5);
            //最后要转动的角度
            float final_angle = -item_rangle * wheel_index + 360 * round_count;

            float duration = 2.5f;
            // DOTween实现转动角度方法实现1
            var roll_act = DOTween.To(() => cur_angle, (x) => cur_angle = x, final_angle, duration);
           //转动模式设置
            roll_act.SetEase(GetEase());
            roll_act.onUpdate = () =>
            {
                // DOTween实现转动角度方法实现2
                itemSpinRoot.localRotation = Quaternion.Euler(0, 0, cur_angle);
            };
            roll_act.OnComplete(() =>
            {
                IsRolling = false;

                onSpinCompleted.Invoke(reward_data);
            });
        }

        void SpinComplete(RewardData rewardData)
        {
            UIManager.Instance.ShowRewardDialog(rewardData, itemImgs);
        }


        private Ease GetEase()
        {
            int index = GetSelectLayoutIndex();

            switch (index)
            {
                case 2:
                    return Ease.OutBack;
                case 3:
                    return Ease.OutQuad;
                case 4:
                    return Ease.OutQuart;
                case 5:
                    return Ease.OutCubic;
                case 6:
                    return Ease.OutCirc;
                case 1:
                default:
                    return Ease.Linear;
            }
        }

    }

}

五、代码链接

https://github.com/lixianjun0903/luckydraw-master.git

相关推荐
李詹11 分钟前
Steam游戏服务器攻防全景解读——如何构建游戏级抗DDoS防御体系?
服务器·游戏·ddos
虾球xz7 小时前
游戏引擎学习第246天:将 Worker 上下文移到主线程创建
c++·学习·游戏引擎
虾球xz9 小时前
游戏引擎学习第240天:将渲染器移至第三层
c++·学习·游戏引擎
林枫依依12 小时前
Unity Webgl在编辑器中报错:Cannot connect to destination host
unity·编辑器·webgl
KhalilRuan12 小时前
Unity-Shader详解-其一
unity·游戏引擎
Clank的游戏栈17 小时前
Unity多线程渲染指令队列设计与集成技术详解
windows·unity·游戏引擎
胜天半子_王二_王半仙1 天前
godot源码编译
游戏引擎·godot
Thomas_YXQ1 天前
Unity3D IK解算器技术分析
开发语言·搜索引擎·unity·全文检索·unity3d·lucene
264玫瑰资源库1 天前
斗鱼娱乐电玩平台源码搭建实录
运维·服务器·游戏·娱乐
Tandy12356_1 天前
Godot开发2D冒险游戏——第二节:主角光环整起来!
游戏引擎·godot