Maemaemae

Godot Dictionary キー存在確認

はじめに

Godotでゲーム開発をする際、Dictionaryは非常に便利なデータ構造です。しかし、存在しないキーにアクセスするとエラーが発生します。この記事では、GDScriptでDictionaryのキー存在を確認する複数の方法を紹介し、それぞれの使い分けについて解説します。

この記事を読むことで、安全なDictionary操作エラー防止のテクニックを習得できます。

Dictionaryキー確認の基本

has() メソッドの活用

最も直接的なキー確認方法は has() メソッドです。

var player_data = {"name": "勇者", "hp": 100, "mp": 50}

if player_data.has("hp"):
    print("HPが存在します: ", player_data["hp"])
else:
    print("HPが設定されていません")

シンプルで明示的なため、可読性に優れています。

in 演算子の使用

in 演算子もキー存在確認に使えます。より自然な構文で書けます。

var enemy_data = {"name": "スライム", "attack": 15, "defense": 5}

if "attack" in enemy_data:
    var damage = enemy_data["attack"]
    print("攻撃力: ", damage)
else:
    print("攻撃力が設定されていません")

Pythonのような構文で、コードが読みやすくなります。

実践的なパターン

キー確認とデフォルト値

存在しないキーに対してデフォルト値を返す関数を作成できます。

func get_stat(data_dict, key, default_value = 0):
    if key in data_dict:
        return data_dict[key]
    return default_value

var character = {"strength": 10, "agility": 15}
var intelligence = get_stat(character, "intelligence", 5)  # デフォルト値の5が返る

繰り返し使用するコードをシンプルにできます。

get() メソッドの活用

実は、Dictionaryクラスには便利な get() メソッドがあります。

var item = {"name": "回復薬", "effect": 30}
var description = item.get("description", "説明がありません")  # デフォルト値を指定

print(description)  # "説明がありません" が出力される

一行で簡潔に書けるため、多くの場合はこの方法が推奨されます。

応用テクニック

ネストされたDictionaryの確認

複雑なデータ構造でも安全にアクセスする方法を紹介します。

var game_data = {
    "player": {
        "stats": {
            "strength": 10,
            "agility": 15
        }
    }
}

# ネストされたキーの安全な確認
if "player" in game_data and "stats" in game_data["player"] and "magic" in game_data["player"]["stats"]:
    print("魔法値: ", game_data["player"]["stats"]["magic"])
else:
    print("魔法値が設定されていません")

ヘルパー関数の作成

深くネストされたデータへの安全なアクセスのためのヘルパー関数も便利です。

func get_nested_value(dict, path, default_value = null):
    var current = dict
    var keys = path.split(".")

    for key in keys:
        if key in current:
            current = current[key]
        else:
            return default_value

    return current

# 使用例
var magic = get_nested_value(game_data, "player.stats.magic", 0)

エラー処理とデバッグ

エラー防止の実践例

実際のゲーム開発では、このようにキー確認を行います。

func apply_damage(character, amount):
    if not "hp" in character:
        push_error("キャラクターにHPが設定されていません")
        return false

    character["hp"] = max(0, character["hp"] - amount)

    if character["hp"] <= 0:
        if "on_defeat" in character:
            character["on_defeat"].call()

    return true

デバッグ用の辞書内容表示

開発中は辞書の内容を確認することも大切です。

func print_dict_keys(dict):
    print("Dictionary keys: ", dict.keys())

func print_dict_content(dict, indent = 0):
    var indent_str = "  ".repeat(indent)
    for key in dict:
        var value = dict[key]
        if value is Dictionary:
            print("%s%s:" % [indent_str, key])
            print_dict_content(value, indent + 1)
        else:
            print("%s%s: %s" % [indent_str, key, value])

ベストプラクティス

  1. 存在確認の習慣化 - 不確かなキーにアクセスする前に必ず確認
  2. get()メソッドの活用 - シンプルな場合はこの方法が最適
  3. ヘルパー関数の作成 - 繰り返し使うパターンは関数化
  4. 早期リターン - キーがない場合は早めに処理を終了
  5. デフォルト値の適切な設定 - ゲームバランスを考慮した値を設定

実装例: アイテムシステム

# アイテム使用関数の例
func use_item(item_id, target):
    var item_db = get_item_database()

    if not item_id in item_db:
        print("存在しないアイテムID: ", item_id)
        return false

    var item = item_db[item_id]

    if not "effect" in item:
        print("アイテムに効果が設定されていません: ", item_id)
        return false

    var effect_type = item.get("effect_type", "heal")
    var effect_value = item.get("effect_value", 0)

    match effect_type:
        "heal":
            if "hp" in target:
                target["hp"] = min(target.get("max_hp", 100), target["hp"] + effect_value)
                print("%sのHPが%d回復した" % [target.get("name", "???"), effect_value])
                return true
        "buff":
            var duration = item.get("duration", 3)
            apply_buff(target, effect_value, duration)
            return true

    return false

参考資料


Godot 4.4以上を対象としています。

GodotGDScriptDictionaryデータ構造ゲーム開発