05/29/24: Multiple Control Schemes


While I continue to receive feedback on the second Castle Fractal combat prototype, I've decided to start formalizing my development process, rather than just the occasional instagram picture of my computer screen. The main thing this week was a reworking of the control system, through the usage of Unity's Input System.

Input System is a far more robust... system for input than Unity's basic Input package. It allows you to create new kinds of actions instead of the basic "Move" and "Fire," and makes multiple control schemes and button remapping SO MUCH EASIER to implement.

So, why haven't I used it before?

Truth be told... I didn't know this existed until I tried to implement multiple control schemes. The basic Input package had worked for what I needed (even if my scripting was pretty inelegant due to it being my first time using it), and I was ready to use it for custom controls as well.


When I initially started working on custom controls, I had created ControlPreset and ControlManager classes, utilizing a Dictionary to map a button (e.g., "Spacebar") to an action (e.g., "Pause"). I would use a ControlManager object in the PlayerController class (the code file that handles Player stats and mechanics) to retrieve presets from a list, and copy the mappings to the player. But as I tried to figure out how to map inputs without just listening for every possible input (which is very performance unfriendly), I stumbled upon a Unity forum post discussing the Input System.

How it works

Once you download the package, you create a new Input Actions object, and double click the .inputactions file. You'll see the window above in the editor.

In addition to Control Schemes, there are three main panels to note when using the editor Input Systems:

  • Action Maps, which are a collection of actions that you can enable/disable in bulk. In the above picture you'll see the Player Map and Menus Map.
  • Actions in the selected Action Map, and the bindings for each Action. New to this system is Composite Bindings, which allow things like combination inputs such as "Shift + Left Click" for a signature move.
  • Properties of the currently selected Action/Binding, such as the path (e.g., "<Mouse>/leftButton"). The path moreso matters for scripting; the editor will simplify it by default. Abstraction, baby!

Speaking of abstraction, you can check out the details of the abstraction by selecting the .inputactions object, going to the inspector, selecting "Generate C# Class," and then hitting apply. You'll then see a C# script with the name of the .inputactions object.

At first, I ran into an issue with the code when I named the .inputactions file "PlayerActions," because there will be structs for each map called "[Map]Actions." A struct is a grouping of data that you can treat as a type. Sincestructs cannot be named the same as the file they're in, the struct for the Player Map, "PlayerActions" clashed with the name of the class. Make sure the .inputactions asset name is distinct from the map names!

Scripting

Once the C# class is created, you don't have to look too deep into it. It's good to understand some of parameters, though, as if you'll need to do some scripting with this class to make it work by creating an object from it.

(Think of a class as a blueprint, and an object as something made from the blueprint)

Before using the InputSystem, the actions the player can take had their logic handled in either the Update or FixedUpdate methods. I updated player inputs to the new system with the help of this video.

(The Update function is called by scripts every frame (a unit of time in which game logic happens The FixedUpdate method is called during Physics updates, and is where Physics objects such as Rigidbodies should have their logic updated).

To start, I initialized my PlayerInputActions object in my PlayerController script.  My goal was to put the major actions in their own methods, and have those methods activate when the player inputs their respective control bindings.

In the PlayerInputActions object, you can access a Map (the "Player" and "Menus" from before), and from there its InputActions (Move, Attack, Roll, etc.). You can then have functions subscribe to a parameter of InputActions called performed, in the OnEnable method (called the first frame the script component is activated).



From here, every time I left click on the mouse, for instance, the Input System will call the method PlayerMainAttack.

I'm currently facing a bug where Signature Moves are inaccessible, due to a limitation of Input System. According to Unity's documentation, "Actions cannot currently 'pre-empt' each other's input. Meaning that it is currently not possible to 'consume' input from one action to prevent it from triggering input on another action. A common scenario is having, for example, a binding for 'A' on one action and a binding for 'SHIFT+A' on another action. Currently, pressing 'SHIFT+A' will trigger both actions." Since Left Click is used for both the Main and Signature Attacks, it seems that the Main Attack is triggered first, causing the equipped weapon to enter an active state. This means that the PlayerSignatureAttack method will fail to actually start the signature attack.


I do have a workaround in progress utilizing coroutines to delay the Main Attack by a frame (and adjusting Weapon startup speed to compensate), which I'll discuss next update. The rest of the inputs work as they did with the old Input System, but my code is much cleaner now, will make action rebinding easier, and serves as training for future Unity projects. And I plan on reworking the ControlPreset class to hold some options that can't be expressed with the Input System (example, aim assist).

The Plan

  • Fix the Signature Move bug
  • Implement Control Switching
  • Random Room Generation
  • Game Logic (score and upgrades)
  • Implement Team Assets
  • Start Menu + Custom Controls

The Future

After some internal discussion, I made the decision to scale back Castle Fractal to what was originally known as “v0.9b" in the roadmap. This has been a major passion project of mine for the past 2.5 years, but I need to expand my portfolio beyond this one game. I don’t want to abandon the ideas I have for this game, but it is going to go on the back-burner for now as I finish up this game and work on other, much simpler projects.

Thanks for reading! I plan to update this devlog weekly with the progress I make.

Files

Caslte Fractal CP02 Play in browser
May 08, 2024
Castle Fractal CP02 Download 25 MB
May 08, 2024

Get Castle Fractal: Combat Prototype 02

Leave a comment

Log in with itch.io to leave a comment.