i just learn New Input System and i found some trouble.
Here when i try press and hold " I " the input executed more than once and make my inventory UI open repeatedly… how to handle this ? i have try some ways but still not working.
void Update()
{
if (inputManager.InventoryInput)
{
if (isInventoryOpen)
{
isInventoryOpen = false;
}
else
{
isInventoryOpen = true;
}
}
Debug.Log("Inventory status" + isInventoryOpen);
}
private void FixedUpdate()
{
//When isInventoryOpen = true
if (isInventoryOpen)
{
inventoryInterface.SetActive(true);
Debug.Log("Open Inventory");
return;
}
//When All Status False
inventoryInterface.SetActive(false);
}
You will need to show us the code that actually handles the input.
this one ?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class InputManager : MonoBehaviour
{
[Header("Input Action Asset")]
[SerializeField] private InputActionAsset playerControls;
[Header("Action Map Name Preference")]
[SerializeField] private string actionMapName = "Player";
[Header("Action Name Preference")]
[SerializeField] private string move = "Move";
[SerializeField] private string run = "Run";
[SerializeField] private string croch = "Croch";
[SerializeField] private string interact = "Interact";
[SerializeField] private string map = "Map";
[SerializeField] private string inventory = "Inventory";
[SerializeField] private string questLog = "QuestLog";
[SerializeField] private string cameraChange = "CameraChange";
[SerializeField] private string pause = "Pause";
private InputAction moveAction;
private InputAction runAction;
private InputAction crochAction;
private InputAction interactAction;
private InputAction mapAction;
private InputAction inventoryAction;
private InputAction questLogAction;
private InputAction cameraChangeAction;
private InputAction pauseAction;
public Vector2 MoveInput { get; private set; }
public bool RunInput { get; private set; }
public bool CrochInput { get; private set; }
public bool InteractInput { get; private set; }
public bool MapInput { get; private set; }
public bool InventoryInput { get; private set; }
public bool QuestLogInput { get; private set; }
public float CameraChangeInput { get; private set; }
public bool PauseInput { get; private set; }
public static InputManager Instance { get; private set; }
private void Awake() {
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
moveAction = playerControls.FindActionMap(actionMapName).FindAction(move);
runAction = playerControls.FindActionMap(actionMapName).FindAction(run);
crochAction = playerControls.FindActionMap(actionMapName).FindAction(croch);
interactAction = playerControls.FindActionMap(actionMapName).FindAction(interact);
mapAction = playerControls.FindActionMap(actionMapName).FindAction(map);
inventoryAction = playerControls.FindActionMap(actionMapName).FindAction(inventory);
questLogAction = playerControls.FindActionMap(actionMapName).FindAction(questLog);
cameraChangeAction = playerControls.FindActionMap(actionMapName).FindAction(cameraChange);
pauseAction = playerControls.FindActionMap(actionMapName).FindAction(pause);
RegisterInputAction();
}
void RegisterInputAction()
{
moveAction.performed += context => MoveInput = context.ReadValue<Vector2>();
moveAction.canceled += context => MoveInput = Vector2.zero;
runAction.performed += context => RunInput = true;
runAction.canceled += context => RunInput = false;
crochAction.performed += context => CrochInput = true;
crochAction.canceled += context => CrochInput = false;
interactAction.performed += context => InteractInput = true;
interactAction.canceled += context => InteractInput = false;
mapAction.performed += context => MapInput = true;
mapAction.canceled += context => MapInput = false;
inventoryAction.performed += context => InventoryInput = true;
inventoryAction.canceled += context => InventoryInput = false;
questLogAction.performed += context => QuestLogInput = true;
questLogAction.canceled += context => QuestLogInput = false;
cameraChangeAction.performed += context => CameraChangeInput = context.ReadValue<float>();
cameraChangeAction.canceled += context => CameraChangeInput = context.ReadValue<float>();
pauseAction.performed += context => PauseInput = true;
pauseAction.canceled += context => PauseInput = false;
}
private void OnEnable() {
moveAction.Enable();
runAction.Enable();
crochAction.Enable();
interactAction.Enable();
mapAction.Enable();
inventoryAction.Enable();
questLogAction.Enable();
cameraChangeAction.Enable();
pauseAction.Enable();
}
private void OnDisable() {
moveAction.Disable();
runAction.Disable();
crochAction.Disable();
interactAction.Disable();
mapAction.Disable();
inventoryAction.Disable();
questLogAction.Disable();
cameraChangeAction.Disable();
pauseAction.Disable();
}
}
InputActions have a .WasPressedThisFrame()
method: Class InputAction | Input System | 1.10.0
You can perhaps have boolean properties to expose this method, or just expose the InputAction’s for simplicity.
im sorry, where should i put that method ?
i put it on my if-else statment and it became error, i try put it on my input handler then it also error
mind if i get some example ?
Thanks
I’m saying expose a way to check for that in your InputManager
class.
Such as just having a property in it:
public bool InventoryInputWasPressedThisFrame => inventoryAction?.WasPressedThisFrame() ?? false;
You’ve already got a central place for inputs. You can just add more functionality as needed.
1 Like
oh i see… thanks, i got it now
1 Like
Your performed/cancelled callbacks all just turn Booleans true/false, so it is clear that the Booleans like InputManager.InventoryInput will remain true while the button is held down. Using booleans and if/else for one-off actions is not really a good idea because of that. Instead, either directly hook up new callbacks to performed
and/or cancelled
for button actions that must be one-offs from a button press, or have the InputManager provide public events like public event Action InventoryPressed;
as proxies for the buttons being pressed or released. These created events can be registered to trigger once with private void PressInventory(InputAction.CallbackContext ctx) => InventoryPressed?.Invoke();
and inventoryAction.performed += PressInventory;
in Awake or Start in InputManager (and unsubscribe in OnDestroy). Code that needs to do something based on the inventory button being pressed would then be subscribed to in Awake/Start, like inputManager.InventoryPressed += ToggleInventory;
(unsubscribe in OnDestroy). In this case, judging by the code, you could most easily write this:
private void ToggleInventory()
{
isInventoryOpen ^= true;
// if you wanted to, you could also set the active state of the inventory display here
// inventoryInterface.SetActive(isInventoryOpen);
}
1 Like
Look simple, i will try this to, thanks for your suggestions