• 小松鼠踩一踩游戏



    一、 介绍和知识点

    玩家通过跳跃踩砖块,达到相应的百分比,即可过关。
    有3个关卡
    可以暂停
    在这里插入图片描述
    在这里插入图片描述

    堆栈
    数据字典
    枚举
    UnityFacade 门面设计模式
    从资源文件中获取音频文件


    九、UnityFacade 门面设计模式

    这是一个UnityFacade类的代码,它是一个单例类,用于管理游戏中的各种Manager,包括AudioManagerUIManagerGameManagerSaveManager。下面是代码的逐行注释:
    
    ```csharp
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class UnityFacade : MonoBehaviour
    {
        private AudioManager _audioManager; //声明一个私有的AudioManager对象
        private UIManager _uiManager; //声明一个私有的UIManager对象
        private GameManager _gameManager; //声明一个私有的GameManager对象
        private SaveManager _saveManager; //声明一个私有的SaveManager对象
        private float _timer; //声明一个私有的计时器变量
    
        //声明一个公有的计时器属性
        public float Timer
        {
            get { return _timer; }
            set { _timer = value; }
        }
    
        //声明一个公有的GameManager属性
        public GameManager GameManager
        {
            get { return _gameManager; }
        }
    
        //声明一个公有的UIManager属性
        public UIManager UiManager
        {
            get { return _uiManager; }
        }
    
        //声明一个公有的AudioManager属性
        public AudioManager AudioManager
        {
            get { return _audioManager; }
        }
    
        //声明一个公有的SaveManager属性
        public SaveManager SaveManager
        {
            get { return _saveManager; }
        }
    
        //声明一个私有的静态UnityFacade对象
        private static UnityFacade _instance;
    
        //声明一个公有的静态UnityFacade对象,用于获取UnityFacade的单例
        public static UnityFacade Instance
        {
            get { return _instance; }
        }
    
        //在Awake中初始化单例
        private void Awake()
        {
            if (_instance == null)
            {
                _instance = this;
            }
        }
    
        void Start()
        {
            //实例化所有Manager
            _audioManager = new AudioManager();
            _uiManager = new UIManager();
            _gameManager = new GameManager();
            _saveManager = new SaveManager();
            //调用所有的Manager的OnInit方法
            _audioManager.OnInit();
            _uiManager.OnInit();
            _saveManager.OnInit();
            _gameManager.OnInit();
        }
    
        // Update is called once per frame
        void Update()
        {
            //调用所有Manager的OnUpdate方法
            _audioManager.OnUpdate();
            _uiManager.OnUpdate();
            _gameManager.OnUpdate();
            _saveManager.OnUpdate();
        }
    
        //在销毁对象时调用所有Manager的OnDestroy方法
        private void OnDestroy()
        {
            _audioManager.OnDestroy();
            _uiManager.OnDestroy();
            _gameManager.OnDestroy();
            _saveManager.OnDestroy();
        }
    
        //启动计时器倒计时
        public void StartTimerCountDown()
        {
            StartCoroutine(_gameManager.TimerCountIEnumerator());
        }
    
        //生成奖励物品
        public void SpawnAward()
        {
            _gameManager.SpawnAward();
        }
    
        //生成惩罚物品
        public void SpawnPunishment()
        {
            _gameManager.SpawnPunishment();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115

    UnityFacade类是一个单例类,用于管理游戏中的各种Manager,包括AudioManager、UIManager、GameManager和SaveManager。在Start函数中,实例化所有Manager并调用其OnInit方法,然后在Update函数中调用所有Manager的OnUpdate方法,确保所有Manager都在运行。在OnDestroy函数中,调用所有Manager的OnDestroy方法,确保在销毁对象时所有Manager都被正确销毁。此外,UnityFacade类还提供了一些公有方法,如StartTimerCountDown、SpawnAward和SpawnPunishment,用于管理游戏中的一些功能。


    二、 声音全局管理器

    这段代码的作用是实现游戏中的音频管理,具体包括以下功能:

    1. 创建音频管理器:在OnInit方法中,创建一个名为"AudiManager"的GameObject,并将其作为音频管理器的根节点。同时,创建名为"BGM"和"Sound"的子节点,并将背景音乐和音效的AudioSource组件分别添加到这两个子节点上。

    2. 加载音频资源:在LoadAudioResources方法中,使用Resources.Load方法加载所有的背景音乐和音效资源,并将它们存储在对应的字典中。其中,BGMType和SoundType是两个枚举类型,用于区分不同的背景音乐和音效。

    3. 播放背景音乐:通过PlayBGM方法,可以播放指定类型的背景音乐。在此方法中,通过字典查找找到对应的音频资源,并将其设置为_bgmAudioSource的clip属性,最后调用Play方法开始播放背景音乐。

    4. 停止背景音乐:通过StopBGM方法,可以停止当前正在播放的背景音乐。

    5. 播放音效:通过PlaySound方法,可以播放指定类型的音效。在此方法中,通过字典查找找到对应的音频资源,并调用PlayOneShot方法播放音效。

    6. 单例模式:通过将AudioManager继承自BaseManager,并利用BaseManager的单例模式,确保全局只有一个音频管理器实例。

    7. 枚举类型:通过BGMType和SoundType枚举类型,区分不同的背景音乐和音效。

    8. 继承和虚方法:将AudioManager继承自BaseManager,并重写OnInit方法,实现了音频管理器的抽象和多态。

    9. Resources功能:使用Unity中的Resources.Load方法加载音频资源,实现了游戏中的音频动态加载和卸载。

    10. 委托和事件:通过定义PlayBGMEvent和StopBGMEvent委托类型和相应的事件,使得其他游戏对象可以订阅和响应这些事件,实现了游戏中音频播放和停止的协作功能。

    
    
    ```C#
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class AudioManager : BaseManager
    {
        //定义两个音源组件
        private AudioSource _bgmAudioSource;
        private AudioSource _soundAudioSource;
        //定义背景音乐和音效的字典
        private Dictionary<BGMType, AudioClip> _bgmDict;
        private Dictionary<SoundType, AudioClip> _soundDict;
    
        //初始化方法
        public override void OnInit()
        {
            //创建音频管理器、背景音乐、音效三个游戏对象,并设置它们的父节点
            GameObject audioManagerGo = new GameObject("AudioManager");
            GameObject bgm = new GameObject("BGM");
            GameObject sound = new GameObject("Sound");
            bgm.transform.SetParent(audioManagerGo.transform);
            sound.transform.SetParent(audioManagerGo.transform);
            //给背景音乐和音效游戏对象添加音源组件
            _bgmAudioSource = bgm.AddComponent<AudioSource>();
            _soundAudioSource = sound.AddComponent<AudioSource>();
            //设置音源组件的初始值,背景音乐循环播放,音效不循环,都不立即播放
            _bgmAudioSource.loop = true;
            _bgmAudioSource.playOnAwake = true;
            _soundAudioSource.loop = false;
            _soundAudioSource.playOnAwake = false;
            //设置背景音乐的默认音量
            _bgmAudioSource.volume = 0.1f;
            //加载声音资源
            LoadAudioResources();
        }
    
        //加载声音资源
        private void LoadAudioResources()
        {
            //背景音乐资源的加载
            AudioClip aboutUsClip = Resources.Load<AudioClip>("BGM/AboutUs");
            AudioClip gameBgm1Clip = Resources.Load<AudioClip>("BGM/GameBgm1");
            AudioClip gameBgm2Clip = Resources.Load<AudioClip>("BGM/GameBgm2");
            AudioClip gameBgm3Clip = Resources.Load<AudioClip>("BGM/GameBgm3");
            AudioClip gameBgm4Clip = Resources.Load<AudioClip>("BGM/GameBgm4");
            AudioClip gameBgm5Clip = Resources.Load<AudioClip>("BGM/GameBgm5");
            AudioClip mainPanelClip = Resources.Load<AudioClip>("BGM/MainPanel");
            //将背景音乐资源添加到字典中
            _bgmDict = new Dictionary<BGMType, AudioClip>();
            _bgmDict.Add(BGMType.AboutUS, aboutUsClip);
            _bgmDict.Add(BGMType.BGM_1, gameBgm1Clip);
            _bgmDict.Add(BGMType.BGM_2, gameBgm2Clip);
            _bgmDict.Add(BGMType.BGM_3, gameBgm3Clip);
            _bgmDict.Add(BGMType.BGM_4, gameBgm4Clip);
            _bgmDict.Add(BGMType.BGM_5, gameBgm5Clip);
            _bgmDict.Add(BGMType.Main_Panel, mainPanelClip);
    
            //音效音乐资源的加载
            AudioClip awardClip = Resources.Load<AudioClip>("Sounds/Award");
            AudioClip brickClip = Resources.Load<AudioClip>("Sounds/Brick");
            AudioClip brick1Clip = Resources.Load<AudioClip>("Sounds/Brick1");
            AudioClip brickDestroyClip = Resources.Load<AudioClip>("Sounds/Brick_Destroy");
            AudioClip buttonClip = Resources.Load<AudioClip>("Sounds/Button");
            AudioClip failedClip = Resources.Load<AudioClip>("Sounds/Failed");
            AudioClip fallDownClip = Resources.Load<AudioClip>("Sounds/Fall_Down");
            AudioClip jumpClip = Resources.Load<AudioClip>("Sounds/Jump");
            AudioClip punishmentClip = Resources.Load<AudioClip>("Sounds/Punishment");
            AudioClip winClip = Resources.Load<AudioClip>("Sounds/Win");
            AudioClip winPerfectClip = Resources.Load<AudioClip>("Sounds/WinPerfect");
            //将音效资源添加到字典中
            _soundDict = new Dictionary<SoundType, AudioClip>();
            _soundDict.Add(SoundType.Award, awardClip);
            _soundDict.Add(SoundType.Brick, brickClip);
            _soundDict.Add(SoundType.Brick_1, brick1Clip);
            _soundDict.Add(SoundType.Brick_Destroy, brickDestroyClip);
            _soundDict.Add(SoundType.Button, buttonClip);
            _soundDict.Add(SoundType.Failed, failedClip);
            _soundDict.Add(SoundType.Fall_Down, fallDownClip);
            _soundDict.Add(SoundType.Jump, jumpClip);
            _soundDict.Add(SoundType.Punishment, punishmentClip);
            _soundDict.Add(SoundType.Win, winClip);
            _soundDict.Add(SoundType.WinPerfect, winPerfectClip);
        }
    
        //播放背景音乐
        public void PlayBGM(BGMType bgmType)
        {
            //停止当前背景音乐的播放
            _bgmAudioSource.Stop();
            //设置新的背景音乐,并播放
            _bgmAudioSource.clip = _bgmDict[bgmType];
            _bgmAudioSource.Play();
        }
    
        //播放音效
        public void PlaySound(SoundType soundType)
        {
            //停止当前音效的播放
            _soundAudioSource.Stop();
            //设置新的音效,并播放
            _soundAudioSource.clip = _soundDict[soundType];
            _soundAudioSource.Play();
        }
    
        //关闭BGM播放
        public void StopBGM()
        {
            _bgmAudioSource.Stop();
        }
    
        //音量控制
        public void ControlVolume(float bgmVolume, float soundVolume)
        {
            _bgmAudioSource.volume = bgmVolume;
            _soundAudioSource.volume = soundVolume;
        }
    
        //以下三个方法都是空实现,不做任何操作
        public override void OnUpdate()
        {
        }
    
        public override void OnDestroy()
        {
        }
    }
    
    //定义背景音乐类型枚举
    public enum BGMType
    {
        AboutUS,
        BGM_1,
        BGM_2,
        BGM_3,
        BGM_4,
        BGM_5,
        Main_Panel
    }
    
    //定义音效类型枚举
    public enum SoundType
    {
        Award, Brick, Brick_1, Brick_Destroy, Button, Failed, Fall_Down, Jump, Punishment, Win, WinPerfect
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147

    测试音频代码

    下面这两段代码,用于测试音频组件,可以复用

    在这里插入图片描述

    
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class aaa : MonoBehaviour
    {
    	private AudioManager _audioManager;
    
    	public AudioManager AudioManager
    	{
    		get { return _audioManager; }
    	}
    
    	private static aaa _instance;
    
    	public static aaa Instance
    	{
    		get { return _instance; }
    	}
    
    	private void Awake()
    	{
    		if (_instance == null)
    		{
    			_instance = this;
    		}
    	}
    
    	// Use this for initialization
    	void Start()
    	{
    		//实例化所有Manager
    		_audioManager = new AudioManager();
    		// 调用所有的Manager的OnInit方法
    		_audioManager.OnInit();
    	}
    
    	// Update is called once per frame
    	void Update()
    	{
    		_audioManager.OnUpdate();
    	}
    
    	private void OnDestroy()
    	{
    		_audioManager.OnDestroy();
    	}
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class TestAudioPanel : MonoBehaviour
    {
    
    	public Button playSoundBtn;
    	public Button playBGMBtn;
    	public Slider volumeSlider;
    	
    	// Use this for initialization
    	void Start () {
    		playSoundBtn.onClick.AddListener(delegate { PlaySoundButtonClicked(); });
    		playBGMBtn.onClick.AddListener(delegate { PlayBGMButtonClicked(); });
    		volumeSlider.onValueChanged.AddListener(delegate(float arg0) { SliderValueChanged(arg0); });
    	}
    	
    	// Update is called once per frame
    	void Update () {
    		
    	}
    
    	private void PlaySoundButtonClicked()
    	{
    		aaa.Instance.AudioManager.PlaySound(SoundType.Button);
    	}
    
    	private void PlayBGMButtonClicked()
    	{
    		aaa.Instance.AudioManager.PlayBGM(BGMType.Main_Panel);
    	}
    
    	private void SliderValueChanged(float value)
    	{
    		aaa.Instance.AudioManager.ControlVolume(value,value);
    	}
    	
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    UI全局管理器

    父类抽象类 BaseManager

    该抽象类定义了一个基本的管理器,其具体实现可以继承该类并实现三个抽象方法,以满足具体的需求。其中,OnInit() 方法用于初始化管理器、OnUpdate() 方法用于在每帧更新管理器、OnDestroy() 方法用于销毁管理器。这样,我们就可以通过继承该类来编写各种各样的管理器,从而更好地管理游戏中的各种资源、对象和逻辑。

    using System.Collections; 
    using System.Collections.Generic; 
    using UnityEngine; 
    
    public abstract class BaseManager  // 定义抽象类 BaseManager
    {
    
        public abstract void OnInit();  // 声明抽象方法 OnInit()
        public abstract void OnUpdate();  // 声明抽象方法 OnUpdate()
        public abstract void OnDestroy();  // 声明抽象方法 OnDestroy()
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    子类 UIManager

    这段代码主要实现了一个UI管理器,其中包括了以下功能:

    1. 加载面板:根据传入的面板类型,从预设体字典中获取对应的预设体并实例化,然后执行该面板的OnEnter方法,同时将该面板入栈。
    2. 关闭(弹出)顶层面板:从栈中弹出顶层面板,并执行该面板的OnExit方法,同时恢复下一个面板的OnResume方法。
    3. 初始化:获取Canvas的Transform属性,初始化预设体字典和已实例化面板字典,并加载第一个面板。
    4. 枚举类型:定义了PanelType枚举类型,包括了所有的面板类型。

    补充说明:

    1. BaseManager是一个抽象类,该UIManager类继承自BaseManager,并且需要实现其中的三个虚函数:OnInit、OnUpdate和OnDestroy。
    2. 该UIManager类中还定义了一个InstantiatedPanelDict属性,用于获取已实例化面板字典。
    ```csharp
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class UIManager : BaseManager
    {
        private Transform _canvasTransform; //Canvas的Transform组件
        private Dictionary<PanelType, GameObject> _uiPanelPrefabDict; //UI面板预制体字典
        private Dictionary<PanelType, BasePanel> _instantiatedPanelDict; //实例化的UI面板字典
        private Stack<BasePanel> _panelStack; //UI面板栈
    
        public Dictionary<PanelType, BasePanel> InstantiatedPanelDict
        {
            get { return _instantiatedPanelDict; }
        }
    
        /// 
        /// 加载面板
        /// 
        /// 
        /// 
        public BasePanel PushPanel(PanelType panelType)
        {
            //从实例化的面板字典中获取该面板
            BasePanel panel = null;
            _instantiatedPanelDict.TryGetValue(panelType, out panel);
            if (panel == null)
            {
                //说明该面板从未实例化过(从未入栈),此处需要实例化
                GameObject panelPrefab = _uiPanelPrefabDict[panelType];
                GameObject panelGO = GameObject.Instantiate(panelPrefab, _canvasTransform, false);
                panel = panelGO.GetComponent<BasePanel>();
                _instantiatedPanelDict.Add(panelType, panel); //将该面板加入实例化的面板字典中
            }
            else
            {
                //说明该面板已经实例化,入栈后被出栈,处于被禁用状态,需要重新启用
                panel.gameObject.SetActive(true);
            }
    
            //执行该Panel的OnEnter
            panel.OnEnter();
            if (_panelStack.Count > 0)
            {
                BasePanel peekPanel = _panelStack.Peek();
                peekPanel.OnPause();
            }
            _panelStack.Push(panel); //将该面板入栈
            return panel;
        }
    
        /// 
        /// 关闭(弹出)顶层面板
        /// 
        public void PopPanel()
        {
            if (_panelStack.Count > 0)
            {
                BasePanel peekPanel = _panelStack.Pop();
                peekPanel.OnExit();
                if (_panelStack.Count > 0)
                {
                    BasePanel secPeekPanel = _panelStack.Peek();
                    secPeekPanel.OnResume();
                }
            }
        }
    
        public override void OnInit()
        {
            //获取挂载Canvas的Transform属性
            _canvasTransform = GameObject.Find("Canvas").transform;
            //初始化面板预制体字典
            _uiPanelPrefabDict = new Dictionary<PanelType, GameObject>();
            _uiPanelPrefabDict.Add(PanelType.Main, Resources.Load<GameObject>("UIPanel/Panel_Main"));
            _uiPanelPrefabDict.Add(PanelType.Game, Resources.Load<GameObject>("UIPanel/Panel_Game"));
            _uiPanelPrefabDict.Add(PanelType.Result, Resources.Load<GameObject>("UIPanel/Panel_Result"));
            _uiPanelPrefabDict.Add(PanelType.Battle, Resources.Load<GameObject>("UIPanel/Panel_Battle"));
            _uiPanelPrefabDict.Add(PanelType.Fail, Resources.Load<GameObject>("UIPanel/Panel_Fail"));
            _uiPanelPrefabDict.Add(PanelType.Success, Resources.Load<GameObject>("UIPanel/Panel_Success"));
            _uiPanelPrefabDict.Add(PanelType.Pause, Resources.Load<GameObject>("UIPanel/Panel_Pause"));
            _uiPanelPrefabDict.Add(PanelType.Level, Resources.Load<GameObject>("UIPanel/Panel_Level"));
            _uiPanelPrefabDict.Add(PanelType.Index, Resources.Load<GameObject>("UIPanel/Panel_Index"));
            //初始化
            _instantiatedPanelDict = new Dictionary<PanelType, BasePanel>();
            _panelStack = new Stack<BasePanel>();
            //加载第一个Panel
            // PushPanel(PanelType.Main);
        }
    
        public override void OnUpdate()
        {
    
        }
    
        public override void OnDestroy()
        {
    
        }
    }
    
    public enum PanelType
    {
        Main,
        Game,
        Result,
        Battle,
        Fail,
        Success,
        Pause,
        Level,
        Index
    }
    
    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121

    这段代码实现了一个UI管理器,用于管理游戏中的UI面板。其中,PushPanel()函数用于加载面板,PopPanel()函数用于关闭顶层面板,OnInit()函数用于在UI管理器被初始化时加载第一个面板。

    UI管理器中使用了一个面板栈_panelStack,用于存储当前打开的所有UI面板,实现了UI面板的层级管理。同时,还使用了两个面板字典_uiPanelPrefabDict_instantiatedPanelDict,用于存储预制体和实例化的面板。

    代码中使用了单例模式实现了UI管理器的唯一性。同时,还继承了BaseManager类,实现了对游戏管理器的统一管理。


    四、 UI按钮的引用

    父类 BasePanel

    这四个方法是状态机中状态的生命周期方法,用于管理状态的进入、暂停、恢复和退出。

    具体来说,当一个状态被切换到时,首先会调用OnEnter()方法,用于初始化状态的数据和变量。当状态被暂停时(例如切换到其他状态),会调用OnPause()方法,用于暂停状态的逻辑和动画。当状态恢复时(例如从其他状态切换回该状态),会调用OnResume()方法,用于恢复状态的逻辑和动画。当状态被退出时,会调用OnExit()方法,用于清理状态的数据和变量。

    using System.Collections;                      
    using System.Collections.Generic;              
    using UnityEngine;                              
    
    public abstract class BasePanel : MonoBehaviour  // 定义一个抽象类 BasePanel,继承自 MonoBehaviour 类
    {
    
        public abstract void OnEnter();              // 声明一个抽象方法 OnEnter,由子类实现
    
        public abstract void OnPause();              // 声明一个抽象方法 OnPause,由子类实现
    
        public abstract void OnResume();             // 声明一个抽象方法 OnResume,由子类实现
    
        public abstract void OnExit();               // 声明一个抽象方法 OnExit,由子类实现
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    子类主面板 MainPanel

    1. 定义MainPanel类,继承自BasePanel。
    2. 定义开始按钮和关闭按钮两个公共属性。
    3. 在Start()方法中添加开始按钮和关闭按钮的点击事件监听器。
    4. 在StartButtonClicked()方法中调用UnityFacade.Instance.UiManager.PushPanel()方法,实现面板的切换到GamePanel。
    5. 在CloseButtonClicked()方法中调用UnityFacade.Instance.UiManager.PopPanel()方法,实现当前面板的弹出。
    6. 在OnEnter()方法中实现面板进入时的操作。
    7. 在OnPause()方法中禁用开始按钮和关闭按钮,实现面板暂停时的操作。
    8. 在OnResume()方法中启用开始按钮和关闭按钮,实现面板恢复时的操作。
    9. 在OnExit()方法中隐藏当前面板,实现面板退出时的操作。
    
    
    ```using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class MainPanel : BasePanel //继承自BasePanel
    {
        public Button startBtn; //开始按钮
        public Button closeBtn; //关闭按钮
    
        private void Start()
        {
            //添加开始按钮点击事件监听器
            startBtn.onClick.AddListener(delegate { StartButtonClicked(); });
            //添加关闭按钮点击事件监听器
            closeBtn.onClick.AddListener(delegate { CloseButtonClicked(); });
        }
    
        private void StartButtonClicked()
        {
            //点击开始按钮,推入GamePanel
            UnityFacade.Instance.UiManager.PushPanel(PanelType.Game);
        }
    
        private void CloseButtonClicked()
        {
            //点击关闭按钮,弹出当前面板
            UnityFacade.Instance.UiManager.PopPanel();
        }
    
        public override void OnEnter()
        {
            //面板进入时调用此方法
            Debug.Log("MainPanel加载了");
        }
    
        public override void OnPause()
        {
            //面板暂停时调用此方法,禁用开始按钮和关闭按钮
            startBtn.interactable = false;
            closeBtn.interactable = false;
        }
    
        public override void OnResume()
        {
            //面板恢复时调用此方法,启用开始按钮和关闭按钮
            startBtn.interactable = true;
            closeBtn.interactable = true;
        }
    
        public override void OnExit()
        {
            //面板退出时调用此方法,隐藏当前面板
            this.gameObject.SetActive(false);
        }
    }```
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    子类 游戏中 GamePanel

    这段代码实现了一个游戏面板(GamePanel),继承自一个基础面板(BasePanel),并实现了在面板中的按钮点击事件。具体来说,这个面板有两个按钮:resultBtn和closeBtn,点击resultBtn会跳转到一个结果面板(PanelType.Result),而点击closeBtn会关闭当前面板。

    在 Start() 方法中,通过监听按钮的点击事件来实现按钮的功能,即 resultBtn 点击时调用 ResultButtonClicked() 方法,closeBtn 点击时调用 CloseButtonClicked() 方法。ResultButtonClicked() 方法中调用了 UnityFacade.UiManager.PushPanel() 方法,用于跳转到结果面板,而 CloseButtonClicked() 方法中调用了 UnityFacade.UiManager.PopPanel() 方法,用于关闭当前面板。

    在 OnEnter() 方法中,当这个游戏面板被打开时,会输出一个 Debug.Log() 信息,提示面板被打开了。

    在 OnPause() 方法中,当这个游戏面板被暂停时,会将 resultBtn 和 closeBtn 的 interactable 属性设置为 false,即这两个按钮将不再响应点击事件。

    在 OnResume() 方法中,当这个游戏面板从暂停状态中恢复时,会将 resultBtn 和 closeBtn 的 interactable 属性设置为 true,即这两个按钮将重新响应点击事件。

    在 OnExit() 方法中,当这个游戏面板被关闭时,会将这个游戏面板的 gameObject 设置为不可见,即关闭这个游戏面板。

    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    // 继承自 BasePanel
    public class GamePanel : BasePanel
    {
        // 定义两个按钮
        public Button resultBtn;
        public Button closeBtn;
    
        // 在 Start 函数中添加按钮点击事件监听
        private void Start()
        {
            resultBtn.onClick.AddListener(delegate { ResultButtonClicked(); });
            closeBtn.onClick.AddListener(delegate { CloseButtonClicked(); });
        }
    
        // 点击结果按钮的处理函数
        private void ResultButtonClicked()
        {
            // 调用 UnityFacade 的 UiManager 的 PushPanel 函数,打开结果面板
            UnityFacade.Instance.UiManager.PushPanel(PanelType.Result);
        }
    
        // 点击关闭按钮的处理函数
        private void CloseButtonClicked()
        {
            // 调用 UnityFacade 的 UiManager 的 PopPanel 函数,关闭当前面板
            UnityFacade.Instance.UiManager.PopPanel();
        }
    
        // 进入面板时的处理函数
        public override void OnEnter()
        {
            Debug.Log("GamePanel打开了");
        }
    
        // 暂停面板时的处理函数
        public override void OnPause()
        {
            // 将两个按钮设置为不可用
            resultBtn.interactable = false;
            closeBtn.interactable = false;
        }
    
        // 恢复面板时的处理函数
        public override void OnResume()
        {
            // 将两个按钮设置为可用
            resultBtn.interactable = true;
            closeBtn.interactable = true;
        }
    
        // 退出面板时的处理函数
        public override void OnExit()
        {
            // 将自身的 gameObject 设置为不可见
            this.gameObject.SetActive(false);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    子类 游戏结果 ResultPanel

    它实现了一个游戏面板,名为ResultPanel。这个面板里有一个按钮,名为closeBtn,点击它可以关闭当前面板。这个面板继承自BasePanel类,因此实现了BasePanel类中定义的四个方法:OnEnter、OnPause、OnResume、OnExit。其中,OnEnter方法是在面板打开时被调用的,OnPause方法是在面板被暂停时被调用的,OnResume方法是在面板恢复时被调用的,OnExit方法是在面板关闭时被调用的。在这里,OnEnter方法只是打印了一条调试信息。Start方法用于初始化面板,它给closeBtn按钮添加了一个事件监听器,当按钮被点击时,会执行CloseButtonClicked方法。CloseButtonClicked方法中,通过UnityFacade.Instance.UiManager.PopPanel()方法关闭当前面板。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class ResultPanel : BasePanel
    {
    
    	public Button closeBtn;
    	
    	
    	
    	public override void OnEnter()
    	{
    		Debug.Log("ResultPanel打开了");
    	}
    
    	public override void OnPause()
    	{
    		
    	}
    
    	public override void OnResume()
    	{
    		
    	}
    
    	public override void OnExit()
    	{
    		this.gameObject.SetActive(false);
    	}
    
    	// Use this for initialization
    	void Start () {
    		closeBtn.onClick.AddListener(delegate { CloseButtonClicked(); });
    	}
    
    	private void CloseButtonClicked()
    	{
    		UnityFacade.Instance.UiManager.PopPanel();
    	}
    	// Update is called once per frame
    	void Update () {
    		
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    角色动画器、控制角色移动

    角色可以跳跃、行走
    在这里插入图片描述

    在这里插入图片描述


    游戏奖惩道具

    掉血的砖块:用数组存储四张图片,踩一下hp-1。

    public void Injured()
    	{
    		_hp--;
    		if (_hp > 0)
    		{
    			if (_hp == 3)
    			{
    				UnityFacade.Instance.GameManager.AddTouchCount();
    			}
    			UnityFacade.Instance.AudioManager.PlaySound(SoundType.Brick);
    			_spriteRenderer.sprite = sprites[4 - _hp];
    		}
    		else
    		{
    			UnityFacade.Instance.AudioManager.PlaySound(SoundType.Brick_Destroy);
    			Destroy(this.gameObject);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述


    保护罩:玩家得到后,不受任何伤害

      protectorGO.SetActive(true);
    
    • 1

    在这里插入图片描述

    红色感叹号炸弹:计时器减少10秒钟


    绿色感叹号:计时器时间增加10秒钟


    死亡小球:玩家碰到后
    直接游戏结束

    在这里插入图片描述

    private void Move()
    	{
    		if (Math.Abs(_rigidbody2D.velocity.x) < 0.05f&&_isOnGround)
    		{
    			if (_direction == MoveDirection.Left)
    			{	
    				_rigidbody2D.velocity=new Vector2((int)MoveDirection.Right*vSpeed,0);
    				_direction = MoveDirection.Right;
    			}else if (_direction == MoveDirection.Right)
    			{
    				_rigidbody2D.velocity=new Vector2((int)MoveDirection.Left*vSpeed,0);
    				_direction = MoveDirection.Left;
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    过关星星动画:
    在这里插入图片描述


  • 相关阅读:
    linux使用yum安装2.x版git
    重读GPDB 和 TiDB 论文引发的 HTAP 数据库再思考
    JDK1.8之前与之后 HashMap底层实现原理的差别
    防火墙详解
    WireShark抓包工具的安装
    汇付国际为跨境电商赋能:做合规的跨境支付平台!
    linux启动停止mysql常见错误
    软考高级系统架构设计师论文真题分析系列之:论软件架构风格
    熬夜万字肝爆Redis知识总结,全网最全
    【Typescript基础】函数详解
  • 原文地址:https://blog.csdn.net/qq_20179331/article/details/130542073