跳转至

3D 表面材质查询

本页覆盖 GFSurfaceUtility 的碰撞 face 到 Mesh surface 或材质映射。它只提供查询和缓存,不内置脚步声、弹孔、命中特效或地形标签规则。

3D 表面材质查询 (GFSurfaceUtility)

应用场景: 当 RayCast3D 命中了 ConcavePolygonShape3D 或由 Mesh 生成的碰撞面,你拿到的是 face index,但脚步声、弹孔、命中特效等通常想按 Mesh surface 或材质分发。

var surfaces := Gf.get_utility(GFSurfaceUtility) as GFSurfaceUtility
var face_index := ray_cast.get_collision_face_index()
var collider := ray_cast.get_collider()

var material := surfaces.get_active_material(collider, face_index)
var surface_index := surfaces.get_surface_index(collider, face_index)

需要一次拿到 surface、基础材质、override 材质和最终 active material 时,可以使用报告入口:

var hit := surfaces.describe_surface_hit(collider, face_index)
if hit.ok:
    var material_name := hit.active_material_name
    var material_path := hit.active_material_path
    var index := hit.surface_index

GFSurfaceUtility 会尝试从命中的 MeshInstance3D、父节点、子节点或相邻节点解析 Mesh,并缓存每个 surface 的 face 数量。它只完成 face 到 surface/material 的映射,不内置“泥地”“金属”“水面”等业务标签。

需要先检查 Mesh 自身结构时,可以使用 describe_mesh()

var layout := surfaces.describe_mesh(mesh_instance)
if layout.ok:
    for surface in layout.surfaces:
        print(surface.surface_index, surface.primitive_name, surface.face_count)

该报告只描述 surface 数量、顶点数、索引数、三角面数、AABB 和材质摘要,不修改 Mesh、不创建碰撞体,也不生成项目节点。导入预检、编辑器工具和运行时调试面板可以读取这些纯数据,再由项目自行决定是否提示、修复或拒绝资源。

get_base_material() 返回 Mesh surface 上的基础材质,get_surface_override_material() 返回 MeshInstance3D 的 surface override,get_active_material() 返回 Godot 最终用于渲染的 active material。缓存以 Mesh RID 为键;默认 cache_modeAUTOMATIC,会按 auto_cache_size 做自动裁剪。需要避免首次命中时计算 surface 面数,可在加载阶段调用 cache_mesh_surface(mesh_or_mesh_instance) 预热;需要完全手动管理时可切到 MANUAL,需要排查动态 Mesh 变化时可切到 DISABLED。运行时替换 Mesh 或动态修改 surface 结构后,可调用 erase_cached_mesh()clear_cache() 重新计算。

describe_surface_hit() 返回 okreasonface_indexsurface_index,以及 base_materialoverride_materialactive_material 三组 JSON-safe 资源摘要、存在标记、资源名、资源路径和类型。日志、诊断或持久化场景通常读取 *_material_name*_material_pathface_indexsurface_index 这类纯数据;运行时分发如果需要真实材质对象,应使用 get_base_material()get_surface_override_material()get_active_material()