Skip to content

Commit d97afee

Browse files
committed
refactor
1 parent 5ace616 commit d97afee

1 file changed

Lines changed: 1 addition & 214 deletions

File tree

NAVMESH_API.md

Lines changed: 1 addition & 214 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Defold Graph Pathfinder Extension - Navigation mesh pathfinding with polygon-bas
1212
- [Spatial Index](#spatial-index)
1313
- [Statistics](#statistics)
1414
- [Enumerations](#enumerations)
15-
- [Complete Example](#complete-example)
15+
1616

1717
---
1818

@@ -288,7 +288,6 @@ end
288288
- `agent_radius = 0`: No portal offsetting, path hugs walls
289289
- `agent_radius > 0`: Portals offset inward by radius, provides collision clearance
290290
- Narrow portals (< `agent_radius * collapse_threshold`) collapse to midpoint
291-
- Recommended: Set `agent_radius` to character's collision radius
292291

293292
### pathfinder.navmesh_cell_at_position()
294293

@@ -523,214 +522,6 @@ end
523522

524523
---
525524

526-
## Complete Example
527-
528-
Here's a complete example demonstrating navmesh pathfinding in a 3D game:
529-
530-
```lua
531-
-- navmesh_controller.script
532-
533-
go.property("navmesh_buffer", resource.buffer("/assets/level1.navmesh"))
534-
535-
local COLORS = {
536-
RED = vmath.vector4(1, 0, 0, 1),
537-
GREEN = vmath.vector4(0, 1, 0, 1),
538-
BLUE = vmath.vector4(0, 0, 1, 1)
539-
}
540-
541-
-- State
542-
local player_position = vmath.vector3()
543-
local target_position = vmath.vector3()
544-
local current_path = {}
545-
local path_length = 0
546-
local path_index = 1
547-
local grid = {}
548-
549-
-- Constants
550-
local MOVE_SPEED = 5.0
551-
local WAYPOINT_RADIUS = 0.5
552-
local AGENT_RADIUS = 0.5
553-
554-
-- Utility: Convert screen coordinates to world plane
555-
local function screen_to_world(camera_url, screen_x, screen_y)
556-
local PLANE_POINT = vmath.vector3(0, 0, 0)
557-
local PLANE_NORMAL = vmath.vector3(0, 1, 0)
558-
559-
local p0 = camera.screen_to_world(vmath.vector3(screen_x, screen_y, 0), camera_url)
560-
local p1 = camera.screen_to_world(vmath.vector3(screen_x, screen_y, 1), camera_url)
561-
562-
local dir = p1 - p0
563-
local denom = vmath.dot(PLANE_NORMAL, dir)
564-
if math.abs(denom) < 0.000001 then
565-
return nil
566-
end
567-
568-
local t = vmath.dot(PLANE_POINT - p0, PLANE_NORMAL) / denom
569-
if t < 0 then
570-
return nil
571-
end
572-
573-
return p0 + dir * t
574-
end
575-
576-
function init(self)
577-
msg.post(".", "acquire_input_focus")
578-
579-
-- Initialize navmesh system
580-
pathfinder.navmesh_init(
581-
600, -- max_cells
582-
6, -- max_edges_per_cell
583-
32, -- pool_block_size
584-
16, -- cache_size
585-
256, -- max_cache_path_length
586-
5, -- min_cell_size
587-
10, -- max_cell_size
588-
1000, -- max_grid_dim
589-
false -- debug
590-
)
591-
592-
-- Optional: Customize funnel tolerances
593-
pathfinder.navmesh_set_funnel(0.002, 0.1, 0.001)
594-
595-
-- Load navmesh from buffer
596-
local buffer = resource.get_buffer(self.navmesh_buffer)
597-
pathfinder.navmesh_set_buffer(buffer)
598-
599-
-- Get spatial index for visualization
600-
grid = pathfinder.navmesh_get_spatial_index()
601-
602-
-- Initialize player position
603-
player_position = go.get_position()
604-
605-
print("Navmesh initialized successfully")
606-
end
607-
608-
function final(self)
609-
pathfinder.navmesh_shutdown()
610-
end
611-
612-
function update(self, dt)
613-
-- Follow current path
614-
if path_index <= path_length then
615-
local waypoint = current_path[path_index]
616-
local target = vmath.vector3(waypoint.x, 0, waypoint.y)
617-
618-
-- Move towards waypoint
619-
local to_target = target - player_position
620-
local distance = vmath.length(to_target)
621-
622-
if distance < WAYPOINT_RADIUS then
623-
-- Reached waypoint, move to next
624-
path_index = path_index + 1
625-
else
626-
-- Move towards waypoint
627-
local direction = vmath.normalize(to_target)
628-
player_position = player_position + direction * MOVE_SPEED * dt
629-
go.set_position(player_position)
630-
end
631-
end
632-
633-
-- Draw current path
634-
draw_path(path_length, current_path)
635-
636-
-- Draw spatial index grid (for debugging)
637-
draw_spatial_grid(grid)
638-
639-
-- Display stats periodically
640-
self.stats_timer = (self.stats_timer or 0) + dt
641-
if self.stats_timer >= 1.0 then
642-
self.stats_timer = 0
643-
local stats = pathfinder.navmesh_get_stats()
644-
print(string.format("Cache: %d/%d, Hit Rate: %d%%",
645-
stats.path_cache.cache_entries,
646-
stats.path_cache.cache_capacity,
647-
stats.path_cache.cache_hit_rate))
648-
end
649-
end
650-
651-
function on_input(self, action_id, action)
652-
if action_id == hash("mouse_click") and action.pressed then
653-
-- Get world position from click
654-
local world_pos = screen_to_world(msg.url("/camera#camera"), action.x, action.y)
655-
if not world_pos then
656-
return
657-
end
658-
659-
target_position = world_pos
660-
661-
-- Find path from player to target
662-
local length, status, status_text, path = pathfinder.navmesh_find_path(
663-
player_position.x, -- start_x
664-
player_position.z, -- start_y (using Z for 3D)
665-
target_position.x, -- goal_x
666-
target_position.z, -- goal_y
667-
128, -- max_path_length
668-
AGENT_RADIUS, -- agent_radius
669-
true -- enable_fallback
670-
)
671-
672-
if status == pathfinder.PathStatus.SUCCESS then
673-
print("Path found with", length, "waypoints")
674-
current_path = path
675-
path_length = length
676-
path_index = 1
677-
elseif status == pathfinder.PathStatus.SUCCESS_START_FALLBACK then
678-
print("Path found (start position corrected)")
679-
current_path = path
680-
path_length = length
681-
path_index = 1
682-
elseif status == pathfinder.PathStatus.SUCCESS_GOAL_FALLBACK then
683-
print("Path found (goal position corrected)")
684-
current_path = path
685-
path_length = length
686-
path_index = 1
687-
elseif status == pathfinder.PathStatus.ERROR_NO_PATH then
688-
print("No path exists to target")
689-
else
690-
print("Pathfinding failed:", status_text)
691-
end
692-
end
693-
end
694-
695-
-- Draw path as connected lines
696-
function draw_path(length, path)
697-
for i = 1, length - 1 do
698-
local from_node = path[i]
699-
local to_node = path[i + 1]
700-
msg.post("@render:", "draw_line", {
701-
start_point = vmath.vector3(from_node.x, 0, from_node.y),
702-
end_point = vmath.vector3(to_node.x, 0, to_node.y),
703-
color = COLORS.GREEN
704-
})
705-
end
706-
end
707-
708-
-- Draw spatial index grid
709-
function draw_spatial_grid(grid)
710-
if grid.vertical then
711-
for _, line in ipairs(grid.vertical) do
712-
msg.post("@render:", "draw_line", {
713-
start_point = line.start_position,
714-
end_point = line.end_position,
715-
color = vmath.vector4(1, 0, 0, 0.2) -- Semi-transparent red
716-
})
717-
end
718-
end
719-
720-
if grid.horizontal then
721-
for _, line in ipairs(grid.horizontal) do
722-
msg.post("@render:", "draw_line", {
723-
start_point = line.start_position,
724-
end_point = line.end_position,
725-
color = vmath.vector4(1, 0, 0, 0.2) -- Semi-transparent red
726-
})
727-
end
728-
end
729-
end
730-
```
731-
732-
---
733-
734525
## Performance Tips
735526

736527
### Cache Configuration
@@ -763,11 +554,7 @@ pathfinder.navmesh_init(
763554
- **Medium meshes** (200-500 cells): `pool_block_size = 64`
764555
- **Large meshes** (>500 cells): `pool_block_size = 128`
765556

766-
### Agent Radius
767557

768-
- Set to character's collision radius for realistic clearance
769-
- Increase for safety margin (e.g., 1.2× collision radius)
770-
- Use 0 only if characters can move exactly along walls
771558

772559
### Fallback Strategy
773560

0 commit comments

Comments
 (0)