Rustを使ったゲーム開発について紹介したいと思います。言語の特徴、ゲームエンジンの選択肢、実際の作品について書いていきます。
1. Rustの特徴
コンパイラが非常に優秀で、メモリや変数の管理がうまくできてないとめちゃくちゃコンパイルエラーを吐き出してくれます。以下に個人的に好きなところを列挙しました。
1.1 メモリ管理が安心
Rustでは変数に寿命と所有権が存在しています。
変数の寿命はスコープの外に出たら使えなくなるという性質です。他の言語でもスタック領域ならその性質は存在するのすが、Rustの場合ヒープ領域に作った変数でもスコープから出ると削除してくれます。このおかげでメモリリークしなくてよさそうです。
fn hoge() {
let a: i32 = 23; // スタック領域の変数
let b = String::from("hoge"); // ヒープ領域の変数
println!("{}, {}", a, b);
}
// aもbもメモリから削除されます。
所有権は変数を別の変数に代入したり、関数の引数として渡したりするときに登場する概念です。これによって効率的で安全なメモリ管理ができます。
fn aaa(hoge: Vec<i32>) {
println!("{:?}", hoge);
}
fn main() {
let hoge: Vec<i32> = vec![1, 2, 3];
aaa(hoge); // ここで所有権がaaaにムーブ
// aaa(hoge)をもう一度実行したらコンパイルエラーがでます。
// 無駄なメモリが削除されるので効率がいいです。
}
上の例ではVectorをそのまま渡しているのですが普通はそんなことをせずに参照を渡します。そのときに所有権を貸し出すということをします。今回は言及しませんが、書き換える目的で変数を借りるmutable borrowに関して危険なプログラムを書くとコンパイラがエラーを吐き出します。安心ですね。
/// 変数を借りている
fn aaa(hoge: &Vec<i32>) {
println!("{:?}", hoge);
}
fn main() {
let hoge: Vec<i32> = vec![1, 2, 3];
aaa(&hoge); // hogeを貸し出し、終わったあと戻ってくる
aaa(&hoge); // hogeが戻ってきたのでエラーは出ません
}
1.2 型チェックが結構厳しい
これは読んで字の如く、i32型にu32型の変数を代入しようとするとエラーを吐き出すみたいな話です。自動でキャストするみたいなことをしないので、その辺自分は雑になりやすいのでうれしいです。他にもRustには変数に書き換え可能かどうかの設定をする必要があって、let mutで宣言した変数にletで宣言した変数を代入するとエラーになります。
1.3 Cargoが便利
Rustのパッケージ管理マネージャなのですが、パッケージ管理だけでなくプロジェクトの作成や実行などなんでもやってくれます。これは完全に感覚なのですがとても快適で最高です。
1.4 Rustに関する結論
ゲームはバグが大量に発生しがちなので、Rustみたいなバグを産みにくい言語はゲーム開発にかなり適しているような気がします。
2. ゲームエンジンの種類
Rustのゲームエンジンで流行っているのはAmethyst、Piston、ggezなどですね。
自分が個人的に使っているのはAmethystです。
2.1 Amethyst
Amethystのチュートリアル的なものは以前に書いたので興味ある方はこちらをどうぞ。
Amethystは3Dも2Dも作ることができるエンジンで、ECS(EntityComponentSystem)という設計をとっています。
2.2 Piston, ggez
Pistonも3Dゲームをつくれますが最近あまり開発が活発でない印象です。
ggezは2Dゲーム開発に強みがあるそうです。(あまり詳しくなくてすいません)
3. 実際の作品
毎月、Rustで開発されたゲームの紹介をしているサイトがあるので以下にリンクを貼っておきます。
https://rust-gamedev.github.io/
自分も現在ゲーム開発をしていて、Twitterにて不定期で進捗をアップしていますのでよければチェックしてみてください。
https://twitter.com/takeryo_eeic
まとめ
Rustを使ったゲーム開発の紹介は以上になります。ありがとうございました。