C# Unity3d交互式暂停菜单,使用Input.GetAxis导航新UI
好的,我正在尝试创建一个交互式暂停菜单,它可以使用Unity 4.6的新UI访问Input.GetAxis 只要为可选元素(在我的例子中是一系列按钮)设置了导航关系,并且C# Unity3d交互式暂停菜单,使用Input.GetAxis导航新UI,c#,user-interface,unity3d,C#,User Interface,Unity3d,好的,我正在尝试创建一个交互式暂停菜单,它可以使用Unity 4.6的新UI访问Input.GetAxis 只要为可选元素(在我的例子中是一系列按钮)设置了导航关系,并且interactiable设置为true,则UI工作正常,但当我设置Time.timeScale=0.0f然后键盘输入导航不再工作。但是,鼠标输入的点击和动画仍按预期工作 我尝试了几种不同的方法来解决时间尺度问题,到目前为止,我得到的最好结果是在monobhavor基本对象的Update消息体中检查从Input.GetAxis(
interactiable
设置为true,则UI工作正常,但当我设置Time.timeScale=0.0f代码>然后键盘输入导航不再工作。但是,鼠标输入的点击和动画仍按预期工作
我尝试了几种不同的方法来解决时间尺度问题,到目前为止,我得到的最好结果是在monobhavor
基本对象的Update
消息体中检查从Input.GetAxis()
返回的值。这在某种程度上是可行的,但我的结果是按钮选择集合的顶部或底部。我认为这是因为update的调用远远多于FixedUpdate
,如果我的控制台打印出更多对上下移动选择的方法的调用,那么update就有意义了。因此,我认为这是一个“办公空间”类型的错误,小数点后1位或一些愚蠢的东西,但我似乎看不到它。否则,我认为我的解决方案将是一个相当可行的解决方案。
下面是我的Unity设置的图像,其中包含Unity 4.6中提到的游戏对象,后面是我的代码
公共类玩家游戏菜单:单行为
{
公共事件系统;
可选择选择按钮;
公众可选择地位;
公共可选设置;
公共储蓄;
公众选择退出;
公共广播暂停;
列表按钮;
int selecteButtonIndex=0;
公共画布菜单;
void Start()
{
Menu.enabled=false;
按钮=新列表();
按钮。添加(状态);
按钮。添加(设置);
按钮。添加(保存);
按钮。添加(退出);
SelectedButton=按钮[0];
}
无效更新()
{
CheckInput();
如果(暂停&&!菜单。已启用)
{
ShowMenu();
}
如果(!暂停&&Menu.enabled),则为else
{
HideMenu();
}
}
void ShowMenu()
{
暂停=真;
Menu.enabled=true;
Time.timeScale=0.0f;
}
void HideMenu()
{
如果(菜单已启用)
{
暂停=错误;
Menu.enabled=false;
Time.timeScale=1.0f;
}
}
void CheckInput()
{
if(cInput.GetKeyDown(“暂停”))
{
暂停=!暂停;
SelectedButton=按钮[SelectedButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject,新BaseEventData(eventSystem));
}
如果(暂停)
{
浮动v=cInput.GetAxis(“垂直”);
//为了尝试降低输入灵敏度,我将检查0.5,而不仅仅是0.0
如果(v>=0.5)
{
货仓();
}
else if(v按钮计数-1)
{
选择按钮索引=按钮。计数-1;
}
其他的
{
selecteButtonIndex=selecteButtonIndex+1;
}
}
//如果我们通过索引,则转到可用的第一个按钮
void GoUp()
{
如果(选择按钮索引<0)
{
选择按钮索引=0;
}
其他的
{
selecteButtonIndex=selecteButtonIndex-1;
}
}
}
我知道它是beta版的,但我想知道你是否打算实现导航,为什么你要设计成Time.timeScale=0.0f;
(暂停游戏的简单方式)不能自然地使用UI按钮导航。比我更重要的问题是什么?或者有一个简单的方法可以做到这一点,我只是不知道我需要翻转哪一位。
我也曾考虑过暂停时冻结刚体,但这似乎需要在我现有的代码库中投入大量时间,而且不会成为所有游戏对象的通用解决方案,尤其是不依赖刚体和粒子系统的碰撞器。我对解决方案持开放态度,但似乎应该有这是一个非常简单的方法。
好的,所以我解决这个问题的方法是利用
在固定的时间间隔内检查输入,并开发一个继承自MonoBehavior的抽象类。代码中是这样的:
public abstract class RealtimeMonoBehavior:MonoBehaviour
{
public float updateInterval = 0.5F;
private double lastInterval;
void Start()
{
DefaultIntervalStart();
lastInterval = Time.realtimeSinceStartup;
RealtimeIntervalStart();
}
void Update()
{
DefaultIntervalUpdate();
float timeNow = Time.realtimeSinceStartup;
if (timeNow > lastInterval + updateInterval)
{
lastInterval = timeNow;
RealtimeIntervalUpdate();
}
}
public virtual void DefaultIntervalUpdate(){}
public virtual void DefaultIntervalStart(){}
public virtual void RealtimeIntervalStart(){}
public virtual void RealtimeIntervalUpdate(){}
}
下面是我的代码在实现更改后的样子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using Extensions;
using UnityEngine.EventSystems;
public class PlayerInGameMenu : RealtimeMonoBehavior
{
public EventSystem eventSystem;
Selectable SelectedButton;
public Selectable Status;
public Selectable Settings;
public Selectable Save;
public Selectable Quit;
public float ButtonThreashold;
public bool Paused;
List<Selectable> buttons;
int selectedButtonIndex;
public PlayerMovement PlayerMovement;
public Canvas Menu;
public override void RealtimeIntervalStart()
{
base.RealtimeIntervalStart();
Menu.enabled = false;
buttons = new List<Selectable>();
buttons.Add(Status);
buttons.Add(Settings);
buttons.Add(Save);
buttons.Add(Quit);
selectedButtonIndex = 0;
SelectedButton = buttons[selectedButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject, new BaseEventData(eventSystem));
}
public override void DefaultIntervalUpdate()
{
base.DefaultIntervalUpdate();
if (cInput.GetKeyDown("Pause"))
{
Paused = !Paused;
}
}
public override void RealtimeIntervalUpdate()
{
base.RealtimeIntervalUpdate();
CheckInput();
if (Paused && !Menu.enabled)
{
ShowMenu();
}
else if (!Paused && Menu.enabled)
{
HideMenu();
}
}
void ShowMenu()
{
Paused = true;
Menu.enabled = true;
Time.timeScale = 0.0f;
}
void HideMenu()
{
if (Menu.enabled)
{
Paused = false;
Menu.enabled = false;
Time.timeScale = 1.0f;
}
}
void CheckInput()
{
if (Paused)
{
float v = Input.GetAxisRaw("Vertical");
if (v > ButtonThreashold)
{
GoUp();
}
else if (v < -ButtonThreashold)
{
GoDown();
}
SelectedButton = buttons[selectedButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject, new BaseEventData(eventSystem));
}
}
void GoDown()
{
if (selectedButtonIndex < buttons.Count - 1)
{
selectedButtonIndex = selectedButtonIndex + 1;
}
}
void GoUp()
{
if (selectedButtonIndex > 0)
{
selectedButtonIndex = selectedButtonIndex - 1;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用UnityEngine;
使用UnityEngine.UI;
使用UnityEngine.Events;
使用扩展;
使用UnityEngine.EventSystems;
公共类玩家游戏菜单:RealtimeMonoBehavior
{
公共事件系统;
可选择选择按钮;
公众可选择地位;
公共可选设置;
公共储蓄;
公众选择退出;
公共浮动按钮应为红色;
公共广播暂停;
列表按钮;
int selectedButtonIndex;
公众游戏者运动游戏者运动;
公共画布菜单;
公共覆盖无效RealtimeIntervalStart()
{
base.RealtimeIntervalStart();
Menu.enabled=false;
按钮=新列表();
按钮。添加(状态);
按钮。添加(设置);
按钮。添加(保存);
按钮。添加(退出);
selectedButtonIndex=0;
SelectedButton=按钮[selectedButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject,新BaseEventData(eventSystem));
}
公共覆盖无效DefaultIntervaluUpdate()
{
base.defaultIntervaluUpdate();
if(cInput.GetKeyDown(“暂停”))
{
暂停=!暂停;
}
}
公共覆盖无效RealTimeIntervaluUpdate()
{
base.realtimeIntervaluUpdate();
CheckInput();
如果(暂停&&!菜单。已启用)
{
ShowMenu();
}
如果(!暂停&&Menu.enabled),则为else
{
HideMenu();
}
}
void ShowMenu()
{
暂停=真;
Menu.enabled=true;
Time.timeScale=0.0f;
}
void HideMenu()
{
如果(菜单已启用)
{
暂停=错误;
Menu.enabled=false;
Time.timeScale=1.0f;
}
}
无效签入
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using Extensions;
using UnityEngine.EventSystems;
public class PlayerInGameMenu : RealtimeMonoBehavior
{
public EventSystem eventSystem;
Selectable SelectedButton;
public Selectable Status;
public Selectable Settings;
public Selectable Save;
public Selectable Quit;
public float ButtonThreashold;
public bool Paused;
List<Selectable> buttons;
int selectedButtonIndex;
public PlayerMovement PlayerMovement;
public Canvas Menu;
public override void RealtimeIntervalStart()
{
base.RealtimeIntervalStart();
Menu.enabled = false;
buttons = new List<Selectable>();
buttons.Add(Status);
buttons.Add(Settings);
buttons.Add(Save);
buttons.Add(Quit);
selectedButtonIndex = 0;
SelectedButton = buttons[selectedButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject, new BaseEventData(eventSystem));
}
public override void DefaultIntervalUpdate()
{
base.DefaultIntervalUpdate();
if (cInput.GetKeyDown("Pause"))
{
Paused = !Paused;
}
}
public override void RealtimeIntervalUpdate()
{
base.RealtimeIntervalUpdate();
CheckInput();
if (Paused && !Menu.enabled)
{
ShowMenu();
}
else if (!Paused && Menu.enabled)
{
HideMenu();
}
}
void ShowMenu()
{
Paused = true;
Menu.enabled = true;
Time.timeScale = 0.0f;
}
void HideMenu()
{
if (Menu.enabled)
{
Paused = false;
Menu.enabled = false;
Time.timeScale = 1.0f;
}
}
void CheckInput()
{
if (Paused)
{
float v = Input.GetAxisRaw("Vertical");
if (v > ButtonThreashold)
{
GoUp();
}
else if (v < -ButtonThreashold)
{
GoDown();
}
SelectedButton = buttons[selectedButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject, new BaseEventData(eventSystem));
}
}
void GoDown()
{
if (selectedButtonIndex < buttons.Count - 1)
{
selectedButtonIndex = selectedButtonIndex + 1;
}
}
void GoUp()
{
if (selectedButtonIndex > 0)
{
selectedButtonIndex = selectedButtonIndex - 1;
}
}
}
var v = Input.GetAxisRaw("JoyY1"); // Or "Vertical"
if (Math.Abs(v) > ButtonThreashold)
{
var currentlySelected = EventSystem.currentSelectedGameObject
? EventSystem.currentSelectedGameObject.GetComponent<Selectable>()
: FindObjectOfType<Selectable>();
Selectable nextToSelect = null;
if (v > ButtonThreashold)
{
nextToSelect = currentlySelected.FindSelectableOnUp();
}
else if (v < -ButtonThreashold)
{
nextToSelect = currentlySelected.FindSelectableOnDown();
}
if (nextToSelect)
{
EventSystem.SetSelectedGameObject(nextToSelect.gameObject);
}
}