[英]Unity3d Interactive pause menu that has uses Input.GetAxis to Navigate the new UI
好的,所以我试图创建一个交互式暂停菜单,该菜单可以使用Unity 4.6的新UI访问Input.GetAxis。
只要为可选元素(在我的示例中为一系列按钮)设置了导航关系,并且将Interactable
设置为true,则UI可以正常工作,但是当我设置Time.timeScale = 0.0f;
则键盘输入导航将不再起作用。 但是,鼠标输入的点击和动画仍然可以按预期工作。
我已经尝试了几种解决时间刻度问题的方法,到目前为止,到目前为止,最好的方法是检查MonoBehavor
基础对象的Update
消息主体中从Input.GetAxis()
返回的值。 这多少有些用,但是我的结果是Button所选集合的最顶部或最底部。 我认为这是因为update被调用的次数比FixedUpdate
并且如果我的控制台打印出更多的对选择上下移动的方法的调用,这将是有意义的。 因此,我正在考虑其“办公空间”类型错误之一,以小数点后一位或有点愚蠢的方式出现,但我似乎看不到它。 否则,我认为我的解决方案将是一个相当可行的解决方案。
以下是我的Unity安装程序的图像,其中包含Unity 4.6中提到的游戏对象,后面是我的代码。
public class PlayerInGameMenu : MonoBehaviour
{
public EventSystem eventSystem;
Selectable SelectedButton;
public Selectable Status;
public Selectable Settings;
public Selectable Save;
public Selectable Quit;
public bool Paused;
List<Selectable> buttons;
int selecteButtonIndex = 0;
public Canvas Menu;
void Start()
{
Menu.enabled = false;
buttons = new List<Selectable>();
buttons.Add(Status);
buttons.Add(Settings);
buttons.Add(Save);
buttons.Add(Quit);
SelectedButton = buttons[0];
}
void Update()
{
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 (cInput.GetKeyDown("Pause"))
{
Paused = !Paused;
SelectedButton = buttons[selecteButtonIndex];
eventSystem.SetSelectedGameObject(SelectedButton.gameObject, new BaseEventData(eventSystem));
}
if (Paused)
{
float v = cInput.GetAxis("Vertical");
//to attempt to cut down on the input sensitity I am checking 0.5 instead of just 0.0
if (v >= 0.5)
{
GoDown();
}
else if (v <= -0.5)
{
GoUp();
}
}
}
void GoDown()
{
//go to the last button available if we go past the index
if (selecteButtonIndex > buttons.Count - 1)
{
selecteButtonIndex = buttons.Count - 1;
}
else
{
selecteButtonIndex = selecteButtonIndex + 1;
}
}
//go to the first button available if we go past the index
void GoUp()
{
if (selecteButtonIndex < 0)
{
selecteButtonIndex = 0;
}
else
{
selecteButtonIndex = selecteButtonIndex - 1;
}
}
}
我在beta中知道它,但是我想知道您是否要实现导航,为什么要以Time.timeScale=0.0f;
这样的方式设计它呢Time.timeScale=0.0f;
(暂停游戏的简单方法)自然无法与UI按钮导航一起使用。 比我更大的头脑问题? 或者有一种简单的方法可以做到,而我只是不知道需要翻转什么。
我还考虑过仅在暂停时冻结刚体,但这似乎需要花费大量时间在我现有的代码库上,并且不会成为所有游戏对象(尤其是不依赖于刚体和粒子系统的对撞机)的通用解决方案。 我对解决方案持开放态度,但似乎应该有一种非常简单的方法来做到这一点。
这就像一个魅力:
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);
}
}
好的,我对这个问题的解决方案是利用Time.realtimeSinceStartup
来检查固定间隔的输入,并开发一个继承自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;
}
}
}
向imapler点头, Input.GetAxisRaw对于检查输入感觉更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.