{"id":33583068,"url":"https://github.com/antoinecharruel/interactive_grid_gdextension","last_synced_at":"2026-02-08T07:30:24.033Z","repository":{"id":320090846,"uuid":"1068518168","full_name":"antoinecharruel/interactive_grid_gdextension","owner":"antoinecharruel","description":"InteractiveGrid is a Godot GDExtension that allows player interaction with a 3D grid, including cell selection, pathfinding, and hover highlights.","archived":false,"fork":false,"pushed_at":"2026-02-01T14:31:32.000Z","size":299349,"stargazers_count":62,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-02-01T23:49:56.853Z","etag":null,"topics":["gdextention","godot","godot-engine","grid","grid-based","grid-based-strategy","inventory","pathfinding","turn-based"],"latest_commit_sha":null,"homepage":"https://godotengine.org/asset-library/asset/4372","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antoinecharruel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-02T14:01:15.000Z","updated_at":"2026-02-01T14:11:54.000Z","dependencies_parsed_at":"2025-10-21T23:25:56.902Z","dependency_job_id":null,"html_url":"https://github.com/antoinecharruel/interactive_grid_gdextension","commit_stats":null,"previous_names":["antoinecharruel/interactive_grid_gdextension"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/antoinecharruel/interactive_grid_gdextension","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoinecharruel%2Finteractive_grid_gdextension","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoinecharruel%2Finteractive_grid_gdextension/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoinecharruel%2Finteractive_grid_gdextension/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoinecharruel%2Finteractive_grid_gdextension/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antoinecharruel","download_url":"https://codeload.github.com/antoinecharruel/interactive_grid_gdextension/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoinecharruel%2Finteractive_grid_gdextension/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29224437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T06:05:31.539Z","status":"ssl_error","status_checked_at":"2026-02-08T05:58:33.853Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gdextention","godot","godot-engine","grid","grid-based","grid-based-strategy","inventory","pathfinding","turn-based"],"created_at":"2025-11-29T03:09:18.200Z","updated_at":"2026-02-08T07:30:24.028Z","avatar_url":"https://github.com/antoinecharruel.png","language":"C++","funding_links":["https://www.patreon.com/c/vivensoft/","https://ko-fi.com/antoinecharruel"],"categories":[],"sub_categories":[],"readme":"[![Interactive Grid GDExtension Godot Asset Library page](https://img.shields.io/static/v1?logo=godotengine\u0026label=Interactive%20Grid%20GDExtension\u0026color=478CBF\u0026message=Latest)](https://godotengine.org/asset-library/asset/4372)\n![GitHub Downloads](https://img.shields.io/github/downloads/antoinecharruel/interactive_grid_gdextension/total)\n[![Patreon](https://img.shields.io/badge/Patreon-Vivensoft-F96854?logo=patreon\u0026logoColor=white)](https://www.patreon.com/c/vivensoft/)  \n[![Ko-fi](https://img.shields.io/badge/Ko--fi-AntoineCharruel-FF5E5B?logo=ko-fi\u0026logoColor=white)](https://ko-fi.com/antoinecharruel)\n[![Vivensoft on Itch.io](https://img.shields.io/badge/Itch.io-Vivensoft-FF5E5B?logo=itch.io\u0026logoColor=white)](https://vivensoft.itch.io/)\n[![Instagram](https://img.shields.io/badge/Instagram-VSFT%20GameDev-E4405F?logo=instagram\u0026logoColor=white)](https://www.instagram.com/vsftgamedev/)\n[![Join the Discord](https://img.shields.io/static/v1?logo=discord\u0026label=Discord\u0026color=7289DA\u0026message=Vivensoft)](https://discord.gg/hZb9PGrrt9)\n[![YouTube](https://img.shields.io/static/v1?logo=youtube\u0026label=YouTube\u0026color=FF0000\u0026message=antoinecharruel)](https://www.youtube.com/@antoinecharruel)\n\n# Interactive Grid GDExtension\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/docs/thumbnail/thumbnail_300x300px.png\"/\u003e\n\u003c/p\u003e\n\nInteractiveGrid is a Godot GDExtension that allows player interaction with a 3D grid, including cell selection, pathfinding, and hover highlights.\n\nNote: To use this plugin, simply download it and add the 'addons' folder to your Godot project's root directory. You don't have to enable it in the plugins menu.\n\n## Features\n\n- Select individual cells.\n\n- Detect obstacles.\n\n- Align cells with the floor.\n\n- Calculate paths from a global position to selected cells using AStar2D.\n\n- Choose movement type: 4 directions, 6 directions, 8 directions.\n\n- Customize the grid from the editor: grid size, cell size, mesh, colors, and shaders.\n\n- High performance using [MultiMeshInstance3D](https://docs.godotengine.org/en/4.4/classes/class_multimeshinstance3d.html) for efficient rendering of multiple cells.\n\n[![](/docs/preview/screenshot_003.png)]()\n\n![](/docs/preview/demo.gif)\n\u003cdiv style=\"text-align:center;\"\u003e\n  \u003ca href=\"https://ahappypapabear.itch.io/interactive-grid-gdextension\" target=\"_blank\" style=\"text-decoration:none;background-color:#28a745;color:white;padding:5px 12px;border-radius:5px;\"\u003e\n    🎮 Play on Itch.io\n  \u003c/a\u003e\n\u003c/div\u003e\n\n[![](/docs/youtube/image_with_play_button.png)](https://www.youtube.com/watch?v=L6V0UsJYBfg)\n\n## Compatibility:\n\n- Fully compatible with Godot 4.5.\n- Cross-platform support (Linux, Windows, macOS, Android, iOS, Web/HTML5).\n\n## Itch.io Page 🎮\n\n[![](docs/itch_io/logo/logo.png)](https://vivensoft.itch.io/interactive-grid-gdextension)\n\n[![InteractiveGrid on Itch.io](https://img.shields.io/badge/Itch.io-InteractiveGrid-FF5E5B?logo=itch.io\u0026logoColor=white)](https://vivensoft.itch.io/interactive-grid-gdextension)\n\n## Online Documentation and Tutorial\n\n[![](/docs/preview/online_documentation_preview.png)](https://antoinecharruel.github.io/godot-gdextension-docs/interactive-grid/interactive-grid-3d.html)\n\n[![InteractiveGrid GDExtension](https://img.shields.io/static/v1?logo=godotengine\u0026label=Interactive%20Grid%20GDExtension\u0026color=478CBF\u0026message=Online%20Documentation)](https://antoinecharruel.github.io/godot-gdextension-docs/interactive-grid/interactive-grid-3d.html)\n\n## Demo GDScript Example\n\n```python\n# interactive_grid_3d.gd\n\nextends InteractiveGrid3D\n\n@onready var ray_cast_from_mouse: RayCast3D = $\"../RayCastFromMouse\"\n\nvar _path: PackedInt64Array = []\nvar _pawn: CharacterBody3D = null\nvar _show_grid: bool = false\n\n@onready var debug_collision_shape_area_3d: CollisionShape3D = $\"../DebugCollisionShapeArea3D/DebugCollisionShapeArea3D\"\n\nfunc _ready() -\u003e void:\n\t_show_grid = false\n\n\nfunc _process(delta: float) -\u003e void:\n\t\n\tif _show_grid == false and self.visible:\n\t\tself.set_visible(false)\n\t\t\n\tif self.get_selected_cells().is_empty():\n\t\tself.highlight_on_hover(ray_cast_from_mouse.get_ray_intersection_position())\n\telse:\n\t\tmove_along_path(_path)\n\n\nfunc show_grid():\n\t#region InteractiveGrid3D Center\n\t## Here, the grid is centered around the player.\n\t## !Note: This operation repositions all cells, aligns them with the environment,\n\t## rescans obstacles and custom data, and refreshes A* navigation.\n\t##  - Manual modifications can also be applied here, such as:\n\t##     - Hiding cells beyond a certain distance\n\t##     - compute_unreachable_cells\n\t##     - Adding custom data\n\t#endregion\n\t\n\tif _pawn == null:\n\t\treturn\n\n\tif not self.is_created():\n\t\treturn\n\t\t\t\t\n\tprint(\"show_grid\")\n\t_show_grid = true\n\n\t_path = []\n\tself.set_visible(true)\n\tself.center(_pawn.global_position)\n\n\tvar pawn_current_cell_index: int = self.get_cell_index_from_global_position(_pawn.global_position)\n\n\t# To prevent the player from getting stuck.\n\tself.set_cell_accessible(pawn_current_cell_index, true)\n\tself.set_cell_reachable(pawn_current_cell_index, true)\n\n\tself.hide_distant_cells(pawn_current_cell_index, 6)\n\tself.compute_unreachable_cells(pawn_current_cell_index)\n\t\n\tvar cell_global_xform: Transform3D = get_cell_global_transform(pawn_current_cell_index)\n\tvar offset:Vector3 = get_cell_shape_offset()\n\tvar offset_xform:Transform3D = Transform3D(Basis.IDENTITY, offset)\n\tdebug_collision_shape_area_3d.global_transform = cell_global_xform * offset_xform\n\t\n\tvar neighbors: PackedInt64Array = self.get_neighbors(pawn_current_cell_index)\n\tfor neighbor_index in neighbors:\n\t\tself.add_custom_cell_data(neighbor_index, \"CFL_NEIGHBORS\")\n\n\tself.add_custom_cell_data(pawn_current_cell_index, \"CFL_PLAYER\")\n\n\t#region update_custom_data()\n\t## !Note: Don't forget to call update_custom_data().\n\t## It refreshes custom_cell_flags, colors, and the A* configuration\n\t## based on the newly updated CellCustomData.\n\t#endregion\n\tself.update_custom_data()\n\n\nfunc _input(event):\n\tif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:\n\t\tif _pawn == null:\n\t\t\treturn\n\n\t\tvar ray_pos: Vector3 = ray_cast_from_mouse.get_ray_intersection_position()\n\t\tif ray_pos == null:\n\t\t\treturn\n\n\t\tvar selected_cells: Array = self.get_selected_cells()\n\t\tif selected_cells.size() \u003c 1:\n\t\t\tvar hit_cell_index: int = self.get_cell_index_from_global_position(ray_pos)\n\t\t\tself.select_cell(hit_cell_index)\n\t\t\tselected_cells = self.get_selected_cells()\n\t\t\tif selected_cells.is_empty():\n\t\t\t\treturn\n\n\t\t\tvar pawn_current_cell_index: int = self.get_cell_index_from_global_position(_pawn.global_position)\n\t\t\tself.set_cell_accessible(pawn_current_cell_index, true)\n\t\t\t_path = self.get_path(pawn_current_cell_index, selected_cells[0])\n\t\t\tprint(\"Last selected cell:\", self.get_latest_selected())\n\t\t\tprint(\"Path:\", _path)\n\t\t\tself.highlight_path(_path)\n\n\nfunc move_along_path(path: PackedInt64Array)-\u003e void:\n\tif path.is_empty():\n\t\tshow_grid()\n\t\treturn\n\n\tvar target_cell_index: int = path[0]\n\tvar target_global_position: Vector3 = get_cell_global_position(target_cell_index)\n\tif not is_on_target_cell(_pawn.global_position, target_global_position, 0.20):\n\t\treaching_cell_target(target_cell_index)\n\telse:\n\t\ttarget_cell_reached()\n\n\nfunc reaching_cell_target(target_cell_index: int) -\u003e void:\n\tif _path.size() \u003e 0:\n\t\tvar target_cell_global_position: Vector3 = self.get_cell_global_position(target_cell_index)\n\t\tif _pawn.has_method(\"move_to\"):\n\t\t\t_pawn.move_to(target_cell_global_position)\n\t\telse:\n\t\t\tprinterr(\"pawn does not have the 'move_to' method.\")\n\n\nfunc target_cell_reached():\n\tif not _path.is_empty():\n\t\t_path.remove_at(0)\n\n\nstatic func is_on_target_cell(current_global_position: Vector3, target_global_position: Vector3, threshold: float) -\u003e bool:\n\treturn current_global_position.distance_to(target_global_position) \u003c= threshold\n\n\nfunc set_pawn(pawn: CharacterBody3D):\n\t_pawn = pawn\n```\n\nMore information about scripting the interactive 3D grid:  \n[Interactive Grid Scripting](https://antoinecharruel.github.io/godot-gdextension-docs/interactive-grid/tutorial-interactive-grid-3d.html#interactive-grid-scripting)\n\n## Use Cell Flags via Alpha Channel to Modify Cell Shader at Runtime\n\n```python\n// interractive_grid.gdshader\n\nshader_type spatial;\nrender_mode unshaded, cull_disabled, depth_draw_opaque;\n\nvarying vec4 instance_c;\nvarying vec4 instance_c_default;\nvarying float alpha;\n\n// Default cell flags:\nconst int CFL_ACCESSIBLE = 1 \u003c\u003c 0;\nconst int CFL_REACHABLE = 1 \u003c\u003c 1;\nconst int CFL_IN_VOID = 1 \u003c\u003c 2;\nconst int CFL_HOVERED = 1 \u003c\u003c 3;\nconst int CFL_SELECTED  = 1 \u003c\u003c 4;\nconst int CFL_PATH = 1 \u003c\u003c 5;\nconst int CFL_VISIBLE = 1 \u003c\u003c 6;\n\n// Custom cell data:\nconst int CFL_PLAYER = 1 \u003c\u003c 7;\nconst int CFL_NEIGHBORS = 1 \u003c\u003c 9;\nconst int CFL_TRAP = 1 \u003c\u003c 10;\nconst int CFL_PULSE = 1 \u003c\u003c 8;\n\nvec3 pulse_color(vec3 base_color, float speed, float min_val, float max_val) {\n   float center = (min_val + max_val) * 0.5;\n   float range  = (max_val - min_val) * 0.5;\n   return base_color * (sin(TIME * speed) * range + center);\n}\n\nvoid vertex() {\n   instance_c = INSTANCE_CUSTOM;\n   int cell_flag = int(instance_c.a);\n   alpha = 0.5;\n\n   if ((cell_flag \u0026 CFL_ACCESSIBLE) == 0) {\n      alpha = 0.20;\n   }\n\n   if ((cell_flag \u0026 CFL_NEIGHBORS) != 0\n      \u0026\u0026 (cell_flag \u0026 CFL_PATH) == 0\n      \u0026\u0026 (cell_flag \u0026 CFL_TRAP) == 0)\n      {\n         if ((cell_flag \u0026 CFL_ACCESSIBLE) != 0) {\n            alpha = 0.40;\n            instance_c.r = 0.2;\n            instance_c.g = 0.5;\n            instance_c.b = 1.0;\n         }\n      }\n\n   if ((cell_flag \u0026 CFL_PATH) != 0) {\n      VERTEX.y += sin(TIME * 4.0 + VERTEX.x * 2.0) * 0.2;\n   }\n\n   if ((cell_flag \u0026 CFL_HOVERED) != 0) {\n      VERTEX.y += sin(TIME * 4.0) * 0.2;\n   }\n\n   if ((cell_flag \u0026 CFL_TRAP) != 0) {\n      VERTEX.y += sin(TIME * 4.0 + VERTEX.x * 2.0) * 0.2;\n   }\n\n   if ((cell_flag \u0026 CFL_PULSE) != 0) {\n      instance_c.rgb = pulse_color(vec3(instance_c.rgb), 4.0, 0.3, 0.8);\n   }\n\n   if ((cell_flag \u0026 CFL_VISIBLE) == 0) {\n      alpha = 0.0; // invisible\n   }\n\n   if ((cell_flag \u0026 CFL_REACHABLE) == 0) {\n      alpha = 0.0; // invisible\n   }\n\n   if ((cell_flag \u0026 CFL_IN_VOID) != 0) {\n      alpha = 0.0; // invisible\n   }\n}\n\nvoid fragment() {\n   if (alpha == 0.0) {\n      discard;\n   }\n   ALBEDO = instance_c.rgb;\n   EMISSION = instance_c.rgb;\n   ALPHA = alpha;\n}\n```\n\nFor details on customizing shaders for the interactive 3D grid, see:  \n[Add Custom Shader](https://antoinecharruel.github.io/godot-gdextension-docs/interactive-grid/tutorial-interactive-grid-3d.html#add-custom-shader)\n\n\n## Use different layouts: square and hexagonal\n\n![Square layout](/docs/preview/square_layout.png)\n![Hexagonal layout](/docs/preview/hexagonal_layout.png)\n\n## Need Help, Found an Issue, or Want to Share Your Work? 🛠️🎨\n\nIf you encounter any issues, have questions, want to share your project using Interactive Grid, or give feedback, feel free to reach out on Discord:\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://discord.gg/hZb9PGrrt9\"\u003e\n    \u003cimg src=\"https://img.shields.io/static/v1?logo=discord\u0026label=Discord\u0026color=7289DA\u0026message=Vivensoft\" alt=\"Join the Discord\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n## Assets and Resources Used\n\n- Kenney. Nature Kit · Kenney. https://kenney.nl/assets/nature-kit\n- Character movement in 3D | GDQuest Library. https://www.gdquest.com/library/character_movement_3d_platformer/#create-a-3d-character-controller-in-godot-4\n\n## References (Videos \u0026 Websites)\n\n- BornCG. (2024, August 4). Godot 4 3D Platformer Lesson #13: Align Player with Ground! [Video]. YouTube. https://www.youtube.com/watch?v=Y5OiChOukfg\n- jitspoe. (2022, May 11). Godot 3D Spatial Shaders: Getting started [Video]. YouTube. https://www.youtube.com/watch?v=6-eIEFPcvrU\n- jmbiv. (2021, October 5). How to make a 3D hexagon grid in Godot\n        (Tutorial) [Video]. YouTube. \n\t\thttps://www.youtube.com/watch?v=3Lt2TfP8WEw\n- Patel, A. J. (2013). Hexagonal grids. \n  \t   https://www.redblobgames.com/grids/hexagons/#neighbors\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantoinecharruel%2Finteractive_grid_gdextension","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantoinecharruel%2Finteractive_grid_gdextension","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantoinecharruel%2Finteractive_grid_gdextension/lists"}