Forum rules - please read before posting.

Auto Detecting Mouse and/or Controller Input

I've scoured the search results from the forum regarding switching between mouse and controller input depending on whether the player moves or clicks the mouse, or presses a button on a controller.

Am I correct in assuming that the best way forward would be to create an Active Input that would switch to the appropriate input?

If so then I'm at a loss on how to switch the input types over as there doesn't seem to be the appropriate action to do this in the actionlists.

I'm useless with the coding side of this so am relying on actionlists. This is the last step I need to complete before releasing my project so it's rather frustrating that I can't seem to do this on my own :(

Comments

  • This script, placed on a GameObject in your scene, should switch the Settings Manager's "Input method" based on the last event type:

    using AC;
    using System.Collections;
    using UnityEngine;
    
    public class DetectInputMethod : MonoBehaviour
    {
    
        private void OnGUI ()
        {
            Event currentEvent = Event.current;
            if (currentEvent != null)
            {
                if (currentEvent.isMouse)
                {
                    SetInputMethod (InputMethod.MouseAndKeyboard);
                }
                else
                {
                    SetInputMethod (InputMethod.KeyboardOrController);
                }
            }
        }
    
        private void SetInputMethod(InputMethod inputMethod)
        {
            if (KickStarter.settingsManager.inputMethod != inputMethod)
            {
                KickStarter.settingsManager.inputMethod = inputMethod;
                // Plus anything else you may want/need to do when changing input
            }
        }
    }
    
  • Thanks Chris!

    I'll try this very soon. I presume I need to add this to every scene to allow the player to switch whenever, should they wish to?

    Also, I've noticed that in Keyboard and Mouse mode, the 'auto select first element' still has the first element selected. Is there a way around this to only select the first element if a controller is in use?

  • I presume I need to add this to every scene to allow the player to switch whenever, should they wish to?

    You can attach it to your PersistentEngine prefab to have it be present in every scene.

    Is there a way around this to only select the first element if a controller is in use?

    You can modify the above script's SetInputMethod to make any other desired changes at the time of the input change:

    private void SetInputMethod(InputMethod inputMethod)
    {
        if (KickStarter.settingsManager.inputMethod != inputMethod)
        {
            KickStarter.settingsManager.inputMethod = inputMethod;
    
            foreach (Menu menu in PlayerMenus.GetMenus ())
            {
                menu.autoSelectFirstVisibleElement = (inputMethod == InputMethod.KeyboardOrController);
            }
        }
    }
    
  • Thanks Chris, but I'm greeted with the game cursor locked in the centre of the screen now. The system cursor works and I can click with that but the buttons don't 'highlight' as they did before...

    Am I missing something?

  • What's the state of your Lock cursor in screen's centre when game begins? setting?

    Before using the script, be sure to work out exactly which settings / properties etc give you the intended behaviour for your two input modes. That is, get the two working separately, before relying on a script to mix them together.

    Then, we can see if the script needs modifying to also incorporate those other settings.

    The other thing to bear in mind is that changing Manager fields through script will affect their edit-mode values - they won't revert back to their original state after exiting Play mode. It's likely that the script will also need to be amended to set the affected settings to default values when the game begins.

    The code itself won't be complex - but we will first need to determine exactly which settings to affect.

  • Good morning, Chris!

    The Lock Cursor in Screen's Centre When Game Begins is unchecked. Checking it makes no difference.

    Mouse/Keyboard works flawlessly when all 'navigate menus directly' are deselected and Mouse/Keyboard is chosen as the input method in the Settings.

    The controller works fine as it should when Controller/Keyboard is selected in the settings and all the 'navigate menus directly' boxes are selected in the Menu settings (Although the Pause menu won't auto-highlight the first element when in controller mode, for some reason - all other menus (Conversation and Inventory) highlight fine).

    It may be worth noting that this is an FMV game so is making heavy use of the Conversation menu as the navigation/choices system behind it all, so gameplay is resuming in the background while this menu is active.

    All menus are Unity-based.

    I hope this clears somethings up.

  • edited January 2021

    You can get an API reference to access any Manager field by right-clicking the field's label.

    So if you want to e.g. update the "Directly navigate Menus when paused?" setting, you can get the API reference to it and incorporate it into your script.

    Here's an updated example script that does that, and also sets default values:

    using AC;
    using System.Collections;
    using UnityEngine;
    
    public class DetectInputMethod : MonoBehaviour
    {
    
        public InputMethod defaultInputMethod;
    
        private void Start ()
        {
            SetInputMethod (defaultInputMethod);
        }
    
        private void OnGUI ()
        {
            Event currentEvent = Event.current;
            if (currentEvent != null)
            {
                if (currentEvent.isMouse)
                {
                    SetInputMethod (InputMethod.MouseAndKeyboard);
                }
                else
                {
                    SetInputMethod (InputMethod.KeyboardOrController);
                }
            }
        }
    
        private void SetInputMethod (InputMethod inputMethod)
        {
            if (KickStarter.settingsManager.inputMethod != inputMethod)
            {
                KickStarter.settingsManager.inputMethod = inputMethod;
    
                bool directMenuControl = (inputMethod == InputMethod.KeyboardOrController);
    
                KickStarter.menuManager.keyboardControlWhenPaused = directMenuControl;
                KickStarter.menuManager.keyboardControlWhenDialogOptions = directMenuControl;
                KickStarter.menuManager.keyboardControlWhenCutscene = directMenuControl;
    
                foreach (Menu menu in PlayerMenus.GetMenus ())
                {
                    menu.autoSelectFirstVisibleElement = directMenuControl;
                }
            }
        }
    
    }
    
  • Chris, thank you SO much for your time and effort, it is most sincerely appreciated!

    I fixed the auto-select first element issue so that's sorted.

    The only issue I seem to be having is that it works fine apart from when it diverts to mouse control there's no cursor until I click, then it vanaished immediately. Also, any elements that react by hovering, such as menus and choices in the conversations, only highlight once clicked, with no further execution after that, so basically I can't make anything actually do anything to progress when using the mouse.

  • What is your AC version, and how do the various Manager fields we're dealing with appear when the issue occurs, vs when you're using Mouse And Keyboard input normally with no scripting?

    What is your Cursor rendering mode set to?

    Are your Menus rendered with Unity UI, and - if so - are you using a custom EventSystem prefab?

  • I'm using AC 1.72.3.

    Here's my cursor setup. Switching the hardware doesn't seem to make any difference.

    My menus are Unity UI. I have no custom EventSystem prefab applied in the menu manager.

    I've noticed that the menu manager for the menus has the 3 'Directly Navigate Menus' ticked when I try to use the mouse - it's not unchecking them. The rest of the menu remains unchanged.

    Using the script you sent also instantly switches control over to the gamepad, even if Mouse & keyboard is selected in the Settings.

  • I've noticed that the menu manager for the menus has the 3 'Directly Navigate Menus' ticked when I try to use the mouse - it's not unchecking them.

    It should be. Try removing the following line from the script:

    if (KickStarter.settingsManager.inputMethod != inputMethod)
    

    Using the script you sent also instantly switches control over to the gamepad, even if Mouse & keyboard is selected in the Settings.

    As intended - it sets default values based on the value in the Inspector, but you can prevent this by removing the Start function.

    when it diverts to mouse control there's no cursor until I click, then it vanaished immediately

    If this remains after the above changes, can you elaborate on this? Does it remain invisible indefinitely?

  • Removing that line seems to have changed nothing at all. The 3 'Directly Navigate Menus' get checked and the mouse is still acting the same. Once the mouse uis moved or clicked the 2 Directly Navigate Menus still stay checked.

  • edited January 2021

    It's likely due to an oversensitivity of the event checking.

    The script works by evaluating Event.current, and adapting the input method to suit.

    What you'll want to do is limit the types of events that can cause a change. Try this:

    using AC;
    using System.Collections;
    using UnityEngine;
    
    public class DetectInputMethod : MonoBehaviour
    {
    
        public InputMethod defaultInputMethod;
    
        private void Start ()
        {
            //SetInputMethod (defaultInputMethod);
        }
    
        private void OnGUI ()
        {
            Event currentEvent = Event.current;
            if (currentEvent != null)
            {
                switch (currentEvent.type)
                {
                    case EventType.Repaint:
                    case EventType.Layout:
                        return;
    
                    default:
                        break;
                }
    
                if (currentEvent.keyCode == KeyCode.Escape)
                {
                    return;
                }
    
                if (currentEvent.isMouse)
                {
                    Debug.Log ("Switch to mouse input. Event type: " + currentEvent.type);
                    SetInputMethod (InputMethod.MouseAndKeyboard);
                }
                else
                {
                    if (currentEvent.keyCode == KeyCode.None) return;
    
                    Debug.Log ("Switch to mouse input. Event type: " + currentEvent.type + ", Keycode: " + currentEvent.keyCode);
                    SetInputMethod (InputMethod.KeyboardOrController);
                }
            }
        }
    
        private void SetInputMethod (InputMethod inputMethod)
        {
            if (KickStarter.settingsManager.inputMethod != inputMethod)
            {
                KickStarter.settingsManager.inputMethod = inputMethod;
    
                bool directMenuControl = (inputMethod == InputMethod.KeyboardOrController);
    
                KickStarter.menuManager.keyboardControlWhenPaused = directMenuControl;
                KickStarter.menuManager.keyboardControlWhenDialogOptions = directMenuControl;
                KickStarter.menuManager.keyboardControlWhenCutscene = directMenuControl;
    
                foreach (Menu menu in PlayerMenus.GetMenus ())
                {
                    menu.autoSelectFirstVisibleElement = directMenuControl;
                }
            }
        }
    
    }
    

    That should reduce the events that have an effect, and the Console will report on what does cause a change.

    Bear in mind that there may be further times when a change is unwanted - e.g. pressing Escape to bring up the pause menu. The above will check for that specifically, but it may be better to only switch to Keyboard Or Controller if only keys from a pre-defined set are pressed instead.

  • Chris, this is ALMOST working now, I can't thank you enough!

    Now, it starts on controller by default and that's fine, it all works beautifully. However, once clicking the mouse button it DOES work, but the first choice in the conversations are still highlighted by default.

    Also, going back to controller again doesn't seem to fully work and nothing on any of the menus is highlighted when pressing a controller button.

    I can't thank you enough for your time in working this out with me!

  • Now, it starts on controller by default and that's fine

    It shouldn't be doing anything by default - if you want to ensure it uses a controller by default, uncomment the line in the Start function, and set the Inspector field to Keyboard And Controller.

    but the first choice in the conversations are still highlighted by default.

    Check your Console for the logs I mentioned - is it in Mouse And Keyboard mode before your Conversation menu appears?

    The script only affects the Auto-select first visible element? property in your Menus. Does your Conversation menu instead supply a specific element to select?

    going back to controller again doesn't seem to fully work and nothing on any of the menus is highlighted when pressing a controller button.

    Aside from the per-Menu properties, is there any difference in your Managers (Menu / Settings) when keyboard control is working without the script, vs not working with the script?

    Check the Console at this point, too - is it inadvertently switching to Mouse And Keyboard?

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.