如何用GDNative Godot API创建Mesh?godot-rust调用Mesh::new()报错
问题分析与解决
为什么Mesh::new()无法调用?
Mesh是Godot中的抽象基类,本身不能直接实例化,只有它的具体子类(比如ArrayMesh、PrimitiveMesh)才实现了Instanciable trait,支持直接创建实例。这就是编译器报错the trait bound 'Mesh: Instanciable' is not satisfied的根本原因,而SurfaceTool是具体工具类,所以可以正常用SurfaceTool::new()创建。
正确的网格创建流程
在godot-rust中创建网格的标准流程是:
- 用SurfaceTool构建顶点、索引等网格数据
- 将SurfaceTool的数据提交到可实例化的Mesh子类(比如ArrayMesh)
- 创建MeshInstance节点,把Mesh赋值给它,再添加到场景树中显示
修正后的代码
首先要修正代码里的两个核心错误:mesh_instance的类型应该是MeshInstance(而非Mesh,MeshInstance才是负责渲染网格的节点),然后替换Mesh::new()为具体子类的实例化逻辑:
use gdnative::{prelude::*, api::{StaticBody, ArrayMesh, SurfaceTool, MeshInstance}}; fn init(handle: InitHandle) { handle.add_class::<Chunk>(); } godot_init!(init); struct Block; #[derive(NativeClass)] #[inherit(StaticBody)] pub struct Chunk { blocks: Vec<Block>, st: Ref<SurfaceTool, Unique>, mesh: Option<Ref<ArrayMesh, Unique>>, mesh_instance: Option<Ref<MeshInstance, Shared>>, } impl Chunk { fn new(_base: &StaticBody) -> Self { let blocks = Vec::new(); let st = SurfaceTool::new(); let mesh = None; let mesh_instance = None; Chunk { blocks, st, mesh, mesh_instance } } fn update(&mut self, #[base] base: &StaticBody) { // 清理旧的MeshInstance if let Some(instance) = self.mesh_instance.take() { unsafe { instance.call_deferred("queue_free", &[]); } } // 用SurfaceTool构建网格数据(示例:创建一个平面) let mut st = self.st.borrow_mut(); st.begin(ArrayMesh::PRIMITIVE_TRIANGLES); // 添加四个顶点 st.add_vertex(Vector3::new(-1.0, 0.0, -1.0)); st.add_vertex(Vector3::new(1.0, 0.0, -1.0)); st.add_vertex(Vector3::new(1.0, 0.0, 1.0)); st.add_vertex(Vector3::new(-1.0, 0.0, 1.0)); // 添加索引,组成两个三角形 st.add_index(0); st.add_index(1); st.add_index(2); st.add_index(0); st.add_index(2); st.add_index(3); // 创建ArrayMesh并提交SurfaceTool的数据 let mesh = ArrayMesh::new(); st.commit(&mesh); self.mesh = Some(mesh); // 创建MeshInstance并挂载到父节点 let mesh_instance = MeshInstance::new(); mesh_instance.set_mesh(self.mesh.as_ref().unwrap()); base.add_child(mesh_instance, false); self.mesh_instance = Some(mesh_instance.claim()); } } #[methods] impl Chunk { #[method] fn _ready(&mut self, #[base] base: &StaticBody) { godot_print!("Hello World from StaticBody {}!", base.to_string()); // 在_ready中触发网格生成 self.update(base); } }
关键修正点
- 把抽象类
Mesh替换为可实例化的ArrayMesh,用ArrayMesh::new()创建实例 - 修正
mesh_instance的类型为MeshInstance,这是场景中负责渲染网格的节点类型 - 补充SurfaceTool构建网格数据的示例,通过
st.commit(&mesh)将数据写入ArrayMesh - 添加了MeshInstance挂载到父节点的逻辑,确保网格能在场景中显示
内容的提问来源于stack exchange,提问作者NaniNoni
相关产品推荐
相关产品推荐

