Skip to content

New physics based first/third person 3d and platformer like modular navigation + input axis and others#533

Open
and3md wants to merge 434 commits intomasterfrom
physics_third_person_navigation
Open

New physics based first/third person 3d and platformer like modular navigation + input axis and others#533
and3md wants to merge 434 commits intomasterfrom
physics_third_person_navigation

Conversation

@and3md
Copy link
Contributor

@and3md and3md commented Sep 19, 2023

Because our current navigation system is quite difficult to modify. We were looking for a way to add navigation that would be, on the one hand, quick to add and, on the other hand, easy to modify. This can be achieved in two ways:

  • add a simple behavior that contains the most basic functions (e.g. limited to moving and jumping) and let game programmer add/modify anything other he needs - this gives full control but also need a lot of work
  • create a system that can be expanded using smaller modules - in this case we have main behavior and a lot smaller that does only one thing like head bobbing, flying support, crouch support and game programmer add these modules to player transform and can implement his own modules when he need something that works different

This PR adds two such possibilities. In all cases we assume that player transform has rigid body and collider.

In the case of the first approach, I implemented two behaviors TSimplestFpsPlayerMovement and TSimpleFpsPlayerMovementWithRotation intended only for FPS games.

TSimplestFpsPlayerMovement

This is the simplest one it assumes that rigid body has blocked rotations and movement direction is determined by the camera direction.

It has few properties:

Property Description
JumpSpeed jump speed (Single value)
HorizontalSpeed speed of movement in X,Z axes (Single value)
ForwardInputAxis the new input axis for forward/backward direction
SidewayInputAxis the new input axis for left/right direction
InputJump input (key) for jump

In this case Player (TCastleTransform) should have camera as his child:

obraz

For camera rotations we use TRotateCamera behavior .

TSimplestFpsPlayerMovement will only work well in the simplest of situations when we do not care about (invisible in FPS game) player rotation. And as I wrote it has only base functions (move and jump) and it is intended to be copied and modified by the game developer.

TSimpleFpsPlayerMovementWithRotation

This behavior is similar to TSimplestFpsPlayerMovement but horizontal rotation (x axis) is made by rotating rigid body (using new TRotateRigidBody behavior.

The properties are the same like in TSimplestFpsPlayerMovement:

Property Description
JumpSpeed jump speed (Single value)
HorizontalSpeed speed of movement in X,Z axes (Single value)
ForwardInputAxis the new input axis for forward/backward direction
SidewayInputAxis the new input axis for left/right direction
InputJump input (key) for jump

In this case Player (TCastleTransform) should have camera as his child and be configured like that:

obraz

The only difference is using TRotateRigidBody for horizontal rotation (y axis) and now in TRotateCamera we rotate camera only vertical (x axis).

But this behavior is also only a start point for game developer that wants do anything in his own way. But what if we don't want implement everything by ourself but still want modify it? We should use TModularMovement

TModularMovement

TModularMovement is navigation system that can be used for all types of games like FPS, TPP and also 2D games.
For most usecases, it is enough to use the modules that we have prepared, and if something is missing or should work differently, game programmer can create another module or modify the existing one.

How does it work?

At first we add TModularMovement and then other modules depending on your needs e.g.

For 2D platformer like game we add TPlatformer2DWalkSupport - that covers jumping, moving left and right out of the box. When we want add double jump we just add TDoubleJumpSupport. All modules have also Exists property so when we want add double jump when player achieve something we simply set exists to false in editor and set to true in right moment.

Similarly for an FPS game we will add TWalk3DSupport for player moving if we want head bobbing simply add THeadBobbing for crouch TFpsCrouch et cetera.

How it works underneath?

TModularMovement has only three functions:

  • gets input
  • checks player is on ground
  • search all modules and run them in update.

All modules inherit from TAbstractMovementModule and implements/overides UpdateMovement() function.

Properties

Property Description
ForwardInputAxis the new input axis for forward/backward direction
SidewayInputAxis the new input axis for left/right direction
InputJump input (key) for jump
GroundPhysicsLayers physics layers used for ground checking

Configuration

This all may seem complicated it is really easy and a lot of things can be achieved without coding any single line of code.

FPS game

obraz

See castle-engine/examples/physics/physics_3d_shooter example.

TPP game:

Here we also use TFollowingTargetForCamera behavior in camera that supports following an object by 3d camera without writing any line of code.

obraz

See castle-engine/examples/physics/physics_3d_third_person example.

Platformer game

obraz

See examples/physics/physics_2d_movement

All modules list

Module Description
TAnimationTrigger Basic animation trigger for TPP game
TFpsCrouch Crouch support
TFly3DSupport Fly support for 3d games
TWalk3DSupport Walk for 3d games
THeadBobbing Head bobbing for FPS games
TStairsSupportByColliderCapsuleRadius Walking on staris support when collider friction > 0
TPlatformer2DWalkSupport 2D platformer walking support
TPlatformer2DInAirControl Ability to control player in air (2d games)
TDoubleJumpSupport Support for double jump (2d and 3d games)
TInAir3DControl In air control for 3D games

Other behaviors

Behaviors that can be usable in many use cases:

Behavior Description
TDirectRotateTransformByKeys Behavior for rotate object by keyboard (do not use with physics objects)
TFollowingTargetForCamera Behavior for Camera to follow Target (like in TPP games)
TRotateCamera Behavior for rotate camera
TRotateRigidBody Behavior for rotate rigid body by input axis

Input Axis

I implemented simple Input Axis that observes some keys/mouse and returns a value. More info in docs. How to use check other behaviors. (this PR description is getting to long)

Simple way to use mouse look

There are tow new functions in TCastleContainer: StartMouseLook() and StopMouseLook(); After StartMouseLook() Container starts update MouseLookLastDelta that can be used everywhere in your game. See TCastleInputAxis Value function and castle-engine/examples/physics/physics_3d_shooter main unit for example

Simple way to use mouse drag

There are tow new functions in TCastleContainer: StartMouseDrag() and StopMouseDrag(); After StartMouseLook() Container starts update MouseDragDelta that can be used everywhere in your game. See TCastleInputAxis.Value() function and castle-engine/examples/physics/physics_3d_shooter man unit for example

Simple way to use mouse wheel everywhere

There is LastUpdateMouseWheelDirection in TCastleContainer that contains mose wheel direction change from latest frame

Cached Collider and RigidBody in TCastleTransform

Now you don't need call FindBehavior every frame just get it by using cached pointers from TCastleTransform.

Some screenshots

Platformer game without writing any code:

obraz

TPP example:

obraz

FPS game:

obraz

More tips for TModularMovement

FPS - How To Use it:
- Player rigid body can rotate only in Y axis (horizontal), other axes
  should be blocked in rigid body
- Y is always up
- Friction in player collider should be 0 - with other friction values
  using stairs needs extra code like TStairsSupportByColliderCapsuleRadius,
  and can have other undesirable problems during contact, e.g. with walls
- Rotate player horizontal using angular velocity (do not change transform
  Rotation directly that leads to physics objects synchronization and
  can make your player can fall off the level - especially when it's done
  every frame) You can use TRotateRigidBody behavior for that purpose.
- Do not rotate player vertical - rotate camera. You can use TRotateCamera
  behavior for that.
- Do not change player translation every frame - use rigid body velocities/forces
- After adding TModularMovement add some movement modules e.g. TWalk3DSupport
- Do not afraid to change/add your own movement modules - this class is
  designed for that :)
- Camera should be rotated by pi in y axis for FPS movement
- See /examples/physics/physics_3d_shooter
- For mouse look use Container.StartMouseLook(Viewport); and Container.StopMouseLook;

TPP - How To Use:
- Player rigid body can rotate only in Y axis (horizontal), other axes
  should be blocked in rigid body
- Y is always up
- Friction in player collider should be 0 - with other friction values
  using stairs needs extra code like TStairsSupportByColliderCapsuleRadius,
  and can have other undesirable problems during contact, e.g. with walls
- Rotate player horizontal using angular velocity (do not change transform
  Rotation directly that leads to physics objects synchronization and
  can make your player can fall off the level - especially when it's done
  every frame) You can use TRotateRigidBody behavior for that purpose.
- For cammera following you can use TFollowingTargetForCamera behavior (add it
  to your camera )
- After adding TModularMovement add some movement modules e.g. TWalk3DSupport
- Do not afraid to change/add your own movement modules - this class is
  designed for that :)
- For mouse look use Container.StartMouseLook(Viewport); and Container.StopMouseLook;
- See /examples/physics/physics_3d_third_person

2D Platformer Game - How To Use:
- Player rigid body rotation should be blocked in all directions
- Player translation in Z axis should be blocked
- GravityStrength should be about 1200 (9.81 is good for 3D games)
- After adding TModularMovement add some movement modules e.g. TPlatformer2DWalkSupport
- Do not afraid to change/add your own movement modules - this class is
  designed for that :)
- See /examples/physics/physics_2d_movement

and3md added 30 commits June 12, 2023 14:19
michaliskambi added a commit that referenced this pull request Apr 22, 2025
…ody.PhysicsSphereCast

Adjusted from #533 , by Andrzej Kilijański
@michaliskambi
Copy link
Member

I've done some work to keep this up-to-date:

  • this is now synchronized with master
  • Kraft upgrade has been done in master (to even further Kraft commit, 2019-08-26-10-17-0000 -> 2025-03-10-04-42-0000, with all CGE adjustments merged) and is now used by this branch too
  • we have cherry-picked from this PR the PhysicsSphereCast and configuring layers for PhysicsRayCast
  • the usage of Collider / RigidBody shortcuts has been more synchronized with master.

Overall, this is up-to-date again, and the diff between this and master got smaller :)

@michaliskambi
Copy link
Member

I've done more fixes, to fix LPK and physics_3d_shooter lights.

TODOs:

  • Document in README the purpose of falling-out-of-level or remove it, if no purpose. If kept: rename to underscores and consistent with other samples in this dir, like physics_test_falling_out_of_level.

  • There are jumps when using mouse look on this branch, both with physical and non-physical navigation. Check interaction of mouse look changes with CASTLE_COLLECT_MOTION merged from master.

  • TCastleInputAxis needs TCastleInputBindind list, and thus https://castle-engine.io/roadmap#component_list . Or we must have an idea for upgrade later to this, if we merge with simple PositiveKey, NegativeKey now.

  • TCastleAbstractRootTransform.FocusedViewport and TCastleAbstractRootTransform.FocusedContainer are just placeholder implementations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants