0% found this document useful (0 votes)
45 views61 pages

Character Movement Fundamentals

Uploaded by

Edge-Tec
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views61 pages

Character Movement Fundamentals

Uploaded by

Edge-Tec
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

Character Movement Fundamentals

Rigidbody-based Character Movement

User Manual
Version 2.2
March 31, 2021

© Jan Ott, 2021


Quickstart
Example Scenes
Mutiple example scenes are included in this package to showcase the controller’s abilities and possible
applications.

Fig. 1 Folder location of example scenes in the package.

Showcase
’ShowcaseScene’ is meant to demonstrate how the controller moves on different terrains, slopes and
stairs as well as to showcase some interesting gameplay possibilities using special level elements (moving
platforms, switching gravity).
It also allows you to switch between different controller prefabs (first person prefab, multiple third
person prefabs).

Fig. 2 Showcase scene.

1
’TopDownScene’ offers a similar experience, but with a focus on gameplay from a top down perspective.

Fig. 3 Topdown scene.

Special

’ClickToMoveScene’ is a very simple example of a top-down controller with ’click-to-move’ mouse


controls: Simply click anywhere on the screen and the controller will go toward the chosen position.

Fig. 4 Click to Move scene.

2
’ExternalCameraScene’ provides an example of a possible camera setup where the character and the
camera are two separate gameobjects.
Although the camera is continuously rotating around a fixed axis, the character will always move in
relation to the current camera view.

Fig. 5 External camera scene.

’PlanetWalkerScene’ demonstrates a simple setup of a ”planetary” gravity environment: In this scene,


the controller is continually aligned to the center of a sphere, allowing it to run around the surface of
the sphere.

Fig. 6 Planet walker scene.

3
Just open the scenes, press play and you’re ready to go! Player controls are explained in the scenes
using UI elements or text meshes.

Prefabs
This package also comes with 16 fully functional controller prefabs, which can be found in the ’Con-
troller Prefabs’ folder. They are organized into ’animated’, ’blank’ and ’simplified’ prefabs.

Fig. 7 Folder location of prefabs in the package.

Blank controller prefabs are purposely put together using only components that are absolutely nec-
essary for the controller to function. They are meant to be a ’blank slate’ or base from which start
from.
Animated controllers come with basic animation (and sound) already set up and serve as an example
on how to link animations and sound cues (like footsteps) with the controller’s movement.
Alternatively, they are also very well suited for quick prototyping.
Simplified controllers use a stripped down, simplified controller script and can serve as an easy intro-
duction for anyone new to character movement scripting.
You can use these prefabs by simply dragging them into an empty scene - no further setup is required.
All controller prefabs come with their own cameras, so make sure to delete any unused cameras in the
scene afterwards.

4
Fig. 8 Select a controller prefab ...

Fig. 9 ... simply drag it into into an empty scene ...

5
Fig. 10 ... and delete the old camera.
Contents
1 Introduction 1

2 About this Package 1


2.1 What Is This? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.2 What Kind of Games Can I Use This For? . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.3 List of Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

3 Package Structure 6

4 Basic Principles 9
4.1 ’Anatomy’ of a Basic Character Controller . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.2 Three Ways to Use this Package in your Projects . . . . . . . . . . . . . . . . . . . . . . 10

5 Overview Over All Included Controller Prefabs 11


5.1 ’Animated’ and ’Blank’ Controller Prefabs . . . . . . . . . . . . . . . . . . . . . . . . . . 11
5.2 ’Simple’ Controller Prefabs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

6 Component Descriptions 17
6.1 Mover . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
6.1.1 Ceiling Detector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
6.2 Controllers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
6.3 Character Input Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.4 Camera Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6.5 Camera Input Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
6.6 Smoothing and Other Visual Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
6.7 Animation and Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.8 Environment Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.9 UI Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

7 Implementing Custom Input 36


7.1 How the Input Scripts Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.1.1 Character Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.1.2 Camera Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7.2 Writing a Custom Character Input Script . . . . . . . . . . . . . . . . . . . . . . . . . . 36

8 Writing a Custom Controller Script 39


8.1 Basic Script Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
8.2 A Basic Controller Code Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
8.3 Extending the Abstract Base ’Controller’ Class . . . . . . . . . . . . . . . . . . . . . . . 44
8.4 Detecting Ceilings Collisions with the ’CeilingDetector’ Component . . . . . . . . . . . . 44
8.5 Moving a Controller Relative to the Camera’s View . . . . . . . . . . . . . . . . . . . . . 46

9 Writing External Scripts 48


9.1 A Quick Note Regarding Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

7
9.2 Adding Forces to a Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
9.3 Rotating the Camera Toward a Target Direction or an Object in the Scene . . . . . . . 49
9.4 Changing Collider Dimensions at Runtime . . . . . . . . . . . . . . . . . . . . . . . . . . 50

10 How to Connect Animations and Audio to Character Movement 51


10.1 Getter Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
10.2 Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1 Introduction
Thank you for your interest in this package! I’m sure it will serve you well and help you realize your
game ideas in Unity!
In case you run into any problems or if you need any help with something related to this package, feel
free to contact me at [email protected].
The same goes for any feedback or thoughts you might have on this package, of course! I’d love to
hear your ideas!
(Note: Please keep the invoice number you received as part of your purchase at hand when requesting
support via email! Thanks!)

2 About this Package


2.1 What Is This?

Fig. 11 Smoothly moving over stairs, slopes and terrain.

’Character Movement Fundamentals’ is a rigidbody-based character movement system.


Put simply, it is a collection of scripts, components and prefabs that will help you quickly set up
characters that can move around and react to a game environment in a physically believable way.
It’s both easy to understand and easy to adapt to your game’s specific needs, either by modifying the
scripts in this package or even writing your own.
I specifically didn’t design this package to be a hyper complex, highly specialized system, that will
only ever work for one specific type of game.
Instead, my main goal is to provide a stable, versatile and robust starting point for anyone developing
games in Unity.
Writing your own character movement system takes a lot of time and effort, with lots of pitfalls along
the way.
To make matters worse, character controllers, though vitally important for smooth gameplay in most
games, are only ever noticed by players when things go wrong: Stuttering, falling through level geom-
etry, coming to a complete stop at tiny obstacles...

1
Fig. 12 Falling, jumping and stopping at walls.

I want to help other developers avoid these common pitfalls altogether and that’s exactly why I created
this package.
To make things as easy as possible for you, this package comes with example scenes, lots of fully set
up controller prefabs and fully documented scripts to help you understand what’s going on behind the
scenes. Even if you don’t intend to write any code, you’ll still be able to create controllers for almost
all types of games just by modifying values in the inspector - all of the components are designed to be
as versatile as possible.

2.2 What Kind of Games Can I Use This For?


Put very simply, if your game needs characters moving around in a 3D (or 2D) environment, maybe
even walking up stairs and slopes, this package is right for you!
It doesn’t matter if you’re planning to develop a fast-paced shooter (such as ’Doom’, ’Team Fortress’,
’Fortnite’ ), an atmospheric adventure game (’Dark Souls’, ’Spyro the Dragon’ ) or even a retro 2D
platformer - with just a few easy adjustments, ’Character Movement Fundamentals’ is capable of
handling all of that and more.
Thanks to the highly versatile camera system included in this package, experimenting with different
camera perspectives is very easy - whether your game needs a first person, third person, 2D sidescroller
or a top-down perspective, everything is easy to configure by changing a few values in the Unity
inspector.

2
(a) First person view.

(b) Third person view.

(c) A topdown game.

Fig. 13 Some examples of different camera perspectives and gameplay styles.

2.3 List of Features


• Versatile, highly customizable character controller system
 Based on Unity’s built-in rigidbody physics.
 Walks up and down stairs, slopes and ramps without losing ground contact.
 Can slide down slopes that are too steep, acceptable steepness can be adjusted.
 Adjustable movement speed, jump speed, custom gravity, air control [...]
 Character controller can be freely rotated, even at runtime. This enables interesting game-
play possibilities - walking on ceilings and walls, on miniature planets, inside loops...
 3 different ground detection methods to achieve great performance on every system/device.

3
• All-purpose camera system
 Highly customizable, can be adapted to work in a wide variety of games.
 Built-in camera smoothing system for smooth camera rotations.
 Adjustable camera angle limits.
 Invertible camera axes.
 Different sensitivity settings for gamepad and mouse input.
• Five example scenes to showcase the various features of the package.
• A set of 16 ready-to-use controller prefabs that can be ’drag and dropped’ into any scene -
no further setup required.
 A first person camera walker prefab.
 A top-down walker prefab.
 A 2D sidescroller prefab.
 Three different third person camera walker prefabs.
 A top-down, ’click-to-move’ walker prefab.
 All prefabs come in two versions: One version with animations and sound already set up
and a blank version, for easier customizing.
 Two ’simplified’ controller prefabs.
• A collection of environment assets, which can be used for quick prototyping.

 Basic environment building blocks (cubes, ramps, stairs, tiles), all textured and set up with
materials.
 A simple moving platform system.

Fig. 14 Some of the included environment building blocks...

4
Fig. 15 ...and a simple level made using these building blocks.

• Rigged and animated low poly character model.


 Low poly character, ideal for quick prototyping.
 Fully textured.
 Full set of animations for walking, idling, jumping, strafing...

Fig. 16 The included rigged and animated character, ’Capguy’.

5
3 Package Structure
The package is structured as follows:

Character Movement Fundamentals


Manual.pdf
ReadMe.txt
Example Scenes
Prefabs
Source

To keep everything organized, all package assets are contained in one root folder (’Character Movement
Fundamentals’). This ensures that your project files stay separated from the package’s files if the
package is imported into an existing Unity project.
On the top layer, you’ll also find a copy of this user manual and a readme file that keeps track of all
changes between different versions of this package.

Example Scenes
This folder contains all example scenes in the package, split into three ’showcase’ scenes to demonstrate
the package’s capabilities and three ’special’ scenes for less common level setups.

Example Scenes
Showcase
EmptyShowcaseScene.unity
ShowcaseScene.unity
TopdownScene.unity
Special
ClickToMoveScene.unity
ExternalCameraScene.unity
PlanetWalkerScene.unity

Source
All meshes, animations, sounds files, materials, textures and scripts can be found in this folder.

Source
Capguy
Meshes, animations, textures and materials for
the capguy character model
[...]
Environment
Meshes, animations, textures and materials for
all environment assets
[...]
Scripts
Sounds
Misc

6
All assets are organized by their use - files related to the environment assets are separated from the
files used by the Capguy character (a low-poly, rigged and animated character model).
This makes it a lot easier to delete unneeded parts of the package - if you find no use for the Capguy
character, you can safely delete its folder to reduce the overall package size.
Apart from that, ’Scripts’ contains all scripts, all sound files are located in ’Sounds’ and ’Misc’ contains
miscellaneous files like fonts, shaders and physics materials.

Prefabs
In this folder, you’ll find all the prefabs included in this package.

Prefabs
Controller
Animated
ClickToMoveWalker Animated.prefab
FirstPersonWalker Audio.prefab
SideScroller Animated.prefab
ThirdPersonWalker A Animated.prefab
ThirdPersonWalker B Animated.prefab
ThirdPersonWalker C Animated.prefab
TopDownWalker Animated.prefab
Blank
ClickToMoveWalker.prefab
FirstPersonWalker.prefab
SideScroller.prefab
ThirdPersonWalker A.prefab
ThirdPersonWalker B.prefab
ThirdPersonWalker C.prefab
TopDownWalker.prefab
Simplified
SimpleFirstPersonWalker.prefab
SimpleThirdPersonWalker.prefab
Environment
Interactive
GravityFlipper.prefab
GravityTunnel.prefab
MovingPlatform.prefab
Static
A collection of basic level building blocks
(ramps, tiles, walls...)
[...]

As already mentioned, most of the controller prefabs come in two versions -’blank’ and ’animated’.
Blank controller prefabs are purposely put together using only components that are absolutely neces-
sary for the controller to function. They are meant to be a ”blank slate” or base for more advanced
controllers.
Animated controllers come with basic animation (and sound) already set up and serve as an example
on how to link animations and sound cues (like footsteps) with the controller’s movement.

7
Simplified controllers use a stripped down, simplified controller script and are a great starting point
for anyone new to character movement scripting.
All environment prefabs are split into ’interactive’ and ’static’. Generally speaking, all interactive
environment assets are used in the example scenes for demonstration purposes. The static environment
assets are composed of modular level building blocks and are used in all example scenes. They are also
very useful for quick prototyping of game environments.
More detailed descriptions of each controller prefab can be found in chapter 5, ’Overview Over All
Included Controller Prefabs’.

8
4 Basic Principles
4.1 ’Anatomy’ of a Basic Character Controller
Mover and Controller
All character controllers in this package follow the same basic idea: The task of moving a character
around the scene is split between two components, a ’Mover’ and a ’Controller’.
On its own, the Mover component won’t do anything. Instead, it expects a movement velocity (and
direction) from another script, which we’ll refer to as a ’Controller’ from now on.
After having received a movement velocity, the Mover component will then set the rigidbody’s velocity
appropriately, make sure that the character maintains the correct distance from the ground and stores
any useful collision information (whether the character is grounded, for example).
In the following frame, the Controller will use that information to determine the new movement vector,
pass that vector to the Mover and the cycle repeats.
Or put differently, you can think of the Mover as the body of the character and the Controller as the
brain. One makes the decisions, the other one carries them out.
This setup makes it possible for all characters in a game to use the same basic Mover component. By
choosing different Controllers, we then can implement all kinds of different movement patterns and
behaviours. We could even switch controllers during gameplay!

Object Hierarchy
When it comes to gameobject hierarchy, all character controllers in this package are structured very
similarly. The Mover and Controller components are added to the root gameobject of the hierarchy,
any other parts (like the camera system and the character model) are added as children to that root
gameobject.

Root gameobject (rigidbody, collider, mover, controller)


Model root
Mesh, material, animations, [...]
Camera root
Camera scripts, camera, [...]

Usually, the character mesh/model/animations and the camera system are split into two different child
hierarchies, both for practical and organizational reasons. For example, many third person games will
have the camera fall slightly behind the character model, for a smoother gameplay experience. This
effect is easily achievable by using this design.

Fig. 17 An example of a typical character controller hierarchy in the package.

In special cases, empty gameobjects may be inserted between the different root gameobjects to prevent
certain scripts from interfering with each other.

9
4.2 Three Ways to Use this Package in your Projects
Depending on your programming experience and your game’s specific requirements, there’s (roughly
speaking) three general ways you can use this package to help you realize your projects.

a) Using one of the included controller prefabs


The prefabs included in this package should already cover most of the common types of character
movement in games nowadays. Each of them is designed in a way that allows for very detailed and
extensive customization, to suit almost any game’s basic requirements.
For example, the first person walker prefab in this package can be easily turned into anything rang-
ing from a fast twitch shooter (like ’Quake’ ) to a slow, contemplative walking simulator, simply by
adjusting some values in the Unity inspector.
Especially for quick game prototyping, game jams or even a quick test run of a level design, the included
prefabs should easily cover all your bases.
In chapter 5, ’Overview Over All Included Controller Prefabs’, you’ll find a comprehensive overview of
all the different prefabs and their individual use cases.
A detailed description of all inspector variables for all relevant components can be found in chapter 6,
’Component Descriptions’.

b) Extending and modifying the included controller scripts


If your game does require a particularly unorthodox movement system, there’s the option of extending
one of the included controller scripts and overriding some of its functions to implement your own code.
This option is meant to serve as a middle ground between not writing any custom code at all and
coding your very own controller script. That way, you get to keep all the physics calculations, basic
movement logic and controller states while still being able to add new features.
In addition to that, if you want to keep all the movement code the way it is but you need to process
the user input in a specific way or if you want to get input from a third-party input system, it’s also
possible to write a custom input script.
More information on how to implement custom controller input can be found in chapter 7, ’Imple-
menting Custom Input’.

c) Writing a custom controller script


Finally, if you need full control over every detail of your character controller, you can also simply write
a completely custom controller script yourself.
Even if this option requires some work on your part, it really isn’t as difficult as it may sound at
first, because the Mover component already takes care of most of the tricky parts related to character
movement: Handling slopes and stairs, ground detection and ground normals, correctly calculating
rigidbody velocities...
This option might also be a good way to go, if you’ve already written a controller for a different system
(like Unity’s built-in character controller, for example) and want to reuse your code. Adapting your
existing character movement logic to fit with Character Movement Fundamentals’ Mover component
should be a fairly easy process.
Read more on how to write a custom controller script in chapter 8, ’Writing a Custom Controller
Script’.

10
5 Overview Over All Included Controller Prefabs
The selection of character controllers included in this package are designed to cover a wide range of
gameplay types. Each one is meant to provide a good starting point for your own individual character
controller, which is why you’ll find all of them containing only the bare essentials needed for the
character controller to function.
As mentioned in chapter 3, most of the character controllers come in two variants - blank and animated.
Both are functionally identical, however, all animated variants are set up with simple animation
and sound effect systems as an example on how to link character movement and animations/sounds
together.
This chapter will provide a quick description of each prefab, what kind of gameplay styles they are
most suited for and which special components they make use of.

All Controllers
Generally speaking, all prefabs use the following set of basic components (with different settings):

• Mover
• Smooth Position
• Smooth Rotation

5.1 ’Animated’ and ’Blank’ Controller Prefabs


FirstPersonWalker
This is your classic first person controller - you move around using the ’WASD’ keys on your keyboard
(or any other set of keys of your choice) and look around by moving your mouse (or gamepad stick,
for example).

Fig. 18 The ’FirstPersonWalker’ prefab.

11
As the name implies, the player camera is positioned where the character’s eyes would be, giving you
a first-person perspective of the game environment.
This prefab is a great starting point for any kind of first-person character controller. By changing some
of its properties in the inspector (like movement speed, jump speed, air control...), you can fine-tune
its movement to suit almost any type of gameplay.
It uses the following components:

• Advanced Walker Controller


• Camera Controller

ThirdPersonWalker A
This prefab serves as a basic foundation for a typical third person controller.

Fig. 19 The ’ThirdPersonWalker A’ prefab.

Movement-wise, it functions very similarly to the FirstPersonWalker preset, however, the player cam-
era is positioned outside and slightly above the character’s head.
To prevent the camera from going into level geometry or other objects in your scenes, all third-person
prefabs also use a special component called Camera Distance Raycaster, which scans for any colliders
blocking the camera’s view.
In addition to this, the 3D model of the character is continuously rotated toward the movement
direction of the controller.
It uses the following components:

• Advanced Walker Controller


• Camera Controller
• Camera Distance Raycaster
• Turn Toward Controller Velocity

12
ThirdPersonWalker B
This prefab is almost identical to ThirdPersonWalker A, the only difference being that it uses a slightly
more specialized camera controller script, which turns the camera toward the characters movement
direction.
This behaviour is commonly expected by players in third person games, which are not primarily
shooters, such as the ’Dark Souls’ or ’Spyro the Dragon’ series, for example.

• Advanced Walker Controller


• Third Person Camera Controller
• Camera Distance Raycaster
• Turn Toward Controller Velocity

ThirdPersonWalker C
This prefab is also almost identical to ThirdPersonWalker A, this time however, the character model
is always rotated toward the direction the camera is facing.

Fig. 20 The ’ThirdPersonWalker C’ prefab.

This makes sense for almost all third person shooters (a popular example being ’Fortnite’ ), since the
player character commonly aims in the same direction as the camera.

• Advanced Walker Controller


• Third Person Camera Controller
• Camera Distance Raycaster
• Turn Toward Transform Direction

13
TopDownWalker
If you need a character controller suited for a top-down game, this prefab will meet all your basic
requirements.

Fig. 21 The ’TopDownWalker’ prefab.

The camera itself is offset quite far above the character and camera rotation around its x-axis (the
”pitch” axis) is disabled.

• Advanced Walker Controller


• Camera Controller
• Turn Toward Controller Velocity

ClickToMoveWalker
This controller provides basic ’click-to-move’ functionality - simply click anywhere on the screen and
the controller will move toward the chosen position.
This kind of movement is commonly found in top-down role-playing games, like the ’Diablo’ series, for
example.
By default, this controller does not include any camera controls (though it’s easy to add them if
needed).

• Click To Move Controller


• Turn Toward Controller Velocity

14
SideScroller
This prefab is meant to provide a solid foundation for any 2D character controller - whether you’re
developing a 2D retro platformer, a sidescrolling shooter or a stealth game set in 2D, this prefab is a
good starting point.

Fig. 22 The ’SideScroller’ prefab.

In contrast to the other prefabs, character movement is locked to a 2D plane and the camera position
and rotation is fixed, as is usual in most 2D games.

• Sidescroller Controller
• Turn Toward Controller Velocity

About the animated variants


As already mentioned, all animated variants of the controller prefabs are functionally identical to their
blank counterparts.
They do, however, use a few additional components to implement animations and sounds (such as
footsteps, for example).

• Animation Controller
• Audio Controller

15
5.2 ’Simple’ Controller Prefabs
The package also comes with two ’simple’ controller prefabs. The main purpose of these prefabs is to
provide an easier introduction for anyone who’s never worked with character movement logic before.

SimpleFirstPersonWalker

This prefab is a simplified version of the ’FirstPersonWalker’. The only real difference between them
is that this prefabs uses the Simple Walker Controller component.

• Simple Walker Controller


• Camera Controller

SimpleThirdPersonWalker

This prefab is a simplified version of the regular ’Third Person Walker’ prefabs. Again, the only
difference is the use of the Simple Walker Controller component.

• Simple Walker Controller


• Camera Controller
• Camera Distance Raycaster
• Turn Toward Controller Velocity

16
6 Component Descriptions
In order to use this package to its full potential, it is helpful to have a good understanding of all the
components and their configurable variables available in the inspector.
This chapter will provide a thorough description of all components and their settings and how to
customize them to fit your game.

6.1 Mover
The Mover component is used by all character controllers in this package to handle character movement
and any interactions with the environment.

(a) Normal view...

(b) ...and with ’Raycast Array’ selected as the sensor


type.

Fig. 23 The ’Mover’ component in the inspector.

It also handles resizing the character’s collider and automatically updates any changes to its dimensions
while the editor is running. As a result, you should use the settings provided by this script to change
the shape, size and offset of the attached collider instead of directly changing settings on the collider
component itself.

17
To optimize your game’s performance, you can choose between different sensor types for ground de-
tection.

• Raycast - Uses only a single raycast.


• Spherecast - Uses a spherecast.
• RaycastArray - Uses an array of raycasts. The number and distribution of raycasts can be further
specified (see figure 23b).

Different sensor types may exhibit slight differences when dealing with certain slopes and level geometry
- I recommend giving each one a try to determine the best fit for your game.
The component will require a rigidbody and a collider to work. All basic Unity colliders (box, capsule,
sphere) are supported, although I recommend using the capsule variant, as its shape is better suited
to interact with most types of level geometry.

Step Height Ratio Acceptable step height ratio. This value ranges from ’0’
to ’1’ and is relative to the collider’s height. For example,
value of ’0.5’ means that the character will be able to
walk on stairs half its height. See figure 25 for a visual
example.
Collider Height Height of the attached collider
Collider Thickness Thickness/width of the attached collider.
Collider Offset (Relative) position offset of the attached collider.
Sensor Type Which type of sensor will be used for ground detection.
Debug Mode If debug mode is enabled, all surface points and normals
detected are displayed in the editor. Also see figure 24.
Sensor Array Rows If ’RaycastArray’ is chosen as the sensor type, this will
control how many rows the array will have.
Sensor Array Ray Count If ’RaycastArray’ is chosen as the sensor type, this will
control how many rays each row in the array will have.
Sensor Array Rows Are If ’RaycastArray’ is chosen as the sensor type, this will
Offset offset every other row for a better ray distribution.

In addition to that, if ’RaycastArray’ is chosen as the sensor type, a preview will be shown at the
bottom of the inspector (see figure 23b).

18
Fig. 24 With debug mode enabled, detected surface points and normals are shown in red in the scene
view. Using the wireframe view mode is recommended for better visibility. The calculated average
position is shown as a green arrow.

Fig. 25 In the image above, ’step height ratio’ is set to ’0.25’. All obstacles lower than the resulting
height (orange), which is exactly 1/4th (= 0.25) of the characters height (shown in purple), are walkable
- the blocks on the right (green) will be treated as stairs, while the block on the left (red) is considered
a wall.

19
6.1.1 Ceiling Detector
The Ceiling Detector component is an optional component that, if attached to a gameobject that also
has an Advanced Walker Controller component, will help register collisions with colliders above the
character.
The component uses Unity’s collision callback functions (’OnCollisionEnter’, ’OnCollisionStay’) and
will determine whether a collision qualifies as a ”ceiling collision” based on the collision normal.

Fig. 26 The ’Ceiling Detector’ component in the inspector.

For more information on how this component works internally, please check out chapter 8.4, ’Detecting
Ceilings Collisions with the ’CeilingDetector’ Component’.

Ceiling Angle Limit This angle limit is used to determine whether a surface
normal counts as a ceiling contact. A value of ’0’ will
never register any collisions, while any value above ’90’
will treat almost anything as ceilings, even walls. For
most cases, ’15’ will work best.
Ceiling Detection This will determine how the component handles multi-
Method ple collision normals. Options include: Only check the
very first normal (’Only Check First Contact’), check if
at least one contact qualifies (’Check All Contacts’) and
checking the average of all contacts (’Check Average Of
All Contacts’).
Is In Debug Mode If enabled, collision contact information will be drawn in
the editor.

20
6.2 Controllers
Simple Walker Controller
This controller offers simple movement options and is used by the ’simple’ controller prefabs included
in the package.
It will get player input from an Input script, keep track of the current vertical speed of the controller
and calculate a movement vector, which is then passed to the Mover component.

Fig. 27 The ’Simple Walker Controller’ component in the inspector.

Movement Speed Movement speed of the character.


Jump Speed Jump speed of the character.
Gravity Amount of (downwards) gravity when the controller is in
the air.
Camera Transform If a camera transform is assigned, the controller will move
relative to that camera’s view. If left blank, the con-
troller’s transform axes will be used instead to calculate
its movement direction.

Advanced Walker Controller


This controller offers advanced movement options and is used by most of the controller prefabs in the
package.
It will get player input from an Input script, keep track of gravity and other physical forces and
calculate a movement vector, which is then passed to the Mover component.
Compared to the ’Simple Walker Controller’, this component offers many options to fine-tune character
movement such as advanced jumping controls, sliding off steep slopes, built-in momentum and air
control.

Fig. 28 The ’Advanced Walker Controller’ component in the inspector.

21
Movement Speed General movement speed of the controller.
Air Control Rate Rate at which the controller can change direction while
in the air. Generally speaking, a higher value will result
in a more responsive but less ”realistic” game feel.
Jump Speed Jump speed of the controller. Higher jump speed values
will allow the character to jump higher.
Jump Duration Maximum jump duration of the controller. If this value
is set to anything above ’0’, the player can keep pressing
the ’jump’ key for a higher jump.
Air Friction Amount of friction applied to the controller’s momentum
when it is in the air.
Ground Friction Amount of friction applied to the controller’s momentum
when it is grounded.
Gravity Amount of (downwards) gravity when the controller is in
the air.
Slide Gravity Amount of (downwards) gravity when the controller is
sliding on a steep slope.
Slope Limit This controls whether a surface is considered as ground
or as a slope, based on its surface normal. For example, a
value of ’70’ will allow the controller to walk on all slopes
that are less steep than 70 degrees.
Use Local Momentum If this is enabled, the controller’s momentum will be cal-
culated locally (meaning if the controller is rotated, its
momentum will be rotated as well).
Camera Transform If a camera transform is assigned, the controller will move
relative to that camera’s view. If left blank, the con-
troller’s transform axes will be used instead to calculate
its movement direction.

Sidescroller Controller
This component extends the Advanced Walker Controller and locks (horizontal) character movement
to a 2D plane defined by the character’s local ’up’ and ’right’ transform axis.

Fig. 29 The ’Sidescroller Controller’ component in the inspector.

22
Click To Move Controller
This controller provides basic ’click-to-move’ controls - the controller will continue to move toward the
position the player has clicked on, until the target position is reached or a new target is chosen.
In addition to that, the component also comes with a few customization options, such as:

• Allowing the user to hold down the mouse button to keep the controller moving.
• Two different raycast detection methods to determine the target position.
• A simple time-out system that will stop the controller from moving if it gets stuck (in a corner,
for example).

Fig. 30 The ’Click To Move Controller’ component in the inspector.

Movement Speed General movement speed of the controller.


Gravity Amount of (downwards) gravity when the controller is in
the air.
Hold Mouse Button To If enabled, the controller will continually move toward the
Move mouse cursor if the mouse button is held down.
Mouse Detection Type Raycast method used to calculate target position. Choose
between ’Abstract Plane’ (less accurate, but ignores ceil-
ings) or ’Raycast’ (more accurate, but ceilings may block
raycast).
Time Out Time If the controller has not moved at least a certain distance
during this timeframe, it will stop moving.
Time Out Distance If the controller has not moved at least this distance in a
Threshold certain timeframe, it will stop moving.

23
6.3 Character Input Scripts
Character input scripts are responsible for calculating and processing user input. At runtime, these
scripts will be accessed by the controller components to get the latest input.

Character Keyboard Input


This character input script calculates keyboard user input and internally uses Unity’s default input
system.

Fig. 31 The ’Character Keyboard Input’ component in the inspector.

Horizontal Input Axis Name of input axis used for going left/right.
Vertical Input Axis Name of input axis used for going forward/backward.
Jump Key Key used for jumping.
Use Raw Input Whether to use raw input values or Unity’s built-in
smoothing when calculating input.

Character Joystick Input


This character input script calculates joystick/gamepad user input and internally uses Unity’s default
input system.

Fig. 32 The ’Character Joystick Input’ component in the inspector.

Horizontal Input Axis Name of input axis used for going left/right.
Vertical Input Axis Name of input axis used for going forward/backward.
Jump Key Key used for jumping.
Use Raw Input Whether to use raw input values or Unity’s built-in
smoothing when calculating input.
Dead Zone Threshold Any input value below this threshold will be set to ’0’.
This helps with preventing any unwanted inputs caused
by joystick jitters.

24
6.4 Camera Scripts
Camera Controller
This component is a general-purpose camera controller - thanks to its adaptability, you can use it in
almost any game that requires a player-controlled camera.

Fig. 33 The ’Camera Controller’ component in the inspector.

It provides built-in camera smoothing for a more ”natural” game feel and options for limiting the
vertical camera angle.

Upper Vertical Limit Upper limit (in degrees) of the rotation around the x-axis.
Lower Vertical Limit Lower limit (in degrees) of the rotation around the x-axis.
Camera Speed Speed at which the camera rotates.
Smooth Camera Whether to smooth player input for a smoother camera
Rotation rotation.
Camera Smoothing If ’Smooth Camera Rotation’ is enabled, this value will
Factor be used to smooth the camera’s rotation. A value of ’50’
will result in no noticeable smoothing, while a value of ’1’
will result in very noticeable smoothing.

Third Person Camera Controller


A slightly modified version of the regular Camera Controller. Is is functionally identical, but adds an
additional option useful for third-person games.

Fig. 34 The ’Third Person Camera Controller’ component in the inspector.

25
If the option ’Turn Camera Toward Movement Direction’ is enabled, the camera controller will rotate
toward the current movement direction of the character. This camera behaviour is commonly used in
third-person games to give the player a better view of where the character is heading.
The speed of this rotation is tied to the character’s movement speed, as well as the remaining angle
between the camera’s view and the characters movement direction.

Turn Camera Toward If enabled, the camera will turn toward the character’s
Movement Direction movement direction.
Controller Reference to a controller component. The velocity of this
controller will be used to calculate the movement direc-
tion.
Maximum Movement Reference speed used when calculating the speed of the
Speed rotation toward the character’s movement direction. This
value should be set to the maximum movement speed
achievable by the controller (i.e. the ’Movement Speed’
setting).
Camera Turn Speed Speed at which the camera turns.

26
Camera Distance Raycaster
This script will automatically try to detect any obstacles between camera and character and, if any
obstacles are detected, will move the camera closer to the character to prevent it from clipping into
level geometry.

Fig. 35 The ’Camera Distance Raycaster’ component in the inspector.

It is recommended to parent the actual camera gameobject to the ’target’ gameobject, in order for the
system to work properly. Please study the included controller prefabs to see this setup in action.

Camera Transform Reference to the transform component of the camera.


Camera Target This transform reference is used as the raycast target.
Transform
Cast Type Type of cast used for detecting obstacles. You can choose
between either a single raycast or a spherecast.
Layer Mask Layermask used when scanning for obstacles.
Ignore List List of colliders to ignore while scanning. In many cases,
it makes sense to add the character’s main collider to this
list, if you encounter any stuttering or glitches.
Minimum Distance from Minimum required distance from any obstacle. When an
Obstacle obstacle is detected, the camera is moved at least this far
away from it to prevent clipping.
Smoothing Factor This value determines how smoothly the camera position
will be adjusted. A value of ’50’ (or greater) will result
in no visible smoothing while a value of ’1’ (or lower) will
result in extreme smoothing. I recommend trying a few
different settings to find the best choice for your game.
Generally speaking, ’25’ is a good default value for most
situations.
Spherecast Radius When Spherecast is chosen as cast type, this value will
determine its radius.

27
Fig. 36 Without the ’Camera Distance Raycaster’ - the camera will clip into level geometry at lower
angles, causing graphical glitches.

Fig. 37 With the ’Camera Distance Raycaster’ enabled - the camera is moved closer to the character
whenever an obstacle is detected. No clipping occurs.

28
6.5 Camera Input Scripts
Camera input scripts are responsible for calculating and processing user input (related to camera
movement). At runtime, the camera controller scripts will then access these inputs scripts to get the
latest input.

Camera Mouse Input


This camera input script calculates mouse input and internally uses Unity’s default input system.

Fig. 38 The ’Camera Mouse Input’ component in the inspector.

Mouse Horizontal Axis Name of input axis used for rotating the camera left/right.
Mouse Vertical Axis Name of input axis used for rotating the camera up/down.
Invert Horizontal Input If enabled, inverts horizontal input.
Invert Vertical Input If enabled, inverts vertical input.
Mouse Input Multiplier Mouse input will be multiplied by this value. Use this to
fine-tune mouse sensitivity.

Camera Joystick Input


This camera input script calculates joystick/gamepad user input (related to camera movement) and
internally uses Unity’s default input system to do so.

Fig. 39 The ’Camera Joystick Input’ component in the inspector.

Joystick Horizontal Axis Name of input axis used for rotating the camera left/right.
Joystick Vertical Axis Name of input axis used for rotating the camera up/down.
Invert Horizontal Input If enabled, inverts horizontal input.
Invert Vertical Input If enabled, inverts vertical input.
Dead Zone Threshold Any input value below this threshold will be set to ’0’.
This helps with preventing any unwanted inputs caused
by joystick jitters.

29
6.6 Smoothing and Other Visual Scripts
Smooth Position
This script will smooth out the position of the gameobject it is attached to by interpolating between
last frame’s position and the current position.

Fig. 40 The ’Smooth Position’ component in the inspector.

It is used by all the included prefabs to smooth out some of the inconsistencies and occasional stutters,
which can happen from time to time in Unity’s internal physics calculations.
Alternatively, you can use it for a ’smooth camera follow’ effect in third-person or 2D games.
You can choose from two different smoothing methods - Unity’s built-in ’Smooth Damp’ and ’Lerp’
(linear interpolation), which will behave slightly differently. It is recommended to try both and use
the option that serves your game best.
Additionally, the script can either run during Unity’s Update or LateUpdate cycle, to prevent multiple
smoothing scripts from interfering with each other.

Target Target transform to lerp/smooth damp towards. When


left empty, the transform’s parent is automatically chosen
as the target.
Lerp Speed Speed at which the object is lerped toward its target.
Used when Lerp is chosen as the smooth type.
Smooth Damp Time This value determines how fast the object is smooth
damped toward its target. Used when Smooth Damp is
chosen as the smooth type.
Extrapolate Position If this option is enabled, the target position is extrapo-
lated to decrease some of the delay caused by the smooth-
ing process. Note: This setting can potentially cause some
’bouncing’ for very slow smoothing settings.
Update Type Whether this script is run during Update or LateUpdate.
Smooth Type Whether the object’s position is interpolated using the
Lerp or Smooth Damp method.

30
Smooth Rotation
This script works very similarly to Smooth Position, but smoothes the object’s rotation instead.

Fig. 41 The ’Smooth Rotation’ component in the inspector.

Target Target transform to smooth towards. When left empty,


the object’s parent is chosen as the target.
Smooth Speed Speed at which the object’s rotation is smoothed toward
its target rotation.
Extrapolate Rotation If this is enabled, the target rotation is extrapolated to de-
crease some of the delay caused by the smoothing process.
Note: This setting can potentially cause some ’bouncing’
for very slow smoothing settings.
Update Type Whether this script is run during Update or LateUpdate.

Turn Toward Controller Velocity


This script rotates the gameobject it is attached to toward a target controller’s movement velocity.

Fig. 42 The ’Turn Toward Controller Velocity’ component in the inspector.

It is normally used to rotate a character mesh toward the movement direction of its controller compo-
nent.

Controller Reference to a controller component.


Turn Speed Speed at which the gameobject is rotated toward the con-
troller’s movement velocity.
Ignore Controller If enabled, only the controller’s movement velocity is used
Momentum to calculate the new rotation (momentum is ignored).

31
Turn Toward Camera Direction
This script rotates a gameobject toward the view direction of a Camera Controller component.

Fig. 43 The ’Turn Toward Camera Direction’ component in the inspector.

Normally, it would be used to make a character look in the same direction as the camera, which is
very common in third-person shooters, for example.

Camera Controller Reference to a camera controller component.

Turn Toward Transform Direction


This script rotates a gameobject toward the ’forward’ direction of a target transform.

Fig. 44 The ’Turn Toward Transform Direction’ component in the inspector.

It functions similarly to the Turn Toward Camera Direction component, but uses a target transform.

Target Transform Reference to a transform.

Align Rigidbody To Target


This script continually rotates a rigidbody, to keep its ’up’ axis aligned to a target object.

Fig. 45 The ’Align Rigidbody To Target’ component in the inspector.

It can be used to implement a simple ’planetary gravity’ effect when used on a controller prefab.

Target Reference to the target object used when aligning.

32
6.7 Animation and Audio
Animation Control
This script serves as a basic animation controller. It is included in this package to demonstrate how
to connect animations and character movement.

Fig. 46 The ’Animation Control’ component in the inspector.

It requires an Advanced Walker Controller to work and will pass necessary information (whether the
character is grounded, its current speed) to an animator component.
If ’Use Strafe Animations’ is enabled, a blend tree more suited for strafing character movement will
be used.

Use Strafe Animations Whether to use a blend tree better suited for strafing
character movement.
Land Velocity Threshold The character’s ’land’ animation is only triggered if
the controller’s vertical speed exceeds this threshold on
ground contact.

Audio Control
This script provides some basic audio control features for game characters. It serves as a demonstration
on how to connect animations, character movement and sound effects.

Fig. 47 The ’Audio Control’ component in the inspector.

It requires an Advanced Walker Controller component to work and will use the controller’s velocity
and its events to play footstep sounds and sound effects for jumping and landing.
In addition to that, it can trigger footstep sound either when a certain distance has been walked by
the character or based on specific animation curves.
For the second option to work, you need animation curves named ’Footstep’ in your animations, to
trigger a sound every time the character’s animation touches the ground. Please take a look at some
of the animation assets included in this package for a working example.

33
Audio Source Reference to an audio source component, which will be
used to play the audio clips.
Use Animation Based If enabled, footstep sounds will be played based on ani-
Footsteps mation curves instead of based on travelled distance.
Land Velocity Threshold The character’s ’land’ sound effect is only played if
the controller’s vertical speed exceeds this threshold on
ground contact.
Footstep Distance If the above option is disabled, footstep sounds will be
played every time this distance is reached by the charac-
ter.
Audio Clip Volume Volume of all sound clips.
Relative Randomized If set to ’0’, all footsteps will be equally loud. If set to
Volume Range anything higher, footstep sounds will progressively differ
in volume. This results in more natural sounding patterns
of footsteps.
Foot Step Clip Audio clip used for footsteps.
Jump Clip Audio clip used for jumping.
Land Clip Audio clip used for landing.

34
6.8 Environment Scripts
Moving Platform
This script serves as a basic example of a moving platform system and is included in this package
mainly for demonstration purposes.

Fig. 48 The ’Moving Platform’ component in the inspector.

It will move a gameobject along a predefined path of waypoints and move any controllers standing on
it along.

Movement Speed General platform movement speed.


Reverse Direction If enabled, the order of waypoints is reversed.
Wait Time How long the platform will wait every time it reaches a
waypoint before continuing.
Waypoints List of waypoints.

6.9 UI Scripts
Mouse Cursor Lock
This script serves provides basic mouse cursor locking functionality.

Fig. 49 The ’Mouse Cursor Lock’ component in the inspector.

After attaching this script to any object in the scene, you can hide and show the mouse cursor by
pressing assignable keys.

Lock Cursor At Game Whether the mouse cursor will be locked at the start of
Start the game.
Unlock Key Code Key used to unlock mouse cursor.
Lock Key Code Key used to lock mouse cursor.

35
7 Implementing Custom Input
7.1 How the Input Scripts Work
As of version 2.0, Character Movement Fundamentals features a streamlined way to get and process
user input. As a result, implementing custom input systems or even third-party input solutions is now
easier than ever.
Put simply, all input-related code is contained in separate scripts, called Input Scripts, which need to
be attached to the same gameobject as the Controller and Mover components.
At runtime, the controller scripts will get all the necessary input values from these input scripts by
using predefined functions.
There are two distinct types of input scripts included in the package: Character Input and Camera
Input, which will be accessed by controller scripts and camera scripts, respectively.

7.1.1 Character Input


Character Input scripts are accessed by controller scripts (such as the Advanced Walker Controller )
by calling the following functions:

GetHorizontal- Returns the current horizontal (left/right) input as a float


MovementInput() value
GetVertical- Returns the current vertical (forward/backward) input as
MovementInput() a float value
IsJumpKeyPressed() Returns true, if the jump key is currently pressed down

7.1.2 Camera Input


Camera Input scripts are accessed by camera controller scripts (such as the Camera Controller ) by
calling the following two functions:

GetHorizontal- Returns the current horizontal (looking left/right) input


CameraInput() as a float value
GetVertical- Returns the current vertical (looking up/down) input as
CameraInput() a float value

7.2 Writing a Custom Character Input Script


As a practical example, let’s go over how to write a custom character input script.
First off, we’ll need to include a using directive at the top of our script, since we’ll be extending the
base CharacterInput class (which is part of the ’CMF’ namespace).
To do this, simply add the directive right below the usual Unity directives:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CMF; //’CMF’ is the namespace used by the ’Character Movement Fundamentals’ package;

36
Next, we extend the base CharacterInput class, like this:
public class MyCustomCharacterInputScript : CharacterInput { [...]

At this point, your scripting IDE (Visual Studio, for example), will probably prompt you to implement
the three required functions. For now, we’ll just implement them empty, like this:
public override float GetHorizontalMovementInput()
{
return 0f;
}

public override float GetVerticalMovementInput()


{
return 0f;
}

public override bool IsJumpKeyPressed()


{
return false;
}

Technically, what we have now is already a valid input script and would work as-is when used in
combination with a controller component.
Of course, the script will always return no input, which makes it fairly useless. To change that, we’ll
actually need to return some useful input information.
For example, we could add the following code to the ’IsJumpKeyPressed()’ function:
public override bool IsJumpKeyPressed()
{
if(Input.GetKey(KeyCode.Space) && Input.GetKey(KeyCode.J))
{
return true;
}
else
{
return false;
}
}

As a result, the character will now only jump if the Spacebar and the ’J’ key on the keyboard are
pressed at the same time.
The other two functions should return a float value, typically ranging somewhere from ’-1’ to ’1’.
A very classic implementation could look like this:
public override float GetHorizontalMovementInput()
{
return Input.GetAxis("Horizontal");
}

Which will just get the current axis input directly from Unity’s built-in input system and pass it along.

37
Alternatively, here’s a more unconventional way to achieve a similar result:
public override float GetHorizontalMovementInput()
{
if(Input.GetKey(KeyCode.A))
{
return -1f;
}
else if(Input.GetKey(KeyCode.D))
{
return 1f;
}
else
{
return 0f;
}
}

Generally speaking, you’re free to do whatever you want in a custom input script, as long as the three
functions return the intended values at the end.
For example, you could add code to your custom script to access an external component (maybe a
third-party input solution), receive the appropriate input and pass it along.
You could add a toggle that switches between different kinds of input.
You could invert the input axes, if you want to.
The Camera Input scripts function nearly identical - the only difference being that you would extend
a different base class (’CameraInput’ instead of ’CharacterInput’ ) and override two differently named
functions (as mentioned earlier).
In addition to that, please consider taking a look at all the different input scripts included in the
package to get a better idea of some of the possibilities.

38
8 Writing a Custom Controller Script
In case your game needs some special features, which go beyond what the included controller prefabs
or even overriding input functions can accomplish, there’s always the option of programming a custom
controller script.
Writing your very own controller script may sound difficult at first glance, but thanks to the Mover
component, which takes care of most of the common technical difficulties of character controller pro-
gramming, it’s actually a very straightforward process. Of course, basic knowledge about programming
in Unity is needed here, as this will require you to code.
This chapter may also be relevant for you if you’ve already written a character controller script in
the past (maybe using Unity’s built-in components) and are considering reusing your code in a new
project. Adapting an existing controller script to work with the Mover component should only require
a few minor changes to your code.

8.1 Basic Script Structure


One very important thing to keep in mind when writing a custom controller is that the Mover
component runs in FixedUpdate(). This is because it is based on Unity’s rigidbody physics
system, which is run in FixedUpdate() to provide a stable, framerate-independent simulation. As a
result, all controller scripts need to be run in FixedUpdate() as well.
Having mentioned that, here’s the basic layout I recommend for writing a controller script:
//’CMF’ is the namespace used by the ’Character Movement Fundamentals’ package;
using CMF;

public class MyCustomControllerScript : MonoBehaviour {

//Reference to attached mover component;


Mover mover;

void Start () {
//Get references to mover component;
mover = GetComponent<Mover>();
}

void FixedUpdate () {
//Run initial mover ground check;
mover.CheckForGround();

//Check whether the character is grounded;


bool _isGrounded = mover.IsGrounded();

Vector3 _velocity = Vector3.zero;

//Calculate the final velocity for this frame;


[...]

//If the character is grounded, extend ground detection sensor range;


mover.SetExtendSensorRange(_isGrounded);

//Set mover velocity;


mover.SetVelocity(_velocity);
}
}

39
For a better understanding of all the basic elements, let’s go through each one separately:
//’CMF’ is the namespace used by the ’Character Movement Fundamentals’ package;
using CMF;

public class MyCustomControllerScript : MonoBehaviour {

Starting from version 2.0 of this asset, all code in the package is contained within the ’CMF’ namespace
to keep your own code cleanly separated from the included scripts.
As a result, if you intend to use or access any of the code of the package, you need to add a ’using’
directive, usually right below the regular Unity directives.
//Reference to attached mover component;
Mover mover;

void Start () {
//Get references to mover component;
mover = GetComponent<Mover>();
}

Since the mover component will be called every physics frame, it makes sense to store a reference in
Start() or Awake() to save performance.
void FixedUpdate () {
//Run initial mover ground check;
mover.CheckForGround();

Before doing any calculations or checks that rely on whether the character is grounded (or not), it is
crucial to first run the mover’s ground check function.
//Check whether the controller is grounded;
bool _isGrounded = mover.IsGrounded();

After calling the mover’s ground check function, we can determine whether the character is grounded
at any time. Depending on your specific character movement code, being grounded might be required
for the character to jump or change the character’s movement speed, among other effects.
Vector3 _velocity = Vector3.zero;
//Calculate the final velocity for this frame;
[...]

At this point in the script, you would typically put your own code to calculate the character’s velocity
for this physics frame. Later in this chapter, there will a basic code example on how to calculate the
velocity for very basic character movement.
//If the controller is grounded, extend ground detection sensor range;
mover.SetExtendSensorRange(_isGrounded);

To allow the character to move down terrain, slopes and stairs, is is necessary for the mover’s ground
check range to be extended when the character is grounded. This is meant to better approximate
what walking down stairs or slopes feels like: A continuous motion instead of constantly losing and
regaining ground contact.

40
//Set mover velocity;
mover.SetVelocity(_velocity);

Finally, the movement velocity for this frame is passed to the mover component. One important thing
to keep in mind here is that the velocity must not be multiplied with Time.deltaTime.
Kinematic controllers, such as Unity’s built-in character controller, basically expect an instruction like
”Move in this direction by this distance, right now!”, while rigidbody-based controllers, like the
controllers in this package, need to be told something like ”This is your movement velocity, use it later
to calculate your new position when the physics simulation is run!”.
I highly recommend sticking to this script outline, unless you plan on heavily modifying the Mover
component itself (which would go beyond the scope of this user manual).

8.2 A Basic Controller Code Example


Using the basic code outline discussed in the previous chapter, all that’s left for a functional controller
script is to calculate the character’s velocity.
To keep this example practical, let’s assume that our character needs to be able to walk around at a
changeable speed, as well as jump and fall according to a custom gravity.
The first step should be to add some variables to the basic script outline:
float currentVerticalSpeed = 0f;
bool isGrounded;

public float movementSpeed = 7f;


public float jumpSpeed = 10f;
public float gravity = 10f;

In order to let the character jump and fall in a believable way, we need a variable to store its current
vertical speed, aptly named currentVerticalSpeed.
This variable’s value will change when the character jumps (by adding speed based on jumpSpeed ) and
when it falls (by subtracting speed based on gravity).
In addition to that, we’ll also add movementSpeed (so we can change the character’s movement speed
if needed) and a simple boolean variable to track whether it is grounded (isGrounded ).
//Run initial mover ground check;
mover.CheckForGround();

//Check whether the character is grounded and store result;


isGrounded = mover.IsGrounded();

Next, after having run the mover’s ground check function, we store the result in our isGrounded
variable.
Vector3 _velocity = Vector3.zero;

//Add player movement to velocity;


_velocity += Vector3.forward * Input.GetAxis("Vertical") * movementSpeed;
_velocity += Vector3.right * Input.GetAxis("Horizontal") * movementSpeed;

On to calculating velocity: We’ll start by adding the characters movement for this frame, which consists
of the player’s input and the character’s movement speed multiplied with two global direction vectors.
Next up is the character’s custom gravity.

41
//Handle gravity;
if(!isGrounded)
{
currentVerticalSpeed -= gravity * Time.fixedDeltaTime;
_velocity += Vector3.up * currentVerticalSpeed;
}
else
{
if(currentVerticalSpeed <= 0f)
currentVerticalSpeed = 0f;
}

Essentially, the above code checks if the character is grounded and if not, subtracts from its current
vertical speed, based on our variable gravity.
However, if the character is grounded, we’ll get rid of any negative vertical speed - after all, we don’t
want any forces pressing the character down, if it is already touching the ground.
//Handle jumping;
if(isGrounded && Input.GetKey(KeyCode.Space))
{
currentVerticalSpeed = jumpSpeed;
isGrounded = false;
}

Right after that, we will implement jumping, by simply checking if a) the character is grounded as
well as b) the player is pressing down the spacebar on their keyboard.
If both conditions are met, we’ll replace the current vertical speed with the characters jump speed,
effectively adding a lot of upwards speed in a split second, thus approximating a jump.
Furthermore, we also need set isGrounded to false, since our character clearly can’t be grounded
anymore, after having just initiated a jump.
//Add vertical velocity;
_velocity += Vector3.up * currentVerticalSpeed;

mover.SetExtendSensorRange(isGrounded);
mover.SetVelocity(_velocity);

The resulting vertical speed is then added to the final velocity by multiplying it with the global ”up”
vector in the scene.
After that, all that is left to do is to extend the mover’s ground check range if the character is grounded
and to finish our script, pass the resulting final velocity to the mover component, which will take it
from here.
Finally, here is the finished script in its entirety:
using CMF;

public class MyCustomControllerScript : MonoBehaviour {

private Mover mover;

float currentVerticalSpeed = 0f;


bool isGrounded;

public float movementSpeed = 7f;


public float jumpSpeed = 10f;

42
public float gravity = 10f;

void Start () {
//Get references;
mover = GetComponent<Mover>();
}

void FixedUpdate () {
//Run initial mover ground check;
mover.CheckForGround();

//Check whether the character is grounded and store result;


isGrounded = mover.IsGrounded();

Vector3 _velocity = Vector3.zero;

//Add player movement to velocity;


_velocity += Vector3.forward * Input.GetAxis("Vertical") * movementSpeed;
_velocity += Vector3.right * Input.GetAxis("Horizontal") * movementSpeed;

//Handle gravity;
if(!isGrounded)
{
currentVerticalSpeed -= gravity * Time.fixedDeltaTime;
}
else
{
if(currentVerticalSpeed <= 0f)
currentVerticalSpeed = 0f;
}

//Handle jumping;
if(isGrounded && Input.GetKey(KeyCode.Space))
{
currentVerticalSpeed = jumpSpeed;
isGrounded = false;
}

//Add vertical velocity;


_velocity += Vector3.up * currentVerticalSpeed;

mover.SetExtendSensorRange(isGrounded);
mover.SetVelocity(_velocity);
}
}

Please refer to the Advanced Walker Controller (and the scripts which extend it) as well as the Simple
Walker Controller, for examples of more controller scripts. All code is fully documented and, even
though it is more complex, still follows the same basic code structure described in this chapter.

43
8.3 Extending the Abstract Base ’Controller’ Class
The package also comes with an abstract Controller base class that you can extend and use as the base
for your own controller script.
Extending from this base class will allow your custom script to interface properly with some of the
secondary scripts in the package, such as:

• ’Turn Toward Controller Velocity’


• ’Third Person Camera Controller’
• ’Flip At Right Angle’
• ’Animation Control’
• ’Audio Control’

To extend this base class in your own controller scripts, include it in your class declaration:
using CMF;
public class MyCustomControllerScript : Controller {

At this point, you’ll need to implement the (virtual) functions of the base class (by using the ’override’
keyword):
public override Vector3 GetVelocity()
{
//Return current controller velocity;
}

public override Vector3 GetMovementVelocity()


{
//Return only current controller movement velocity;
}

public override bool IsGrounded()


{
//Return whether the controller is currently grounded;
}

In addition to that, the class also includes a set of two delegate functions (’OnLand’ and ’OnJump’ )
that can be called in extending scripts to trigger animations and sounds.
Please see the Advanced Walker Controller and the Simple Walker Controller for some examples of
how you can use these delegates in your own scripts.

8.4 Detecting Ceilings Collisions with the ’CeilingDetector’ Component


To handle collisions with colliders above a character’s head (let’s refer to them as ”ceiling collisions”),
you can use the optional Ceiling Detector component.
As mentioned earlier in the manual, this component uses Unity’s physics event functions (’OnCol-
lisionEnter’, ’OnCollisionStay’) to check whether the character has hit any ceilings during the last
frame.
To make use of this functionality in your own controller scripts, attach the component to the same
gameobject as your controller script and simply use its ’HitCeiling()’ function:

44
CeilingDetector ceilingDetector = GetComponent<CeilingDetector>();

if(ceilingDetector.HitCeiling())
{
//Handle collision with ceiling here;
}

However, there’s one important thing to keep in mind when using this script: Always make sure to
call the component’s ’ResetFlags()’ function at the very end of your controller script’s execution.
This resets the last frame’s hit information and could look something like this in your code:
void FixedUpdate()
{
//Your regular controller code goes here;
[...]

//Reset ceiling detector;


ceilingDetector.ResetFlags();
}

45
8.5 Moving a Controller Relative to the Camera’s View
Instead of using global transform axes (like Vector3.up), as we did in the example controller script, it
makes more sense in most games that use a rotating camera for the character to move relative to the
camera’s view.
In this chapter, I’ll quickly go over two ways to implement this in your custom controller scripts.

Projecting the Camera’s Transform Axes


The first option consists of simply taking a chosen camera’s transform component and projecting its
axes on the ground.
Unity already comes with an easy-to-use function, namely ’Vector3.ProjectOnPlane’, that simplifies
the projecting itself a lot.
For example, here’s a short piece of code that projects the camera’s ’forward’ axis on the ground:
//Get the ’forward’ axis of the camera;
Vector3 cameraForward = cameraTransform.forward;

//We use the character’s ’up’ axis to define a ground plane to project on;
Vector3 groundPlaneNormal = characterTransform.up;

//Project the axis;


Vector3 projectedForward = Vector3.ProjectOnPlane(cameraForward, groundPlaneNormal);

//Normalize result;
projectedForward.Normalize();

After doing this, we can now use the resulting vector to calculate a character’s movement direction.
For a more complex example, I recommend taking a look at the code of the Simple Walker Controller
script, specifically the ’CalculateMovementDirection()’ function, which uses the same method.

Using the Camera Controller’s Built-in Functions


Another possibility is using the three ’direction’ functions provided by the Camera Controller compo-
nent.
• GetFacingDirection()
• GetStrafeDirection()
• GetAimingDirection()

Fig. 50 The vectors returned by ’GetAimingDirection’(orange)


and ’GetFacingDirection’ (blue).

46
As seen in the diagram above, each function will return a different vector representing either the
direction the camera is facing in, the corresponding ’strafing’ direction or the direction the camera is
pointing (or aiming) at.
For character movement, you should use the facing direction to move the character forward/backwards
and the strafe direction to move it sidewards.
The aiming direction can either be used to fire projectiles or weapons in shooter games, to raycast for
specific game objects or to determine where the player is currently looking at.
You would use these functions in your custom controller code by replacing the following lines:
Vector3 _velocity = Vector3.zero;

//Add player movement to velocity;


_velocity += Vector3.forward * Input.GetAxis("Vertical") * movementSpeed;
_velocity += Vector3.right * Input.GetAxis("Horizontal") * movementSpeed;

With something similar to this:


Vector3 _velocity = Vector3.zero;

//Add camera direction vectors;


_velocity += cameraController.GetFacingDirection() * Input.GetAxis("Vertical") * movementSpeed;
_velocity += cameraController.GetStrafeDirection() * Input.GetAxis("Horizontal") * movementSpeed;

Of course, your character’s hierarchy needs to contain a Camera Controller component and you would
have to get a reference to this component first by using the Start or Awake functions in your custom
script.

47
9 Writing External Scripts
9.1 A Quick Note Regarding Namespaces
Since all the code in the package is contained inside the ’CMF’ namespace (to keep your project’s
scripts separate from the package’s scripts), it is necessary to add a ’using’ directive, usually right
below the default Unity directives, so you can actually access functions and classes from ’Character
Movement Fundamentals’.
Luckily, this is quite easy and only requires you to add one short line of code at the very beginning of
your scripts:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CMF; //<--This right here;

After that, you’re good to go!

9.2 Adding Forces to a Controller


Since the Mover component is directly controlling (and overriding) the rigidbody’s velocity, using the
default physics functions for adding forces like ’AddForce()’ will have no effect.
Instead, the Advanced Walker Controller component provides its own function to add forces:
public void AddMomentum (Vector3 _momentum)

Calling this function from an external script allows you to directly add to the controller’s momentum
without causing any problems with its internal movement logic.
After that, the newly added momentum will be affected by the controller’s friction and gravity settings.
void LaunchUpwards()
{
//Add upwards momentum to controller;
controller.AddMomentum(Vector3.up * 100f);
}

For example, the code above would instantly launch the controller directly upwards, which could be
used for a ’jump pad’ effect.
The Advanced Walker Controller also comes with a function to directly set the controller’s momentum:
void ResetMomentum()
{
//Nullify controller momentum;
controller.SetMomentum(Vector3.zero);
}

This may come in handy if you need to take direct control of the controller’s momentum, such as
resetting the momentum (as seen above).

48
9.3 Rotating the Camera Toward a Target Direction or an Object in the
Scene
In many games, making the camera look at a specific object in the scene (or in a specific direction) is
a simple but efficient way to direct the player’s attention.
Other times, you might even want to give the player direct control over this camera behaviour, so they
can ”lock on” to enemies in third-person games (as seen in games like ’Dark Souls’ ).
To make implementing this kind of camera movement easier, the Camera Controller component offers
the following two functions:
public void RotateTowardPosition(Vector3 _position, float _lookSpeed)
public void RotateTowardDirection(Vector3 _direction, float _lookSpeed)

Using them in your code only requires you to call one of them from an external script and pass either
the position of an object in the scene or a direction vector you calculated, as well as a speed value (to
control how much the camera will turn in that one frame).
void Update()
{
if(Input.GetKey(Keycode.Q)
{
//Rotate camera toward ’targetObject’;
cameraController.RotateTowardPosition(targetObject.position, 45f);
}
}

In the code example above, the camera is rotated toward a target object as long as the player is holding
down the ’Q’ key on their keyboard.
However, it is important to keep in mind that the function has to be called continuously over many
frames for the camera to eventually look in the intended direction - as a result, it is best used in either
Update() or as part of a coroutine.

49
9.4 Changing Collider Dimensions at Runtime
Sometimes, you might need to resize the character at runtime. A very common example would be a
crouching system, which reduces the character’s vertical height while a button is held down.
Since the Mover component takes the character’s size into account when doing any ground detection,
simply resizing the collider directly will inevitably result in glitching and errors.
Instead, I recommend changing the collider’s dimensions via the Mover component, which comes with
the three following, built-in functions:
public void SetColliderHeight(float _newColliderHeight)
public void SetColliderThickness(float _newColliderThickness)
public void SetStepHeightRatio(float _newStepHeightRatio)

Calling any of these functions will also automatically recalibrate the Mover’s ground detection.
For example, here’s a short code example that reduces the collider’s height to ’1’ whenever the ’Control’
key is pressed and reverts its height by pressing ’Shift’:
if(Input.GetKeyDown(KeyCode.LeftControl))
{
mover.SetColliderHeight(1f);
}

if(Input.GetKeyDown(KeyCode.LeftShift))
{
mover.SetColliderHeight(2f);
}

One thing I’d just like to mention here is that resizing the collider will not change the scale of the
actual gameobject in any way. So, for a convincing ’crouching’ effect, triggering an animation to
visually match the change in height will be necessary as well.

50
10 How to Connect Animations and Audio to Character Move-
ment
The addition of animations and sounds to a character will make it feel more believable as well as add
more feedback for the player to react to. Some practical examples of this include:

• Triggering footstep sound clips whenever a character reaches a certain point in its walking ani-
mation.
• Passing a characters current movement speed to a blend tree for believable animated character
movement.
• Adding a subtle head bobbing motion to your player camera, when the character is moving.
• Activating a screen shake animation when the player character lands on the ground after a high
jump.

In order to make implementing all of this easier, Advanced Walker Controller features getter func-
tions and delegates to help you access all the necessary information you might want to pass to your
animator components and audio scripts.
Already included in the package are two scripts, Animation Control and Audio Control, which are
used by all the animated character controller prefabs as a demonstration on how to realize some of the
examples mentioned above.
Both scripts are fully documented and I recommend referring to them when programming more ad-
vanced animation and audio control scripts.

10.1 Getter Functions

GetVelocity() Returns the current velocity of the character as a Vector3


GetMovementVelocity() Returns only the current movement velocity (without
momentum) of the character as a Vector3
GetMomentum() Returns the current momentum of the character as a
Vector3
IsGrounded() Returns true, if the character is currently grounded.

Here’s a basic code example of these values being retrieved and passed to an animator component:
using CMF;

public class MyAnimationControl : MonoBehaviour {

AdvancedWalkerController controller;
Animator animator;

void Start()
{
controller = GetComponent<AdvancedWalkerController>();
animator = GetComponentInChildren<Animator>();
}

void Update () {
//Get controller velocity;

51
Vector3 _velocity = controller.GetVelocity();

//Get controller grounded status;


bool _isGrounded = controller.IsGrounded();

//Pass values to animator component;


animator.SetBool("IsGrounded", _isGrounded);
animator.SetFloat("Speed", _velocity.magnitude);
}
}

10.2 Delegates

OnJump() This delegate is called when the character initiates a jump.


OnLand() This delegate is called when the character lands after being in the air.

In both cases, the current velocity of the character (at the time the delegate was called) is provided
as a Vector3. You can use this vector to (for example) determine the intensity of the animation which
accompanies the event or to calculate a fitting audio volume for a sound cue.
You can use these delegates in your own code by connecting your own functions to them, like this:
using CMF;
public class MyControllerEventHandler : MonoBehaviour {

AdvancedWalkerController controller;
Animator animator;
AudioSource audioSource;

void Start()
{
controller = GetComponent<AdvancedWalkerController>();
animator = GetComponentInChildren<Animator>();
audioSource = GetComponentInChildren<AudioSource>();

//Connect events to controller events;


controller.OnLand += OnLand;
controller.OnJump += OnJump;
}

void OnLand(Vector3 _v)


{
//Set animation trigger;
animator.SetTrigger("OnLand");

//Only play audio clip if velocity magnitude surpasses a certain threshold;


if(_v.magnitude > 10f)
audioSource.Play();

void OnJump(Vector3 _v)


{
//React to event by playing audio clip, animations, [...]
animator.SetTrigger("OnJump");
}
}

52

You might also like