Character Controlling

For most games or apps a character / camera controlling is necessary to move in 3D space. This section handles firstperson- and thirdperson character controlling and all expandable components. The framework makes it very easy to implement such behaviour. Without huge coding you can setup everything at design-time.

The TGorillaCharacterController is the basis class for TGorillaFirstPersonController and TGorillaThirdPersonController, but should not be used directly, because it's only an abstraction layer for shared functionality.

All character controllers receive inputs from a TGorillaInputController instance. By those inputs a linked camera component will be moved or users are allowed to interact with your game.

Hotkeys

Because we've linked an input controller to the character controller, we have to define hotkeys to react on.

In short this means: if the input controller detects a hotkey, it will forward the event to the character controller. And then the character controller will react on the hotkey event by a specific operation, like moving forward or shooting.

By default the character controllery already defines standardized hotkeys, like W-A-S-D for movement. But you're allowed to overwrite those hotkeys by your own.

Predefined input hotkeys by the TGorillaCharacterController class are:

Predefined

NAME CODE DEVICE
KEY_FORWARDGORILLA_INPUT_KEY_WKeyboard
KEY_BACKWARDGORILLA_INPUT_KEY_SKeyboard
KEY_LEFTGORILLA_INPUT_KEY_AKeyboard
KEY_RIGHTGORILLA_INPUT_KEY_DKeyboard
KEY_JUMPGORILLA_INPUT_KEY_SPACEKeyboard
KEY_CROUCHGORILLA_INPUT_KEY_CTRL_LEFTKeyboard
KEY_CRAWLGORILLA_INPUT_KEY_ALTGRKeyboard
KEY_BOOSTGORILLA_INPUT_KEY_SHIFT_LEFTKeyboard
KEY_AIMGORILLA_INPUT_KEY_ALTKeyboard
KEY_CUSTOM1Code: GORILLA_INPUT_KEY_QKeyboard
KEY_CUSTOM2Code: GORILLA_INPUT_KEY_EKeyboard
KEY_CUSTOM3Code: GORILLA_INPUT_KEY_FKeyboard
KEY_CUSTOM4Code: GORILLA_INPUT_KEY_CKeyboard
KEY_STARTCode: GORILLA_INPUT_KEY_ESCAPEKeyboard
KEY_MODECode: GORILLA_INPUT_KEY_PAUSEKeyboard
KEY_BACKCode: GORILLA_INPUT_KEY_SHIFT_BACKSPACEKeyboard
KEY_MENU_UPGORILLA_INPUT_KEY_ARROW_UPKeyboard
KEY_MENU_DOWNGORILLA_INPUT_KEY_ARROW_DOWNKeyboard
KEY_MENU_LEFTGORILLA_INPUT_KEY_ARROW_LEFTKeyboard
KEY_MENU_RIGHTGORILLA_INPUT_KEY_ARROW_RIGHTKeyboard
MOUSE_LEFTBUTTONGORILLA_INPUT_MOUSE_LBUTTONMouse
MOUSE_MIDDLEBUTTONGORILLA_INPUT_MOUSE_MBUTTONMouse
MOUSE_RIGHTBUTTONGORILLA_INPUT_MOUSE_RBUTTONMouse
GAMEPAD_MOVE0GamePad
GAMEPAD_MOVE_FORWARDGORILLA_INPUT_GAMEPAD_DPAD_UPGamePad
GAMEPAD_MOVE_BACKWARDGORILLA_INPUT_GAMEPAD_DPAD_DOWNGamePad
GAMEPAD_MOVE_LEFTGORILLA_INPUT_GAMEPAD_DPAD_LEFTGamePad
GAMEPAD_MOVE_RIGHTGORILLA_INPUT_GAMEPAD_DPAD_RIGHTGamePad
GAMEPAD_JUMPGORILLA_INPUT_GAMEPAD_SHOULDER_RIGHTGamePad
GAMEPAD_CROUCHGORILLA_INPUT_GAMEPAD_THUMBSTICK_RIGHTGamePad
GAMEPAD_CRAWLGORILLA_INPUT_GAMEPAD_THUMBSTICK_LEFTGamePad
GAMEPAD_BOOSTGORILLA_INPUT_GAMEPAD_SHOULDER_LEFTGamePad
GAMEPAD_AIMGORILLA_INPUT_GAMEPAD_THUMBSTICK_LEFTGamePad
GAMEPAD_BUTTONAGORILLA_INPUT_GAMEPAD_BUTTON_AGamePad
GAMEPAD_BUTTONBGORILLA_INPUT_GAMEPAD_BUTTON_BGamePad
GAMEPAD_BUTTONXGORILLA_INPUT_GAMEPAD_BUTTON_XGamePad
GAMEPAD_BUTTONYGORILLA_INPUT_GAMEPAD_BUTTON_YGamePad
GAMEPAD_STARTGORILLA_INPUT_GAMEPAD_STARTBUTTONGamePad
GAMEPAD_MODEGORILLA_INPUT_GAMEPAD_MODEBUTTONGamePad
GAMEPAD_BACKGORILLA_INPUT_GAMEPAD_BACKBUTTONGamePad
GAMEPAD_MENU_UPGORILLA_INPUT_GAMEPAD_DPAD_UPGamePad
GAMEPAD_MENU_DOWNGORILLA_INPUT_GAMEPAD_DPAD_DOWNGamePad
GAMEPAD_MENU_LEFTGORILLA_INPUT_GAMEPAD_DPAD_LEFTGamePad
GAMEPAD_MENU_RIGHTGORILLA_INPUT_GAMEPAD_DPAD_RIGHTGamePad

Remark: All available input codes are defined in Gorilla.Controller.Input.Consts.pas.

Modification

Axis Movement

The default character controllers only move along the X and Z axis.

You can enable or disable axis movement by the lock properties:

Property Description
LockXAxis Lock or unlock X-axis for movement. Enable this property if you don't want the character to force movement on x direction.
LockYAxis Lock or unlock Y-axis for movement. Enable this property if you don't want the character to force movement on y direction.
LockZAxis Lock or unlock Z-axis for movement. Enable this property if you don't want the character to force movement on Z direction.

Even if we unlock it, up and down movement along the y-axis is still not possible by default. There's no interaction with the underlying area.

You can implement that yourself by OnMove and OnRotate event

Speed

In case movement or rotation speed does not suit your needs. You can of course modify those values, too.

Property Description
Speed Get or set speed of movement. A basis speed value applied to direction vector. Default value is 1.0.
RunningSpeedBoostBoost factor on speed if state is fpBoost. Values between 1-1000 are allowed. Default value is 2.0.
MouseControllerSpeedGet or set mouse speed. The value controls camera rotation speed. Default value is 0.075.
GamePadThumbstickSpeedGet or set gamepad controller thumbstick speed for movement and rotation speed. Default value is 0.5.
CrawlingSpeedReductionFactor of reduction on speed if state is fpCrawling. Values between 0.0 - 1.0 are allowed. Default value is 0.15.
CrouchingSpeedReductionFactor of reduction on speed if state is fpCrouching. Values between 0.0 - 1.0 are allowed. Default value is 0.15.

Boost

The boost mode getting triggered by the OnBoost event. By default boost mode is active by holding the left shift key down or the left shoulder button on your gamepad.

“RunningSpeedBoost” is multiplied with the current speed value. And the current speed value can be the normal speed or reduced speed by crawling and crouching.

If boost movement is active, states should contain the fpBoost flag.

Rotation Sideways

By default we rotate the controller by moving the mouse to left or right. This will implicitly rotates the camera view too. You can disable this behaviour by setting the “RotateOnSideways” property to true. And as best practice it is recommended to also deactivate the “MoveSideways” property.

Moving the camera up and down by mouse move will still be possible.

Property Description
RotateOnSidewaysThe left and right movement will be used to rotate the camera left to right, instead of strifing the character to the side.
SidewayRotationSpeedGet or set speed of sideway rotation. A basis speed value applied to direction vector. Default value is 1. This value will only be recognized, if RotateOnSideways is enabled.
MoveSideways Activate or deactivate to move character sideways on move-left/right hotkeys.

Movement Drag Mode

We can also enable movement only when dragging is active. W-A-S-D or thumbstick movement behaviour will then no longer work.

Only if left mouse button is dragged (MovementDragModeButton == LButtonDown) the camera will be moved into view direction. This behaviour is sometimes used in strategy games when moving along a map.

And in case you want to invert the movement, you can use the “InvertMovementDragModeXAxis” and “InvertMovementDragModeYAxis” property.

PropertyDescription
MovementDragModeGet or set MovementDragMode value, which defines if camera movement is only been applied, if mouse-down button is active. Set MovementDragModeButton to define the mouse button to be used. Valid states are: LButtonDown, MButtonDown, RButtonDown
MovementDragModeButtonGet or set mouse button to be used if MovementDragMode is enabled. Valid states are: LButtonDown, MButtonDown, RButtonDown
InvertMovementDragModeXAxisInvert the X-Axis direction value if MovementDragMode is enabled.
InvertMovementDragModeYAxisInvert the Y-Axis direction value if MovementDragMode is enabled.

Rotation Drag Mode

We can also enable rotation only when dragging is active. It's then no longer possible to rotate the camera without holding the drag button.

PropertyDescription
RotationDragModeGet or set RotationDragMode value, which defines if camera rotation is only been applied, if mouse-down button is active. Set RotationDragModeButton to define the mouse button to be used. Valid states are: LButtonDown, MButtonDown, RButtonDown
RotationDragModeButtonGet or set mouse button to be used if RotationDragMode is enabled. Valid states are: LButtonDown, MButtonDown, RButtonDown

Rotation Around Center

In case you want to use the first person controller without a free camera rotation, but instead with a rotating first-person controller, use the “RotateAroundCenter” property.

WARNING: This property is currently a little bit buggy!

Hide Cursor

In many games you don't want to show the mouse cursor. On Windows platform we provide an easy to use property called “ShowCursor”, which enables or disables the displayed mouse cursor.

PropertyDescription
ShowCursorYou can show/hide mouse cursor while first person controller is running. It is recommended to disable it already at design time.

Size

A character controller is not only a virtual component, it actually should have a size. Therefor it is important to define a Width, Height and Depth for you controller, suitable to the expected character size.

It will be the basis for jumping, crawling, crouching and later for physics collision detection.

PropertyDescription
WidthWidth of the virtual character controller.
HeightHeight of the virtual character controller.
DepthDepth of the virtual character controller.

Jumping

You can control the jumping height and the time it takes by the “JumpingAnimationTime” and the “JumpingHeight” property.

While jumping, states should contain the fpJumping state.

JumpingHeight is a multiplier for the character height. So a value of 2 means it can jump up the double of its size. And the animation time is given in seconds and tells the controller how long it takes for jumping.

PropertyDescription
JumpingHeightMultiplier of peek jumping height for the virtual character controller.
JumpingAnimationTimeTime in seconds the jumping up and down takes.

Crouching

You can control switching to crouch-mode. While the “CrouchingAnimationTime” is the time it takes to enter or leave that mode, the “CrouchingHeight” is the final character size in that mode, based on it's original height.

When crouching is active states should contain the fpCrouching state.

CrouchingHeight is a multiplier for the character height. A value of 0.5 means, the character height in crouching is only half of it's full size. And the animation time is given in seconds and tells the controller how long it takes to get down to crouching or up from crouching. Internally an animation runs, that shrinks or grows the character size.

PropertyDescription
CrouchingHeightMultiplier for originl characters height. Will define the active crouching size.
CrouchingAnimationTimeTime in seconds the animation takes to enter or leave the crouching state.
CrouchingSpeedReductionMultiplier to reduce regular speed while in crouching mode.

Crawling

Besides the crouching mode, you can also control switching to crawling-mode. Crouching often is half of the size of the character, while crawling is less then a quater of it.

While the “CrawlingAnimationTime” is the time it takes to enter or leave that mode, the “CrawlingHeight” is the final character size in that mode, based on it's original height.

When crawling is active states should contain the fpCrawling state.

CrawlingHeight is a multiplier for the character height. A value of 0.25 means, the character height in crawling is only a quater of it's full size. And the animation time is given in seconds and tells the controller how long it takes to get down to crawling or up from crawling. Internally an animation runs, that shrinks or grows the character size.

PropertyDescription
CrawlingHeightMultiplier for originl characters height. Will define the active crawling size.
CrawlingAnimationTimeTime in seconds the animation takes to enter or leave the crawling state.
CrawlingSpeedReductionMultiplier to reduce regular speed while in crawling mode.

Push / Pull

Two states are not automatically handled, because developers always have to decide when pushing or pulling is activated.

When pushing is active states should contain the fpPushing state.

When pulling is active states should contain the fpPulling state.

MethodDescription
procedure Push(AEnabled : Boolean);Manually activates/deactivates the pushing state and calls the OnPush event.
procedure Pull(AEnabled : Boolean); Manually activates/deactivates the pulling state and calls the OnPull event.

Default Behaviour

Finally there are 2 important properties to deactivate default behaviour of our character controllers.

PropertyDescription
UseDefaultBehaviour Will deactivate any automatic operation handling like jumping, crouching, crawling, moving and so on. But the user-specific callback events like OnMove, OnJump or OnCrawl and so on, are still getting called.
UseDefaultMovementAllows to disable default movement of the controller. This has no influence on camera rotation.

User-Friendly Events

For individual treatment you can disable or overwrite those predefined hotkeys. The basic character controller component catches all input events, handles them and throws back user-friendly events.

Event CallbackDescription
OnIdleTOnCharacterControllerEventOnIdle event getting raised when first person controller switches to idle mode.
OnMoveTOnCharacterControllerMoveEventOnMove event getting raised in doOnMoveForward, doOnMoveBackward, doOnMoveLeft, doOnMoveRight and DoOnGamePadThumbstickPos methods, used by keyboard hotkeys and gamepad thumbstick movement.
OnRotateTOnCharacterControllerRotateEventOnRotate event getting raised if the view was rotated by DoOnGamePadThumbstickPos or DoOnMouseMove.
OnBoostTOnCharacterControllerEventOnBoost event getting raised when boost mode was activated or deactivated.
OnCrouchTOnCharacterControllerEventOnCrouch event getting raised when crouching was activated or deactivated.
OnCrawlTOnCharacterControllerEventOnCrawl event getting raised when crawling was activated or deactivated.
OnJumpTOnCharacterControllerEventOnJump event getting raised when first person controller is jumping.
OnAimTOnCharacterControllerEventOnAim event getting raised when aiming mode was activated or deactivated.
OnPushTOnCharacterControllerEventOnPush event getting raised when pushing mode was activated or deactivated
OnPullTOnCharacterControllerEventOnPull event getting raised when pulling mode was activated or deactivated.
OnCustomActionTOnCharacterControllerHotKeyTriggeredOnCustomAction event getting raised by keyboard custom action hotkeys and gamepad buttons.
OnClickTOnCharacterControllerHotKeyTriggeredOnClick event getting raised by clicking left, middle or right mouse button.
OnStartTOnCharacterControllerEventOnStart event getting raised when start hotkey was activated.
OnModeTOnCharacterControllerEventOnMode event getting raised when mode hotkey was activated.
OnBackTOnCharacterControllerEventOnBack event getting raised when back hotkey was activated.
OnNavigateTOnCharacterControllerHotKeyTriggeredOnNavigate event getting raised when menu navigation was triggered.
OnChangeSizeTNotifyEventGetting called, when leaving crouching or crawling mode.
OnHotKeyTOnCharacterControllerHotKeyTriggeredOnHotKey event getting raised when a registered hotkey was triggered. It's a central callback event for all hotkeys. Parallel to it hotkey specific events will be raised: OnIdle, OnMove, OnBoost, OnCrouch, OnJump, OnCustomAction, OnClick, OnStart, OnMode, OnBack and OnNavigate
OnTriggerPointTOnCharacterControllerTriggerPointIf a TGorillaTriggerPointManager component was linked to the first person controller, a trigger-point check will automatically be performed on movement. If then a trigger-point is in reach, the OnTriggerPoint event will be raised.

And the corresponding event method declarations look like:

NameDeclaration
TOnCharacterControllerHotKeyTriggeredprocedure(ASender : TObject; const AKind : TGorillaCharacterControllerHotKey; const AHotKey : TGorillaHotKeyItem; const AStates : TGorillaCharacterControllerStates; const AMode : TGorillaInputMode) of object;
TOnCharacterControllerMoveEventprocedure(ASender : TObject; AKind : TGorillaCharacterControllerHotKey; ADir : TPoint3D; ACurrentSpeed : Single) of object;
TOnCharacterControllerRotateEventprocedure(ASender : TObject; ACurrentRotation : TQuaternion3D; ANewRotation : TQuaternion3D; ADelta : TPointF) of object;
TOnCharacterControllerEventprocedure(ASender : TObject; AState : TGorillaCharacterControllerState; AMode : TGorillaInputMode) of object;
TOnCharacterControllerTriggerPointprocedure(ASender : TObject; AManager : TGorillaTriggerPointManager; APt : TGorillaTriggerPoint; ADist : Single) of object;

FirstPerson Controller

The TGorillaFirstPersonController controls movement of a linked camera component in its basic settings. But you're allowed to add sub controls like a TGorillaModel to display arms or weapons as known in typical ego shooter games.

You can set up a firstperson controller at design-time or at runtime by:

[...]
 
  protected
    FInputCtrl : TGorillaInputController;
    FFirstPersonCtrl : TGorillaFirstPersonController;
 
[...]
 
uses
  Gorilla.Controller.Input.Types,
  Gorilla.Controller.Input.Character,
  Gorilla.Controller.Input.FirstPerson;
 
[...]
 
FInputCtrl := TGorillaInputController.Create(Self);
FInputCtrl.Supported := [TGorillaInputDeviceType.Keyboard, TGorillaInputDeviceType.Mouse];
FInputCtrl.Enabled := true;
 
FFirstPersonCtrl := TGorillaFirstPersonController.Create(FViewport);
FFirstPersonCtrl.Parent := FViewport;
FFirstPersonCtrl.InputController := FInputCtrl;
FFirstPersonCtrl.Camera := FCamera;

ThirdPerson Controller

The TGorillaThirdPersonController is an extension of the TGorillaFirstPersonController but changes camera movement. It's the typical character controller when having a character model with a top down look by camera.

[...]
 
  protected
    FInputCtrl : TGorillaInputController;
    FThirdPersonCtrl : TGorillaThirdPersonController;
 
[...]
 
uses
  Gorilla.Controller.Input.Types,
  Gorilla.Controller.Input.Character,
  Gorilla.Controller.Input.ThirdPerson;
 
[...]
 
FInputCtrl := TGorillaInputController.Create(Self);
FInputCtrl.Supported := [TGorillaInputDeviceType.Keyboard, TGorillaInputDeviceType.Mouse];
FInputCtrl.Enabled := true;
 
FThirdPersonCtrl := TGorillaThirdPersonController.Create(FViewport);
FThirdPersonCtrl.Parent := FViewport;
FThirdPersonCtrl.InputController := FInputCtrl;
FThirdPersonCtrl.Camera := FCamera;

Optionally linkable components

It's usual to handle different things during character controlling. So you'd like to check for special positions in 3D space and execute actions when getting triggered. Or you like to playback sounds on specific states or refer to a sound-map.

The following components are allowed to link to a character controller:

Physics Character Controller

A TGorillaPhysicsCharacterController is a helper layer to manage physics engine, character controller and animation controller. The component handles all the complex management of collision detection and animation playback of a model on basis of a firstperson/thirdperson character controller. Without any programming it's possible to implement a game-typical character controlling, where animations switched automatically on different interactions. On top there is physics collision detection (capsule collider).

Besides easy-to-drop designtime handling, you can setup a physics character controller at runtime.

  [...]
 
  FAssetsManager : TGorillaAssetsManager;
  FMainPackage : TGorillaAssetsPackage;
 
  FPhysics : TGorillaPhysicsSystem;
  FAudioManager : TGorillaFMODAudioManager;
 
  FCharacter : TGorillaModel;
  FPhysCtrl : TGorillaPhysicsCharacterController;
  FAnimCtrl : TGorillaAnimationController;
  FInputCtrl : TGorillaInputController;
  FThirdPersonCtrl : TGorillaThirdPersonController;
  FAudioCtrl : TGorillaAudioManagerController;    
  FTriggerPoints : TGorillaTriggerPointManager;
 
  [...]
 
procedure TGameWindow.LoadCharacter(const AAssets : String);
var LPath : String;
    j : Integer;
    LLay : TGorillaAnimationTransitionLayer;
    LTP : TGorillaTriggerPoint;
begin
  // setup character assets path
  LPath := AAssets + IncludeTrailingPathDelimiter('mymodel');
 
  // create physics character controller (PCC)
  // a PCC is able to connect a character controller with a physics system
  // because with the terrain a collider was added, so that we can walk
  // with our character on it. the PCC will automatically add a capsule collider
  // for collision detection
  FPhysCtrl := TGorillaPhysicsCharacterController.Create(FViewport);
  FPhysCtrl.Parent := FViewport;
  // here we can control the gravity - default value = 25
  FPhysCtrl.GravityScale := 3;
 
  // create character model
  // this will just be a visual instance for our character
  // the controlling will be done by the physics character controller and the
  // third person character controller
  FCharacter := TGorillaModel.LoadNewModelFromFile(FPhysCtrl, FMainPackage,
        LPath + 'mymodel.dae', []);
  FCharacter.Parent := FPhysCtrl;
  // we don't want to interact with the model - so we deactivate any raycast tests.
  FCharacter.SetHitTestValue(false);
  // we always want to see our character, so we disable frustum culling check
  // nevertheless this should not be necessary
  FCharacter.FrustumCullingCheck := false;
  // position character model inside of PCC capsule collider (may be obsolete - depending on your model)
  FCharacter.RotationAngle.Point := Point3D(-180, 90, 0);
  FCharacter.Position.Point := Point3D(0, 8, 0);
  FCharacter.Scale.Point := Point3D(0.75, 0.75, 0.75);
 
  // load all animations used by animation controller
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-idle.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-walk-forward.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-walk-backwards.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-walk-left.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-walk-right.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-run-forward.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-run-backwards.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-run-left.dae');
  FCharacter.AddAnimationFromFile(LPath + 'mymodel-run-right.dae');
 
  [...]
 
  // we start the first animation in our model - this should be the basis animation
  // inside of the first model file.
  if Assigned(FCharacter.AnimationManager) and Assigned(FCharacter.AnimationManager.Current) then
    FCharacter.AnimationManager.Current.Start();
 
  // animation controller setup
  // create animation controller for handling animation transitions
  // animation transitions define how to switch from one animation to another
  // and which inputs / hotkeys are triggering
  FAnimCtrl := TGorillaAnimationController.Create(FViewport);
  // link the model to the animation controller, to apply animation transitions to
  FAnimCtrl.Model := FCharacter;
 
  // add all defined animation transitions
  LLay := FAnimCtrl.AddLayer('WalkingAnimations');
  LLay.AddTransition('idle-forward > walk-forward', 'mymodel-idle.dae', 'mymodel-walk-forward.dae', true, KeyboardMoveForward, [fpMoving], tmImmediatly);
  LLay.AddTransition('idle-backward > walk-backward', 'mymodel-idle.dae', 'mymodel-walk-backward.dae', true, KeyboardMoveBackward, [fpMoving], tmImmediatly);
  [...]
 
  // set the default animation to be played at the beginning
  FAnimCtrl.DefaultAnimation := 'mymodel-idle.dae'; // the filename of your idle animation
 
  // create an audio manager controller to automatically playback sounds on
  // specific hotkey actions
  FAudioCtrl := TGorillaAudioManagerController.Create(Self);
  FAudioCtrl.AudioManager := Self.FAudioManager;
  FAudioCtrl.AddHotKeyMapping('RUN_FORWARD',  SOUND_RUN,
        TGorillaCharacterControllerHotKey.KeyboardMoveForward, [fpMoving,fpBoost]);
  FAudioCtrl.AddHotKeyMapping('RUN_BACKWARD', SOUND_RUN,
        TGorillaCharacterControllerHotKey.KeyboardMoveBackward, [fpMoving,fpBoost]);
  FAudioCtrl.AddHotKeyMapping('WALK_FORWARD',  SOUND_WALK,
        TGorillaCharacterControllerHotKey.KeyboardMoveForward, [fpMoving]);
  FAudioCtrl.AddHotKeyMapping('WALK_BACKWARD', SOUND_WALK,
        TGorillaCharacterControllerHotKey.KeyboardMoveBackward, [fpMoving]);
 
  // create a trigger points manager and some coordinates to be triggered
  FTriggerPoints := TGorillaTriggerPointManager.Create(Self);
  // we don't want to check against camera, but againts the character model
  FTriggerPoints.RelatedControl := FCharacter;
  FTriggerPoints.Enabled := true;
 
  // wheel #1 trigger point
  LTP := FTriggerPoints.AddTriggerPoint('Wheel1', Point3D(-10, 0, 10), 0.25, 30);
  LTP.LookInDirection := false;
  LTP.Kind := TGorillaTriggerPointKind.StaticTriggerPoint;
  LTP.Data := TValue.From<String>('Press [E] to rotate wheel #1');
  LTP.Tag  := 1;
  LTP.OnTriggered := DoOnWheelTriggered;
  LTP.OnUnTriggered := DoOnWheelUnTriggered;
 
  // wheel #2 trigger point
  LTP := FTriggerPoints.AddTriggerPoint('Wheel2', Point3D(15, 0, -20), 0.25, 30);
  LTP.LookInDirection := false;
  LTP.Kind := TGorillaTriggerPointKind.StaticTriggerPoint;
  LTP.Data := TValue.From<String>('Press [E] to rotate wheel #2');
  LTP.Tag  := 2;
  LTP.OnTriggered := DoOnWheelTriggered;
  LTP.OnUnTriggered := DoOnWheelUnTriggered;
 
  // position the physics controller in 3D physics space - we let the capsule
  // collider drop from -75.0 onto the terrain.
  FPhysCtrl.Position.Point := Point3D(0, -5, 0);
  // link physics controller with character
  FPhysCtrl.Model := FCharacter;
  // resize the capsule collider for better scaled size regarding the scene size
  FPhysCtrl.SetSize(6, 16, 6);
 
  // create a third-person controller
  // this is the basic input handler for characters
  // this will control movement depending on inputs (by the input controller)
  FThirdPersonCtrl := TGorillaThirdPersonController.Create(FPhysCtrl);
  // attach the character controller to the physics character controller (PCC)
  // so it can automatically move it on interaction
  FThirdPersonCtrl.Parent := FPhysCtrl;
  // link the camera to the controller for automatic camera movement
  FThirdPersonCtrl.Camera := FCamera;
  // link the input controller to process all keyboard inputs, to let the
  // character move, jump or whatever
  FThirdPersonCtrl.InputController := FInputCtrl;
  // link the audio manager controller for automatic sound playback on hotkeys
  FThirdPersonCtrl.AudioManagerController := FAudioCtrl;
  // link triggerpoints manager for auto-detection of game coordinates
  FThirdPersonCtrl.TriggerPoints := FTriggerPoints;
 
  // deactivate default behaviour, because we're attaching the character controller
  // to the physics character controller and the physics system
  // we need to deactivate to allow physics system interaction with the character
  FThirdPersonCtrl.UseDefaultMovement := false;
  // reduce default speed, because of large scene scale
  FThirdPersonCtrl.Speed := 15;
 
  // set camera position a bit more far away for better optics
  FCamera.Position.Point := Point3D(25, 0, -20);
  FCamera.Target := FCharacter;
 
  // link animation controller to physics character controller (PCC)
  // the PCC will then automatically dispatch all input events to the animation
  // controller to playback the correct animation transition.
  FPhysCtrl.AnimationController := FAnimCtrl;
  // link the physics system to PCC, to interact with physics world (terrain and objects)
  FPhysCtrl.Physics := FPhysics;
  // link the character controller to PCC, to let the PCC know, what to control.
  FPhysCtrl.Controller := FThirdPersonCtrl;
end;    

Movement

Since the latest version of Gorilla3D (v0.8.3.1995) we support kinematic character movement. While previous versions worked completely on physics computation, the latest change added a more stable way.

The true physics collision detection for characters works, but has bad sideeffects. The most serious problem was stuttering characters which bounced off the terrain. Also it was impossible to “climb” up steep hills because physics always dragged you down again. Even if this is more realistic, the usability was horrible for classic character movement.

So in the latest component state the “UseRayCasting” property is activated. This changes the character controller from a dynamic rigid body to a kinematic body. Here we now cast a ray to detect the current position on objects instead of letting physics do the job. Nevertheless interaction with static or dynamic objects is still available.

Remark: In case you need the old behaviour, just switch “UseRayCasting” to FALSE.

Control you raycast-movement by some properties like Slop, RayDirection and RayOffset. Especially the slopping value allows you to control f.e. the max. height of stairs to be able to walk.

PropertyDescription
SlopThis only affects computation if UseRayCasting is enabled. The slop value is the maximum height a movement ray direction. Adjust this value to your specific scene, especially when walking of stairs or similar static objects. Default value is 0.5.
RayDirectionThe RayDirection defines in which direction the controller will be adjusted. Default direction is (0, 1, 0), which means downwards.
RayOffsetGet or set ray offset from where the raycasting is started. The offset will be computed from current physics character controller position.

Next step: Prefabs