Movement & Pathfinding
Controlling movement or making entities move by pathfinding is critical to many types of games. The HYTOPIA SDK exposes a number of building block primitives you can use to create your own movement logic and pathfinding systems.
Important Building Blocks & Primitives
Below are the most frequently used building blocks and primitives when creating movement and pathfinding logic for entities.
SimpleCharacterController
The first building block that's best suited for relatively simple pathfinding is the Movement & Pathfinding. This entity controller implements basic movement and facing functions to create realistic movement behaviors with defined speeds.
RigidBody
All entities inherit from the RigidBody class. Rigid bodies have a number of physics properties and controls that are necessary for creating custom movement and pathfinding logic. This means, any property or method that the RigidBody class has, an Entity does as well.
We recommend you look through the RigidBody API Reference here to see a full list of available properties and methods.
ChunkLattice
If you're creating more complex pathfinding, you'll likely want to iterate the nearby terrain state of the world to determine the path an entity should take for it's movement. You can use a world's chunk lattice for this. The chunk lattice is useful for retrieving the chunks near an entity, or seeing if specific coordinates have a block set or not, or what kind of block is set. Learn more about the ChunkLattice.
Basic Waypoint Movement Example
We can create some basic movement behavior by providing a set of waypoints our entity will move through. The SimpleCharacterController used will take the most immediate path to the next target waypoint, colliding and potentially being stopped by any terrain or entities in the way. This is simple, dumb movement in this case.
// ... other code
let targetWaypointIndex = 0;
const WAYPOINT_COORDINATES = [
{ x: -5, y: 1, z: -7 },
{ x: 15, y: 1, z: 10 },
{ x: 17, y: 1, z: -12 },
];
const cow = new Entity({
controller: new SimpleEntityController(),
modelUri: 'models/npcs/cow.gltf',
modelScale: 0.7,
modelLoopedAnimations: [ 'walk' ],
modelAnimationsPlaybackRate: 1.6, // roughly match the animation speed to the move speed we'll use
rigidBodyOptions: {
enabledRotations: { x: false, y: true, z: false }, // prevent flipping over when moving
},
});
// We want to face towards the target each tick, since our relative position
// to the target may change as we move from a previous waypoint to the next.
cow.on(EntityEvent.TICK, () => {
if (targetWaypointIndex >= WAYPOINT_COORDINATES.length) {
return; // reached final waypoint, no need to rotate
}
// continually face towards target as we move
const controller = cow.controller as SimpleEntityController;
const targetWaypoint = WAYPOINT_COORDINATES[targetWaypointIndex];
controller.face(targetWaypoint, 5);
});
cow.spawn(world, { x: 0, y: 3, z: 0 });
// Pathfind to the next waypoint as we reach each waypoint
const pathfind = () => {
if (targetWaypointIndex >= WAYPOINT_COORDINATES.length) {
cow.stopModelAnimations(['walk']);
cow.startModelLoopedAnimations(['idle']);
return; // reached final waypoint, no need to pathfind
}
const controller = cow.controller as SimpleEntityController;
const targetWaypoint = WAYPOINT_COORDINATES[targetWaypointIndex];
// Makes the controlled entity, the cow, start moving towards the waypoint
// It will automatically handle it's own internal tick for movement.
controller.move(targetWaypoint, 3, {
moveCompleteCallback: () => {
// pathfind to next waypoint
targetWaypointIndex++;
pathfind();
},
moveIgnoreAxes: { x: false, y: true, z: false }, // ignore our y position when considering if movement is complete
});
};
pathfind();
Here's what our movement for our cow looks like!
Complex A* Pathfinding
The HYTOPIA SDK provides an out of the box, generalized and configurable Pathfinding Entity Controller that can be used to implement pathfinding that takes complex obstacles and terrain into consideration when moving to a target entity or position.
We recommend you take a look at the pathfinding entity example in the SDK to see an up to date example of how you can implement the PathfindingEntityController for your own entities.
Last updated