Rust是一种系统级编程语言,其设计目标是提供内存安全、并发性和高性能的解决方案。以下是使用Rust开发游戏的一些优势:
总之,Rust是一种非常有前途的编程语言,它的内存安全性、并发性和高性能使得它在开发游戏应用时非常有优势。
由于Rust是一个较新的编程语言,传统的游戏引擎很少使用。
Unity游戏引擎的引擎层是用C++编写,并使用C#作为游戏的编程语言。C++没有Rust的内存安全性,而C#运行时需要持续运行后台的GC线程,不如Rust的运行性能高效。
Unreal游戏引擎的引擎层和游戏都使用C++编写,也没有Rust的内存安全性。
Bevy游戏引擎是由Rust编写的,但是目前没有官方的编辑器,开发游戏相对较麻烦。
因此我写了一个由Rust编写的Steel游戏引擎。
Steel游戏引擎是我为了学习Rust语言和Vulkan渲染而写的。Steel的目标是开源,简单,模块化,高性能,跨平台和自带编辑器:
为了实现这些目标,接下来详细分析Steel引擎技术。
一般游戏基本架构可以分为GameObject架构和ECS架构。GameObject架构是面向对象编程,而ECS架构是面向数据编程。
ECS(Entity Component System)架构是一种软件设计模式,用于组织和管理游戏或应用程序中的实体(Entity)、组件(Component)和系统(System)。在ECS架构中,实体代表游戏或应用程序中的对象或角色,组件代表实体的属性或特征,而系统负责处理和更新组件。
相对于GameObject架构,ECS架构具有以下优势:
总之,ECS架构是一种软件设计模式,用于组织和管理游戏或应用程序中的实体、组件和系统。相对于GameObject架构,ECS架构具有更好的数据管理、更高的性能、更容易的扩展、更高的代码复用性和更简单的游戏开发等优势。
因此Steel游戏引擎使用ECS架构实现。Rust有很多开源的ECS框架,其中shipyard是功能非常完整,API非常的简洁的ECS实现。Steel引擎选用shipyard作为ECS架构的实现。
Vulkan是一种现代的图形API,旨在提供高效、低开销的图形渲染,适用于游戏、虚拟现实和增强现实等应用。以下是Vulkan的一些优势:
总之,Vulkan是一种现代的图形API,旨在提供高效、低开销的图形渲染,适用于游戏、虚拟现实和增强现实等应用。Vulkan具有低开销、高级控制、跨平台、多线程和可扩展性等优势。
然而Vulkan的API是非常繁琐的,需要写大量的模板代码,增加维护成本,提升程序复杂度。幸好Rust有一个包装了Vulkan的开源库vulkano。vulkano是一个Vulkan的safe包装,去掉了对Vulkan的unsafe调用,极大简化了Vulkan的代码,并且内存释放方式与Rust保持一致,也就是Vulkan对象离开作用域自动释放内存,防止了Vulkan内存泄漏。
vulkano的这些优点可以极大提升Vulkan程序的开发效率,因此Steel引擎选用vulkano作为渲染API。
一般游戏编辑器提供可视化搭建场景,可视化数据设置,可视化资源管理和动态加载游戏代码等功能,是一个复杂的图形应用程序。
egui是一个Rust编写的即时模式(immediate mode)GUI库,这意味着它根据应用程序的当前状态在每一帧更新用户界面。相比之下,保留模式(retained mode)GUI库维护用户界面组件的树状结构,并仅在必要时更新它们。在即时模式GUI库中,用户界面在每一帧中构建和更新,这使它们更加灵活和响应迅速,但实现和维护也更加复杂。另一方面,保留模式GUI库更易于实现和维护,但响应速度较慢且灵活性较差。egui的即时模式使其更轻量和高效,因为它不需要维护用户界面组件的复杂树状结构。相反,它根据应用程序的当前状态更新用户界面,这使它响应更快且更易于使用。
游戏程序需要每帧都绘制并显示新的图像,并且有快速响应的需求,所以即时模式GUI库是游戏程序的最佳选择。因此Steel引擎选择egui作为GUI框架。Steel引擎编辑器使用egui编写界面,并且Steel引擎的游戏同样也可以使用egui编写界面。
Rust是一个静态语言,编写的代码需要编译成动态链接库,就可以动态加载了。
首先为了编译Rust为动态链接库,可以在Cargo.toml中设置create-type为cdylib即可:
[lib]
crate-type = [ "cdylib" ]
接下来还需要实现运行时编译。Rust的Cargo就是一个强大的编译器,我们可以使用Rust的std::process::Command执行cargo build命令即可在编辑器运行时发起编译:
std::process::Command::new("cargo")
.arg("build")
.arg("-p")
.arg("steel-dynlib")
.spawn()?
.wait()?;
最后需要实现运行时加载动态链接库。Rust的libloading可以轻松实现运行时加载一个动态链接库:
let library: Library = unsafe { Library::new(&lib_path)? };
let create_app_fn: Symbol<fn() -> Box<dyn App>> = unsafe { library.get(b"create")? };
let mut app = create_app_fn();
...
Steel编辑器加载了游戏的代码之后,调用create函数生成一个装有游戏数据的Box
Steel是一个Rust编写的开源,简单,模块化,高性能,跨平台和自带编辑器的游戏引擎。
Github链接:https://github.com/SSSxCCC/steel
目前的开发还处于早期阶段,欢迎大家来star/fork!