Character Controllers
This document's goal is to explain how custom controllers can be implemented, and made to work perfectly with FP Motion.
Last updated
This document's goal is to explain how custom controllers can be implemented, and made to work perfectly with FP Motion.
Last updated
A Character Controller is a game-object that the player uses to traverse the world. This object usually contains a movement script, together with a camera and all the objects that the player may use.
This description applies only to normal first-person games. After all, this is what we are all here for!
In FP Motion, the controller's hierarchy isn't any more complex that the ones other controllers out there have. The major difference being that this asset needs an object to hold all the camera effects.
This object will also need to have the camera game-object parented to it. Aside from this difference, the basic hierarchy (not including any weapons, or first-person objects) is simple.
Even when we take first-person objects into account and include them into the hierarchy, you won't see an enormous difference in how complicated the structure is.
The fundamental object required for that to work is a Holster game-object. This object will be parented to the camera, and will have all of the first-person objects parented to it.
Now that you know what the hierarchy of a controller that will properly work with FP Motion looks like, you are ready to get to the components each game-object needs!
There are four scripts that every controller using the asset have to have, no matter whether they are only using one effect, or all of them. These scripts are:
Normally you would place these scripts on the base player object, meaning the first object in the player's hierarchy, but we have noticed that this may lead to clutter. The way you can avoid this is to create a new game-object, parent it to the player, and adding the scripts to it.
After adding all these scripts to the correct objects, you also need to keep the controller's events up-to-date. Events like the grounding state or the velocity change require constant updating.
The way to keep these updated is to add a Character Controller Supplier script to your base player, or wherever the Character Controller component is.
If you find any problems with the Character Controller Supplier, it is possible that you are not using a Character Controller component, or are tracking the velocity and grounding state separate from it.
To fix this you can easily make a new script that inherits from Controller Data Supplier and use it to provide the correct values to events.
You can read more about creating custom Data Suppliers here!
Now that you have all the basic things working correctly, it's time to start adding the effects. We can add them to the Effects game-object we created previously and to the Holster.
The Effects object holds the effects that affect the whole player. This means that they affect both the camera and the weapons.
Meanwhile, the Holster game-object only holds the effects that target the Weapons. The reason behind this is that we want, trough adding more motion, to separate the movement of the weapons from the camera.
The Holster game-object also holds the Holster script. This component allows the player to toggle trough the weapons at run-time.
Although this component is 'hella cool', it is unnecessary.
That said, let's get to actually adding the effects!
In case you don't know exactly what effects you can add, and how to tweak them to suit your needs, you can go trough the demo scenes in the asset and check out the Motion Effects page.
Here is a brief list of the effects that you can add to these game-objects:
Offset
Bob, Roll & Strafe
Breath
Fall & Land
Lean
Sway
Shooting
Animation Addition
Once you have added all the effects your game requires, you have mostly finished setting up a new controller that work with FP Motion. You can now move on to adding Weapons, or building a cool game with the asset!
A Custom Data Supplier is a script that passes the controller-related events information on the player's movement. We limit this information to the player's velocity and grounding state.
The script with the name 'Controller Data Supplier' is just a base class for other scripts to inherit from. It contains no logic on passing information to the Event System, but it allows the scripts that inherit from it to do so easier.
Creating Controller Data Suppliers is one of the more annoying steps to set-up things in FP Motion. This has made us realize that we need to change how things work.
Moving forward FP Motion will remove its Event System and replace it with a more traditional approach for simplicity.
Now that you know what a Controller Data Supplier is, we can get to how we can write one!
First you will need to make a new script, and give it a great name like Movement Data Supplier. If you are unsure how you can do this, follow the guide here.
Now that you have your new script, you can open it in your IDE of choice. You should see an empty class with the name you just picked being its class name.
The first thing we will change inside of this script is what the class inherits from. Our class, Movement Data Supplier, is inheriting from MonoBehaviour. We can see this from the line:
We need to make sure it is instead inheriting from our supplier base class, Controlller Data Supplier. We can do this by changing MonoBehaviour to ControllerDataSupplier.
This change will require us to override two methods. These two being Init()
and Supply()
. We can go ahead and do it like this:
These two methods are necessary when passing information from some movement script to the Event System.
You can use the Init()
method to get a reference to your movement component for latter use, and the Supply()
method to pass information from it to the Event System.
This workflow will allow the Event System to be up-to-date on the controller values.
This is an excellent example of how you can make a good Data Supplier. As you can see, we make use of the pEvents
to set the values for the events. This value is equal to PlayerEvents.Instance
and is thus just a shortcut.
We then use the information from our movement component, in this case Movement Component, to update these events to the correct values.