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

相关推荐
勿忘初心911 天前
游戏手柄遥控越疆协作机器人[一]
游戏·机器人
全栈软件开发1 天前
萌猫 合并卡牌 RPG抽卡游戏 Unity3D休闲益智游戏源码完整项目
游戏·unity源码
HahaGiver6661 天前
从0到1做一个“字母拼词”Unity小游戏(含源码/GIF)- 字母拼词正确错误判断
unity·游戏引擎·游戏程序
远程软件小帮手1 天前
好用的云电脑!手机怎么用UU远程云电脑玩电脑游戏?
运维·服务器·游戏·电脑
yingxiao8882 天前
挖掘百亿“数字热土”!解读印度游戏与媒体娱乐的高速增长
游戏·娱乐·媒体
一个小狼娃2 天前
Android集成Unity避坑指南
android·游戏·unity
极客柒2 天前
Unity 协程GC优化记录
java·unity·游戏引擎
黄思搏2 天前
Unity SpriteRenderer 进度条 Shader 实现
unity·游戏引擎
猫屋小鱼丸2 天前
手把手教你在unity中实现一个视觉小说系统(一)
unity
国服第二切图仔2 天前
Rust开发实战之简单游戏开发(piston游戏引擎)
开发语言·rust·游戏引擎