Upgrade to Pro — share decks privately, control downloads, hide ads and more …

こわくない!! たのしい!! GDExtension

Avatar for ueshita ueshita
October 25, 2023

こわくない!! たのしい!! GDExtension

第1回 Godot勉強会のLTスライドです。

Avatar for ueshita

ueshita

October 25, 2023
Tweet

More Decks by ueshita

Other Decks in Programming

Transcript

  1. ターゲット固有機能の使用 • ターゲット固有機能 – OSサービスの使用 (ex.課金APIなど) – 特殊なデバイスの使用 (ex.USB機器など) •

    もしかしたら、既に存在しているかも? – エンジンの機能? → 公式ドキュメントで探す – OSSで存在? → AssetLibraryやGitHubで探す
  2. GDExtensionで使用できる言語 • 公式のサポート – C++: https://github.com/godotengine/godot-cpp • コミュニティベースのサポート (下記は一例) –

    Rust: https://github.com/godot-rust/gdext – Go: https://github.com/godot-go/godot-go – D: https://github.com/godot-d/godot-d
  3. ターゲットごとにビルドが必要 • Windows → dll • macOS → dylib •

    Linux → so • iOS → dylib • Android → so • Web → wasm GDExtensionはつらい!? 用途を絞って使いましょう
  4. 基本のスクリプト • 画面端でバウンドするだけ func _process(delta: float) -> void: position +=

    velocity * delta if position.x < 0.0: velocity.x = -velocity.x elif position.x > 1280.0: velocity.x = -velocity.x if position.y < 0.0: velocity.y = -velocity.y elif position.y > 720.0: velocity.y = -velocity.y
  5. _processをC++化してみた GDScript C++ func _process(delta: float) -> void: position +=

    velocity * delta if position.x < 0.0: velocity.x = -velocity.x elif position.x > 1280.0: velocity.x = -velocity.x if position.y < 0.0: velocity.y = -velocity.y elif position.y > 720.0: velocity.y = -velocity.y void SpriteCpp::_process(float delta) { Vector2 position = get_position(); position += velocity * delta; set_position(position); if (position.x < 0.0) { velocity.x = -velocity.x; } else if (position.x > 1280.0) { velocity.x = -velocity.x; } if (position.y < 0.0) { velocity.y = -velocity.y; } else if (position.y > 720.0) { velocity.y = -velocity.y; } }
  6. パフォーマンス比較 スプライト数 GDScript C++ 10000 63 fps 124 fps 20000

    33 fps 62 fps 30000 21 fps 44 fps • FPS計測結果 (高いほど速い) ※ instanciate(ノード生成)負荷は除外 (実際はFPSは半分くらいになる)
  7. RenderingServerで2Dスプライトを表示 extends Node2D var texture: Texture var rid: RID func

    _ready(): # CanvasItem(2Dの描画インスタンス)を作成 (RIDが返ってくる。free_ridで解放する必要あり) rid = RenderingServer.canvas_item_create() # 親インスタンスを設定 (自分は2Dノードである必要がある ) RenderingServer.canvas_item_set_parent(rid, get_canvas_item()) # テクスチャをロード(参照は維持しておく必要がある) texture = load("res://my_texture.png") # テクスチャ描画を追加 (原点に中心が来るようにする ) var rect = Rect2(texture.get_size() / -2, textexture.get_size()) RenderingServer.canvas_item_add_texture_rect(sprite.rid, rect, texture.get_rid()) # 45度回転させて(200,300)に移動するトランスフォームをセットする var xform = Transform2D().rotated(deg_to_rad(45)).translated(Vector2(200, 300)) RenderingServer.canvas_item_set_transform(rid, xform)
  8. サーバーAPIを活用してみた GDScript C++ func _process(delta: float) -> void: if spawn:

    # Spawn phase for i in range(10): var sprite = ServerSpriteGD.new() sprite.rid = RenderingServer.canvas_item_create() RenderingServer.canvas_item_set_parent(sprite.rid, get_canvas_item()) RenderingServer.canvas_item_set_draw_index(sprite.rid, len(sprites)) var rect = Rect2(0, 0, texture.get_width(), texture.get_height()) RenderingServer.canvas_item_add_texture_rect(sprite.rid, rect, texture.get_rid()) var speed = 200 var direction = angle + i * (deg_to_rad(360)) / 10 sprite.position = Vector2(640, 360) sprite.velocity = Vector2(cos(direction), sin(direction)) * speed sprites.append(sprite) angle += deg_to_rad(2) # Update phase for sprite in sprites: sprite.position += sprite.velocity * delta if sprite.position.x < 0.0: sprite.velocity.x = -sprite.velocity.x elif sprite.position.x > 1280.0: sprite.velocity.x = -sprite.velocity.x if sprite.position.y < 0.0: sprite.velocity.y = -sprite.velocity.y elif sprite.position.y > 720.0: sprite.velocity.y = -sprite.velocity.y var sprite_transform = Transform2D(0.0, Vector2(0.25, 0.25), 0.0, sprite.position) RenderingServer.canvas_item_set_transform(sprite.rid, sprite_transform) void SpriteServerCpp::_process(float delta) { auto rs = RenderingServer::get_singleton(); if (spawn) { // Spawn phase for (int i = 0; i < 10; i++) { auto sprite = ServerSpriteCpp(); sprite.rid = rs->canvas_item_create(); rs->canvas_item_set_parent(sprite.rid, get_canvas_item()); rs->canvas_item_set_draw_index(sprite.rid, (int)sprites.size()); Rect2 rect = Rect2(0, 0, texture->get_width(), texture->get_height()); rs->canvas_item_add_texture_rect(sprite.rid, rect, texture->get_rid()); float speed = 200.0f; float direction = angle + i * (UtilityFunctions::deg_to_rad(360.0f)) / 10.0f; sprite.position = Vector2(640, 360); sprite.velocity = Vector2(cos(direction), sin(direction)) * speed; sprites.emplace_back(sprite); } angle += UtilityFunctions::deg_to_rad(2); } // Update phase for (auto& sprite : sprites) { sprite.position += sprite.velocity * delta; if (sprite.position.x < 0.0) { sprite.velocity.x = -sprite.velocity.x; } else if (sprite.position.x > 1280.0) { sprite.velocity.x = -sprite.velocity.x; } if (sprite.position.y < 0.0) { sprite.velocity.y = -sprite.velocity.y; } else if (sprite.position.y > 720.0) { sprite.velocity.y = -sprite.velocity.y; } Transform2D sprite_transform = Transform2D(0.0, Vector2(0.25, 0.25), 0.0, sprite.position); rs->canvas_item_set_transform(sprite.rid, sprite_transform); } }
  9. まとめ • GDExtension – エンジンに足りない機能を追加できる – 言語はRust,Go,Dなど色々選択できる • パフォーマンス改善について –

    重い処理をC++で実装して高速化できる – 更にパフォーマンスを上げたい時はサーバーAPIを使う
  10. 参考リンク • Godot公式リンク – GDExtensionの解説とチュートリアル – サーバーを使用した最適化 • 自分関係のリポジトリ –

    今回のデモ: パフォーマンス改善のコード一式 – EffekseerForGodot4: エフェクトエンジンのGodotプラグイン – ADXLE-GodotPlugin: サウンドミドルウェアのGodotプラグイン