繁体   English   中英

使用Input.GetAxis来导航新UI的Unity3d交互式暂停菜单

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM