You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:35:50