Table of Contents

The SAMPLECHARACTERCONTROLLERS[1.0] package on the Zilch Market contains 2D and 3D input scripts that work with the SweptController component also included in the package. The SweptController is a generic kinematic character controller that is useful when prototyping many 2D and 3D game concepts.

Learning Objectives

  • Character controller explanation
  • Kinematic vs Dynamic
  • SweptController usage

Level Setup

  • Command : New Project

  • Create a new project using the {nav icon=clone, name=Empty 2D Project} template

  • Click the market button in the top right of the editor window image

  • Click the Sample Character Controller package image

  • Click the download link for the SAMPLECHARACTERCONTROLLERS[1.0].ZEROPACK image

  • Click the Import button button image

  • Close the Market Browser

  • Command : CreateCube

  • In the Properties Window

  • Under Transform

  • Set Scale to [50,1,1]

  • Under RigidBody

  • Set DynamicState enum to Static

  • In the Library Window

  • Under Archetype

  • Click and drag {nav icon=wrench, name=SweptPlayer2_5D} into the Level Window SweptArchetype

  • Command : PlayGame

  • Move left with A and right with D

  • Jump with Space

Swept2DMoving

The Player object moving and jumping

SweptInput

Let's take a look at the SweptInput2D component.

class SweptInput2D : NadaComponent
{
  [Dependency] var SweptController : SweptController;
  
  [Property] var LeftKey : Keys = Keys.A;
  [Property] var RightKey : Keys = Keys.D;
  [Property] var JumpKey : Keys = Keys.Space;
  
  function Initialize(init : CogInitializer)
  {
    Zilch.Connect(this.Space, Events.LogicUpdate, this.OnLogicUpdate);
  }

  function OnLogicUpdate(event : UpdateEvent)
  {
    var movement = Real3(0, 0, 0);
    
    // Check for left/right movment
    if(Zilch.Keyboard.KeyIsDown(this.LeftKey))
      movement.X = -1;
    if(Zilch.Keyboard.KeyIsDown(this.RightKey))
      movement.X = 1;
    
    if(Zilch.Keyboard.KeyIsPressed(this.JumpKey))
    {
      this.SweptController.Jump();
    }
    
    this.SweptController.Update(movement, event.Dt);
  }
}

Very similar to our dynamic character controller from the first input tutorial, we need to calculate a direction in which to move and whether the character should jump. Using the input properties, we can configure which inputs drive the SweptController.

The important line to note in SweptInput2D is this.SweptController.Update(movement, event.Dt);. SweptController.Update must be called every frame on which the character should be moving. This function handles much of the behavior of the SweptController and should always be called at the end of the input detection update function in order to apply any changes that were made to SweptController properties that frame.

Swept Controller Properties

Because the SweptCharacter uses a Kinematic object, it must handle its own gravity behavior. The strength of this gravitational acceleration can be adjusted per object.

  • In the Properties Window for Player object

  • Under SweptController

  • Set Gravity to 50

  • Command : PlayGame

  • Jump with Space

SweptGravity

*The Player object jumping with increased Gravity *

Notice that the acceleration of gravity is now more powerful.

The jump velocity is also adjustable.

  • In the Properties Window

  • Under SweptController

  • Set JumpSpeed to 25

  • Command : PlayGame

SweptJumpSpeed

*The Player object jumping with increased Gravity and increased JumpSpeed *

Using these values alongside MaxFallSpeed allows you determine how fast your character rises and falls with each jump.

In-Air Control

When the swept character is in the air, it has slight control by default. The SweptController allows you to modify the strength of that control.

air_control_default

*The Player object jumping and moving with default AirAcceleration *

Now let's try increasing the air control.

  • In the Properties Window

  • Under SweptController

  • Set AirAcceleration to 25

  • Command : PlayGame

  • Jump and then move side to side while in the air

air_control_High

*The Player object jumping and moving with increased AirAcceleration *

In addition to changing the rate of acceleration in the air, you can also modify the GroundAcceleration to similarly affect the SweptCharacter's acceleration when not in the air.

Max Ground Slope

Something you may not have thought about yet is how the SweptController detects whether it is on ground// or not. There are certain behaviors, such as jumping, that should only occur when the object is //on ground//. This //ground detection is done through a technique called //swept collision//, which is too advanced to cover in this tutorial. The final step of ground detection, though, is to check the angle of the slope that the character is on. If the slope is too steep, the SweptController will cause the character to slide down it instead of being able to move up it.

ground_angle

*Platforms both above and below the MaxGroundSlope *

Notice how the Player object object can move freely on the platform with a rotation of [0,0,25], but when it attempts to move onto the platform with a rotation of [0,0,-50], it slides off. This is due to the Z-Axis rotation of the lefthand platform having a greater magnitude than the MaxGroundSlope of the Player object's SweptController.

Swept Collision

Collision events were covered in the events tutorial. Now let's take a look at how they interact with the SweptController.

  • Command : Add Resource
  • Create a NadaScript resource using the Component template template and name it CollisionDetector
  • Update the CollisionDetector script to the following:
class CollisionDetector : NadaComponent
{
  function Initialize(init : CogInitializer)
  {
    Zilch.Connect(this.Owner, Events.CollisionStarted, this.OnCollisionStarted);
  }

  function OnCollisionStarted(event : CollisionEvent)
  {
    Console.WriteLine("`this.Owner` collided with `event.OtherObject`");
  }
}
---------------- Begin Game ----------------
Loaded level 0.00s
Level 'Level' was loaded.
Loaded level 0.00s
----------------  End Game  ----------------

Notice how our print statement from the CollisionDetector component is not executed. This is due to the fact that no standard collision is actually occurring here. The SweptController moves the player by predicting collision based on input and then translating to the correct point to simulate collision resolution. The result is that the kinematic collider of the Player object never actually touches the static colliders of the platforms.

  • Command : StopGame
  • In the Properties Window
  • Under SweptController
  • Set ForwardEvents checkBox to true

image

The customcollisioneventtracker detects circumstances where standard CollisionEvents would be sent out and dispatches them when a collider component would be involved in a standard collision.

---------------- Begin Game ----------------
Loaded level 0.00s
Level 'Level' was loaded.
Loaded level 0.00s
<Cog 'Player' (SweptPlayer2D) [2035]> collided with <Cog 'Cube' [2034]>
----------------  End Game  ----------------

Now we can detect and react to the CollisionEvents sent by the customcollisioneventtracker.

Related Materials

Tutorials

Manual

Reference

Commands

Classes

Events

Enums

Tasks

  • T1181