C# Unity3d交互式暂停菜单,使用Input.GetAxis导航新UI

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(

好的,我正在尝试创建一个交互式暂停菜单,它可以使用Unity 4.6的新UI访问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);
        }
    }