Unity noob trying to architect a character that takes input from input system or an AI "brain"

Hey, I’m trying to write a character controller that can be controlled either by a player using the input system or what I will just call an “AI Brain” component and I am having trouble trying to decide what goes where, and how to make my scripts follow the SOLID principals of coding. I have a list of concerns and a rough draft so far but I would really like to hear from somebody with more experience to help me clean up my act. My hope with this post is to come up with clearly defined jobs for my scripts, and a cleaner way to abstract my input from the character components, as if I change anything about input in one script, I have to change it in four others.

I’ll start by sharing my current draft:

This is what it looks like right now. Labeled elements are as follows:

  • Is an object which houses an input singleton. It houses input actions and exposes variables that represent the values of the input actions. For example, a button input like Fire1 (left click) has a publicly accessible boolean that says if the button is down on the current frame.
  • Is the root of the player, it houses all the logic for the character.
  • Is the character’s “brain” and it uses an IEntityInput interface. There are currently two types. For any input action exposed in the singleton, an IEntityInput interface has an identical variable. In the Player version of the brain, it just exposes the value of the variable from the singleton to the components with a getter. The AI version of the brain has a simple state machine that manipulates the variables like “Fire1” or “InputDirection” based on the states. This is where I have the most trouble.
  • A simple state machine that kinda does nothing for now, but like if it is in the main state then the character can move and act normally, but if it goes to the dead state then the player can no longer move or shoot. In the future this is where I would put a status effect like stunned or slowed.
  • Inventory controls tools the character can hold and it has caused me a lot of headache with respect to handling inputs. I actually broke it just prior to this screenshot because I can’t figure out how I want to handle binding the “Use” function of an item to an input based on the slot that something goes in. Especially if say, I have a slot for the main hand, and maybe a specific tool has a special ability that has an additional binding beyond just using Fire1. Maybe I am overengineering this too early?
  • A simple recreation of the locomotion behavior from Blockland (which is largely similar to quake, who knew?).

Was that confusing? I am confused too. I don’t know what I am doing and I feel like input handling has bled out into too many components. I want to simply expose the input actions themselves in the singleton, but if I do that, then I can’t make the AI brain work because I can’t make fake input actions for the ai state machine to control. Examples of scalable input system usages that I have found online seem to be a bit too advanced, like the FPS Sample, or they are too simple to answer my concerns. My long-term goal here is to make something like the bots in TF2. They are designed for players first, but then I can make a simple AI control a character that works just like a player in every other way.

Did my question make sense? This is kinda broad. I don’t quite know what I am asking because I don’t know what I need. Big thanks to anyone who made it this far.

Think you should make the “input system” invisible for the character.
You can make a component that houses all of the controlling values, and make the character’s components read ONLY from that component. Let’s call it “controller”.
Then you make a InputSystem handler and a AI handler that write to that “controller”.
For the inventory, I think the items that you are holding should share a universal templet which handles however the character wants to interact with it. And the character itself should know what kind of item it’s interacting with.

Alright, I’ll give that a shot. I have already started working on your suggestion as of writing this and I have hidden the input from the character. It has cleaned up a lot of my code. Now I am working on coming up with a universal template for items. Thanks for the ideas!

1 Like

I got around to defining the basics of an item better like you suggested. I made some scriptable objects I’m calling Equip Regions that that come with input bindings like Mainhand goes with fire1 and Offhand goes with fire2, and I assign them to items to manage what things can be equipped and to keep inputs straight. It is working pretty well so far. Much cleaner than what I had before.

1 Like

I can share you what I did for my game - it’s a completely different kind of game, but at an abstract level this is what I did.

For AI - I’d have an “AISequence” which is a list of “PlayerAI” instances, each with it’s own configuration. Broke it down to a very basic level. Within a “PlayerAI” there is a series of “MovementAIs” (controlling movement) and “ItemAIs” controlling their use of an item (whatever is equipped). The actions are very simple. MoveStraightVector, PointTowardsNearest, MoveCircle, EvokeItemConstantly… etc

Multiple AI steps made up a single AI which generally represents a single action. The AISequence would then have state machine logic to determine which action to perform.

My experience, coding more complex scenarios involves breaking things down into very simple components and complex properties emerge from the combination of many single simple functions.

Thanks,
Bkeegan

1 Like