Tutorial Soup

Untangling Unity’s New Input System

What do you get when you dive straight into game development without reading the documentation or doing any formal trainings? Why tutorial soup, of course! It tastes like an over-seasoned mess of too many ingredients. Allow me to elaborate.

Diving into Unity's New Input System

Unity's "new" Input System is a bit overwhelming when trying to just dive in head-first because it facilitates four different paradigms for propagating inputs (seen in the screenshot below). A younger, more naive, version of me thought he had a grip on the new input system. He did not.

I ended up implementing two different ways of invoking the input actions. The first person controller asset uses message-based actions, which essentially means OnMyCustomAction() methods would be invoked for every custom action defined. What I did was add a reference to the generated script to the first person controller and added event-based action triggers for my custom action. What I ended up with was confusion when I tried switching to the "UI" action map from the "Player" action map. My custom player actions were still triggering because I was mixing event-based and message-based paradigms.

Debugging Action Map Switching

A quick debug session using Rider led me to understand that my custom player events were not getting disabled when I switched action maps. It turns out that if you use that generated player controller script to process actions, you can't simply switch action maps and expect your custom actions to be disabled.

You must manually enable and disable Actions and Action Maps that are embedded in MonoBehaviour components. ~Source

Whoops! Here's my pitfall, and subsequent my eureka moment.

        public UnityEvent unityEventUse;
        public UnityEvent unityEventPause;
        public UnityEvent unityEventUnpause;

        // generated player controls
        private PlayerControls controls;

        private void Awake()
        {
            // get a reference to our main camera
            if (_mainCamera == null)
            {
                _mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
            }

            // v----- These lines use Unity Events -------v
            controls = new PlayerControls();
            controls.Player.Use.performed += context => unityEventUse.Invoke();
            controls.Player.Pause.performed += context => unityEventPause.Invoke();
            controls.UI.Unpause.performed += context => unityEventUnpause.Invoke();
        }

I got those lines from following a tutorial on the new input system without understanding that is for Unity Event-based actions. Let me show you what the first person controller asset actually uses.

my-input-settings

Whoops again! I scrolled down in their code and sure enough, I saw OnMove(), OnSprint(), OnJump(), et. al, which directly corresponded to the Action Map definitions for the first person controller. So, I removed all references to the PlayerControls script and built on what was already there. I added these methods, and like magic, it worked.

        public void OnPause(InputValue value)
        {
            pauseController.Pause();
        }

        public void OnUnpause(InputValue value)
        {
            pauseController.Resume();
        }

Understand before you code

I got into this situation from not fully understanding what I was doing while I was doing it. The tutorial may have even directed me to add those Unity Events to the stock first person controller, but that is the wrong advice. I would have known if I understood it more first. I need to be better at understanding the code I'm writing to avoid pitfalls like this from happening again.

Add a comment

Previous Post Next Post