Foltkaurの制作ブログ

制作物の紹介や技術的な備忘録などを書いていきます。

GodotでバイナリでセーブとロードをするついでにPathのメモ

Godotはゲームエンジンの一つです。他に有名なのだとUnityとかUnreal Engineとかですね。 Godotはオープンソースで完全にタダで使えるみたいです。

GodotにはJSONやオブジェクトそのものをシリアライズする機能もあるようですが、今回はバイナリで保存する方法を自身の備忘録も兼ねて書いておこうと思います。 ほぼ初めてブログを書くので技術的な知識はあるがGodotは知らないという方向けの書き方になってしまいそうで、始めたばかりの方には少し難しい用語が多く出てくると思いますが各自で調べながら読んでみてください。公式や掲示板等の情報が英語なことが多く私自身もGoogle翻訳を使いながら少しずつ読んでいますので間違いなどありましたらコメントやTwitterにてご指摘くださいますと幸いです。

コードを書いていますがGodotはインデントでスコープを変えているのでコピペはおすすめできません。

FileクラスとPath

FileクラスはGodotでファイル操作をするためのクラスです。

フォルダ(ディレクトリ)操作はDirectoryクラスがあります。

が、今回は詳しく触れません。 操作(作ったり消したり、動かしたり)するための一般的な機能を集めたものという認識で構いません。Godotにおけるクラスというものもエンジン側のものでエンジンを参照しているのでスクリプトではどこからでも呼べるという感じ?(不安)ですかね......。 エンジン側に登録されているから自分でも作成できるとかだったかな......。(不安)

Pathについてですが、Godotはデフォルトでプロジェクトがあるフォルダを"res://"というルートフォルダに設定します。他にも"user://"という(WindowsだとAppData以下になるらしい)といった特殊なフォルダ指定があります。

良い書き方がわからないので以下やったことと結果

  • Pathの指定を "" にするとルートフォルダ("res://"と同じ)になる(セーブのテスト時にファイルが作られた)
  • Fileクラスにはファイルが無ければ作るという修飾子があるがフォルダがない場合まで作ってくれるわけではない

GDScriptはわかるよって方はFileクラスのリファレンス冒頭に書いてあるコードがセーブとロードの例になっているのでそちらも見てみてください。

セーブ

セーブは File.open(ファイルのパス , モードフラグ) で行います。 セーブというかファイルへの書き込みですね。

その前にFileクラスを使うためにはnewしないといけません。先に全体を書きますね。

func save_game():

    var file = File.new()
    file.open("res://hoge/hoge.txt", File.WRITE)

    ここにセーブ処理

    file.close()

File.WRITEですがモードフラグの一つで書き込み操作のために開いてなければ作るです。 他には

  • READ 読み取り
  • READ_WRITE 読み取りと書き込み ファイルを切り捨てない
  • WRITE_READ 読み取りと書き込み ファイルがあれば切り捨てる なければ作る

切り捨てはおそらく全消ししてから書き込むかどうかということでしょう。

実際のセーブ処理は store_??? というメソッドを使用します。

  • 文字列は store_string
  • floatは store_float

integerなんですけどfloatもintegerも64bitらしいので integerは store_64 がベストかもしれないです。(16とか32とかあるけども......。)

他にも CSV とか 一行でとかもあるようです。

ということでこんな感じ。(感じ、なので各自で変数名など変えてみてください)

func save_game():

    var file = File.new()
    file.open("res://hoge/hoge.txt", File.WRITE)

    var tex = "aaabbbccc"
    var flot = 3.1415

    file.store_32(tex.length())
    file.store_string(tex)
    file.store_float(flot)

    file.close()

ロード

ロードも最初に new してから読み込みます。ロードは get_??? になります。 ちょっと凝ったことをしてみましょう。上でセーブした文字列のあとに書き込みされた float だけを取り出してみます。

func load_game():

    var file = File.new()
    file.open("res://hoge/hoge.txt" , File.READ)

        file.seek( 4 + file.get_32())
        var content = file.get_float()

        file.close()

        print(content)

file.seek でカーソルの位置を動かします。セーブした順番を確認してください。 文字列の長さ、文字列、float の順番でセーブしました。なので seek でファイルのカーソル位置を floatのところまで動かします。

まず「文字列の長さ」は32bitで保存しているので4バイトです。 そのあとに文字列をセーブしたのでその長さを get_32 で取り出します。(メソッド名は結構わかりやすいので助かります)(今回 "aaabbbccc" は9バイトでした)

シーンを実行してみて、コンソールに3.1415と出たら成功です。

感想

ここまで読んでいただきありがとうございます。こういったものを書くのは以前 Qiita にUnreal Engine 向け Epic 公式 Blender プラグインの記事を書いたのが初めてで今回2回めです。 大変読みにくい部分もあるかと思いますが、今後のためご容赦頂ますようよろしくお願いいたします。ただ間違った情報については遠慮なくご指摘ください。より良いモノにして行きましょう。

リンク

以前書いた記事

qiita.com

Godot公式

godotengine.org

Fileクラスのリファレンス

docs.godotengine.org