Editor结构
UI顶层是一个Canvas用于渲染下方的Image,button以及TextMeshPro。
下方由:
包含UI的Button部分的PauseSelectionHightTabPanel
每个Button的组成
一个ButtonGameObject作为父物件,一个TextMeshPro作为子物件的复合体
每个Panel是个附带了HorizontalLayoutGroup 的EmptyObject
其确保了下方的所有TabImage,Tab,Button 保持一个间距相等的距离,
并且可以控制子物体的Szie和Scale
只使一个Tab作为ActiveObject,Tab的ActiveSelf属性会直接影响其他组件
代码UImanager通过Tab的Active切换实现。
Aspect radio Fiter组件
确保了大型Panel与屏幕适配
可以看看这篇:Aspect Ratio Fitter 重温总结(多图)_Huil的博客-CSDN博客
I的设计只需要一个Class即可实现
如下,UIManager:
using UnityEngine;
using UnityEngine.UI;
public class UIManager : SingletonMonoBehaviour<UIManager>
{
[SerializeField]
private bool _isPauseMenuOpen;
public bool IsPauseMenuOpen
{
get{
return _isPauseMenuOpen;
}
set{
_isPauseMenuOpen=value;
}
}
[SerializeField] private GameObject PauseMenuGOBJ;
[SerializeField] private GameObject[] menuTabs;
[SerializeField] private Button[] menuButtons;
protected override void Awake()
{
base.Awake();
PauseMenuGOBJ.SetActive(false);
IsPauseMenuOpen=false;
}
private void Update()
{
PauseMenu();
}
private void PauseMenu()
{
if(Input.GetKeyDown(KeyCode.Escape))
{
if(IsPauseMenuOpen)
{
DisablePauseMenu();
}
else
{
EnablePauseMenu();
}
//每次点击esc bool取反
IsPauseMenuOpen=!IsPauseMenuOpen;
}
}
private void DisablePauseMenu()
{
Time.timeScale=1;//使游戏进程继续运行
PauseMenuGOBJ.SetActive(false);
// Player.Instance.PlayerInputDisabled=false;//恢复Input
}
private void EnablePauseMenu()
{
Time.timeScale=0;//使游戏进程暂停
PauseMenuGOBJ.SetActive(true);
// Player.Instance.PlayerInputDisabled=true;//若其他Script存在输入,应该禁止其他系统需要的Input并使其无效。
System.GC.Collect();
HighlightTheSelectedTabButton();
}
private void HighlightTheSelectedTabButton()
{
for(int i=0;i<menuTabs.Length;i++)
{
if(menuTabs[i].activeSelf)
{
SetMenuTabActive(menuButtons[i]);//此处更改的对象应该为MenuButton
}
else
{
SetMenuTabInactive(menuButtons[i]);//此处更改的对象应该为MenuButton
}
}
}
private void SetMenuTabActive(Button button)
{
ColorBlock colors=button.colors;
colors.normalColor=colors.pressedColor;
button.colors=colors;
}
private void SetMenuTabInactive(Button button)
{
ColorBlock colors=button.colors;
colors.normalColor=colors.disabledColor;
button.colors=colors;
}
//此处提供一个可从外部调用的OnClick函数
/// <summary>
///
/// </summary>
/// <param name="buttonParam"> </param>
public void SwitchTheSelectedTab(int buttonParam)
{
for(int i=0;i<menuTabs.Length;i++)
{
if(menuTabs[i].activeSelf)
{
menuTabs[i].SetActive(false);
}
}
menuTabs[buttonParam].SetActive(true);
HighlightTheSelectedTabButton();
}
}
原理
Unity内部通过TIme.timescale来进行游戏进程的推进
来自官方api
- timeScale为0时,FixedUpdate完全停止
- 当
timeScale
设置为 0 时,如果您的所有函数都是独立于帧率的, 则游戏基本上处于暂停状态。 - 当
timeScale
设置为 0 时,不会调用 FixedUpdate 函数。 - 如果您减小了 /timeScale/,建议也将 Time.fixedDeltaTime 减小相同的量。
timeScale
影响 Time 类的所有时间和增量时间测量变量(但 realtimeSinceStartup 和 fixedDeltaTime 除外)。
System.GC.collect()
主动使用垃圾处理器,清理游戏进行中出现的Garbage;
Uimanager使用Tab的ActiveSelf属性达成切换条目(Tab)时同时改变Button和Image
ColorBlock
其为Button 各种条件下Color的复合属性,代码中对其直接进行调用更改。