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 小时前
Unity网络通信的插件分享,及TCP粘包分包问题处理
tcp/ip·unity·游戏引擎
weixin_lynhgworld12 小时前
从概率游戏到价值创造:盲盒一番赏的透明化革命
游戏
liulilittle1 天前
游戏加速器核心技术:动态超发
开发语言·网络·c++·网络协议·游戏·加速器·游戏加速
erxij2 天前
【游戏引擎之路】登神长阶(十八):3天制作Galgame引擎《Galplayer》——无敌之道心
游戏引擎
lizz312 天前
GAMES101 lec2-数学基础1(线性代数)
线性代数·游戏引擎·图形渲染
啊基米德2 天前
lua(xlua)基础知识点记录一
unity·lua·xlua
夜色。2 天前
Unity Android Logcat插件 输出日志中文乱码解决
android·unity
X-mj2 天前
Unity URP + XR 自定义 Skybox 在真机变黑问题全解析与解决方案(支持 Pico、Quest 等一体机)
unity·游戏引擎·xr
erxij2 天前
【游戏引擎之路】登神长阶(十七):Humanoid动画——长风破浪会有时,直挂云帆济沧海
游戏引擎
erxij2 天前
【游戏引擎之路】登神长阶(十九):3D物理引擎——岁不寒,无以知松柏;事不难,无以知君子
3d·游戏引擎