-
Notifications
You must be signed in to change notification settings - Fork 0
Wall Climbing Example (Spider)
com.azure.azurecortex.example.spider.CortexSpiderEntity is the third bundled example, alongside the melee zombie
(Full Example Walkthrough) and the ranged skeleton
(Ranged Example Walkthrough (Skeleton)). It uses the same GOAP/behavior-tree
shape as those examples, but swaps in AzureCortex's crawl-aware navigation for live-target pursuit.
The important architectural point is still the same: wall crawling belongs mostly to the navigation/execution layer,
not the decision layer. The planner can still think in terms of WANDER, INVESTIGATE, and HUNT_TARGET; only the
movement branch that actually needs to climb has to care about crawl traversal.
The current 1.21.1 example differs from the original walkthrough in a few important ways:
- The spider now targets players and iron golems only under vanilla-like dark/night conditions.
-
CrawlToDestinationActionnow handles both crawl movement and ordinary ground movement itself. - Ground movement gets explicit low-step jumping instead of relying only on passive step height.
- Crawl routing can fall back to ordinary
AStarPathfinderwhen the ground route is better. - The crawl action turns the mob toward its horizontal movement direction.
- The crawl search accepts vertical/ceiling cling surfaces more consistently and has a larger search budget.
- The example spider has
STEP_HEIGHT = 1.5F/maxUpStep() = 1.5F. - The old custom
travel(Vec3)override was removed fromCortexSpiderEntity. - The example's crawl chase is intentionally slower and much quicker to declare itself stuck/repath.
The goal enum is deliberately ordinary:
public enum CortexSpiderGoal implements Goal {
NONE,
WANDER,
INVESTIGATE,
HUNT_TARGET;
@Override
public boolean isNone() {
return this == NONE;
}
}Nothing about this enum says "crawler" because crawling is not a planning concern. A crawler still wants to wander, investigate, or hunt just like a ground mob.
CortexSpiderGoalPlanner remains structurally similar to CortexSkeletonGoalPlanner:
- Hunt a valid live target.
- Otherwise investigate a recent sighting.
- Otherwise wander.
It also uses the same GoalFailureCooldowns / PlanFeedback flow as the other examples so repeated FAILED_STUCK or
FAILED_NO_PATH results can temporarily reduce the desirability of immediately retrying the same plan.
See GOAP Planning for the planner mechanics.
The current spider example no longer uses the broad players().or(ironGolems()) predicate. Its sensor is built from
the nighttime-aware helpers:
var validity = VanillaTargetPredicates.onlyPlayersAtNight()
.or(VanillaTargetPredicates.onlyGolemsAtNight());onlyPlayersAtNight() also rejects dead, creative, and spectator players. This keeps the example closer to vanilla
spider behavior without changing the planner itself: when no valid target is sensed, the normal investigate/wander
branches continue to work.
The high-level tree still looks like the other bundled examples:
return PrioritySelector.of(
new ActionNode<>(idle, 0),
new Condition<>(
(agent, bb, cd) -> bb.get(CommonBlackboardKeys.ACTIVE_GOAL_TYPE) == CortexSpiderGoal.WANDER,
new ActionNode<>(wander, 5)
),
new Condition<>(
(agent, bb, cd) -> bb.get(CommonBlackboardKeys.ACTIVE_GOAL_TYPE) == CortexSpiderGoal.INVESTIGATE,
new ActionNode<>(investigate, 8)
),
hunt
);WANDER and INVESTIGATE stay on the ordinary navigation path. HUNT_TARGET is the branch that uses the dedicated
crawl action.
InvestigateLastSeenTargetAction still uses AStarPathfinder.INSTANCE, but the spider supplies:
SpiderTraversalPredicates::standableForCrawlerThat does not magically make the investigate action climb. It simply avoids rejecting wall/ceiling-adjacent search positions too early. The actual climb-capable execution remains scoped to the chase action.
The spider has one melee attack profile and a crawl-aware chase action:
var chase = new CrawlToDestinationAction<CortexSpiderEntity, CortexSpiderGoal>(
CrawlTraversalEvaluator.INSTANCE,
0.35D,
1,
10,
5
);Those values currently mean:
- speed cap:
0.35D - arrival radius:
1 - minimum repath interval:
10ticks - stuck timeout:
5ticks
That short stuck timeout is intentional in the current example: if the direct execution stalls, the action fails fast so the planner/pathing flow can recover instead of leaving the spider pushing into a bad waypoint for several seconds.
The original version of this action was mostly "follow every crawl waypoint directly." The current version is more practical: it still follows the AzureCortex path waypoint-by-waypoint, but chooses the movement mode for each waypoint.
Each tick it determines whether the current waypoint is genuinely crawl-related using the crawl/traversal helpers. If
it is, and the agent can wall-crawl, the action enables crawling and uses computeWallCrawlVelocity(...). Otherwise it
uses its own ground-velocity path.
Conceptually:
var velocity = wallCrawling
? NavigationQueries.computeWallCrawlVelocity(agent, waypointCenter, speed)
: computeGroundVelocity(agent, waypointCenter, speed);The action then writes that velocity directly, marks the entity as having an impulse, and turns the mob toward its horizontal movement direction.
Because this action bypasses vanilla MoveControl, vanilla does not automatically rotate the mob toward the direction
it is moving. faceMovementDirection(...) now updates body/head yaw from the horizontal velocity so a crawler no
longer moves sideways or backwards while pursuing a target.
Purely vertical movement keeps the previous heading because there is no meaningful horizontal direction to face.
Crawl-aware A* is necessarily more expensive and has different costs from ordinary ground pathing. Uneven ground, hills, roots, and other mundane terrain can sometimes produce a weaker partial crawl path even though a plain walking route would work well.
For that reason, repathing now follows this pattern:
- Try
CrawlTraversalEvaluatorfirst, because only it can discover wall/ceiling routes. - If that route is empty or ends too far from the destination, try
AStarPathfinder.INSTANCE. - Keep the ground path when it reaches closer to the destination than the crawl path.
This makes the action a crawl-first hybrid rather than a crawler that insists on treating every trip like a wall traversal problem.
On ordinary ground waypoints, the action also detects a low obstruction immediately ahead. If the block at foot level is solid while the space above it is clear enough to step onto, the action supplies a jump impulse instead of waiting for a stuck timeout.
The test accounts for the mob's width rather than probing only a single center point. That matters for the spider's wide body: one side can be obstructed even when a narrow center-line probe looks clear.
The current crawl implementation also includes supporting pathfinding fixes:
- cling-surface checks include
UP, improving ceiling/contact handling; - crawl search budget was increased;
- partial-path selection is no longer rejected merely because the goal is vertically separated;
- climb-neighbor generation was adjusted to make crawl routes less likely to terminate early;
- ordinary A* received the same partial-path relaxation so the fallback can still return its best useful partial path.
These are pathfinding-layer changes; no special GOAP states are needed to benefit from them.
CortexSpiderEntity extends vanilla Spider primarily so the example can reuse vanilla's dimensions, attributes,
renderer/model/texture, and other normal spider bookkeeping while replacing its decision-making AI.
It implements:
-
CrawlCapability, backed by aCrawlState -
MovementCapability, for custom passable-solid/hazard rules
The example treats cobwebs as passable-solid and lava as a hazard fluid.
The current example raises step height:
public static AttributeSupplier.Builder createAttributes() {
return Spider.createAttributes().add(Attributes.STEP_HEIGHT, 1.5F);
}
@Override
public float maxUpStep() {
return 1.5F;
}This helps ordinary terrain traversal, while the action's explicit low-step jump handles the cases where manually applied velocity prevents vanilla step assist from being sufficient on its own.
Older versions of this walkthrough required CortexSpiderEntity#travel(Vec3) to special-case wall crawling and apply
getDeltaMovement() directly. The current example no longer contains that override.
Do not copy the old travel(Vec3) block from older versions of this wiki page into the current example. Movement
execution is now handled by the updated crawl action/controller flow instead.
The entity still updates crawl state/controller state around the AzureCortex runtime:
crawlState.tick();
CrawlController.updateWallCrawlingPhysics(this);
if (!level().isClientSide() && isAlive() && !isNoAi()) {
tickGoalPlanner();
runtime.tick();
CrawlController.updateCrawlOrientation(this, getDeltaMovement());
}The periodic hook keeps DESTINATION synchronized with the current live target while HUNT_TARGET is active.
Registration follows the same pattern as the zombie/skeleton examples:
- register the entity type and spawn egg;
- register
CortexSpiderEntity.createAttributes(); - use ordinary ground spawn placement rules;
- add the spawn egg to the desired creative tab;
- register vanilla
SpiderRenderer::newon the client; - provide the language and spawn-egg model resources.
No custom spider art assets are required by the bundled example.
- Decision layer: a crawler does not need crawler-specific goals merely because it can climb.
- Sensing layer: target predicates can independently reproduce vanilla-like conditions such as nighttime hostility.
-
Pathfinding layer: use
CrawlTraversalEvaluatorwhere climbing is genuinely required, but allow a plain A* ground route to win when it is better. -
Execution layer: crawl and ground waypoints need different velocity handling; the current
CrawlToDestinationActionhandles both and also supplies facing/step recovery. -
Capability layer:
CrawlCapability+CrawlStateexpose the synced crawl state whileMovementCapabilitydefines terrain-specific rules. -
Entity integration: the current example no longer needs the old custom
travel(Vec3)override.
- Wall Crawling — crawl capability, controller, orientation, and traversal reference.
- Ranged Example Walkthrough (Skeleton) — the ranged example whose planner/tree structure this one closely mirrors.
- Full Example Walkthrough — the basic melee/zombie integration.
-
Built-in Actions —
CrawlToDestinationAction,MoveToDestinationAction, and other reusable actions. - Navigation and Pathfinding — A*, incremental search, traversal evaluators, partial paths, and movement capability.