LoginSignup
1

More than 1 year has passed since last update.

Dictionaryを使ってコードをエレガント(?)なコードにする試み

Last updated at Posted at 2023-01-05

はじめに

海外のとある大学のPython講義動画が日本語字幕付きだったので勉強していたところ、めちゃくちゃ便利なものを見つけてUnityにもあるのかと探していたら見つけたためこれを使ってコードをエレガントにしようと思ったのでその試みを書いていこうと思います。
(私的にはエレガントになってると思います。)
※誤字・脱字・日本語おかしい等あるかもしれませんが脳内補完していただけると嬉しいです。

Pythonの動画(面白いのでぜひ)
https://youtu.be/cHOyFXJlkO0

Dictionaryってどんなところで使えるの?

自分的に考えた使いみちですけど、
例えばRPGで各キャラクターに出会ったときにそのキャラクターの名前を表示するスクリプトを書くときや
文字通り辞書アプリを作るときなどに使えると思います。使い方によっては使いにくい可能性があります。
(1番最初に記述したものは後でコードを紹介しようと思います。)

Dictionaryを具体的に(今回使うのだけ)

宣言する際はこのようになります。

Dictionary<Key, Value> 変数名 = new Dictionary<Key, Value>();  

ex) Key => 文字 , Value => 数字 , 変数名 => dic
Dictionary<string,int> dic = new Dictionary<string,int>();  

ex) Key => 文字 , Value => 文字 , 変数名 => dic
Dictionary<string,string> dic = new Dictionary<string,string>();  

値を追加する際はこのようになります。

変数名.Add(Key,Value);

ex) Key => 文字 , Value => 数字 , 変数名 => dic
dic.Add("スライム",1);   <= Keyにスライム、Valueに1を追加

ex) Key => 文字 , Value => 文字 , 変数名 => dic
dic.Add("slime","スライム");   <= Keyにスライム、Valueにスライムを追加

エレガントにするコード

今回エレガントにするコードはRPGで出会ったキャラの名前を表示するコードです。
エレガント前のコードはこのような感じです。

[SerializeField]
    Text charactorname;
    private void OnTriggerStay2D(Collider2D collision)
    {
        if(collision.gameObject.name == "zombie")
        {
            charactorname.text = "ゾンビ";
        }
        else if(collision.gameObject.name == "slime")
        {
            charactorname.text = "スライム";
        }
        else if(collision.gameObject.name == "villager")
        {
            charactorname.text = "村人";
        }
    }

OnTriggerStay2D()でキャラクターに遭遇すると実行されキャラクターの名前で条件分岐しcharactornameに名前を表示するというコードです。一見これでもよくねとは思いますが、あくまで3キャラだけだからまだいいですが、これが20キャラとか100キャラとかに増えていくと悲惨なことになってしまい他の処理の部分が見にくくなりバグやエラーのもとになったりメンテナンス性が低下するのでエレガントにしていこうと思います。

エレガント第1段階:Dictionaryをとりあえず使う

[SerializeField]
    Text charactorname;
    Dictionary<string, string> characternamedic = new Dictionary<string, string>();
    void nameset()
    {
        characternamedic.Add("slime", "スライム");
        characternamedic.Add("zombie","ゾンビ");
        characternamedic.Add("villager", "村人");
    }
    private void Start()
    {
        nameset();
    }
    private void OnTriggerStay2D(Collider2D collision)
    {
        charactorname.text = characternamedic[collision.name];
    }

Start()でDictionaryに情報を追加します。あとはエレガント前のコードと同じです。
これだけでも条件分岐する分が減るのでかなりエレガントになると思います。(条件式部分と{}分が減る)
ですがこれだとまだ追加する部分が見えて100キャラとかになると追加する部分だけで100行使ってしまうため完全なエレガントとは言い難いです。

エレガント第2段階:txtファイルを使う

   [SerializeField]
    Text charactorname;
    Dictionary<string, string> charactornamedic = new Dictionary<string, string>();
    void nameset()
    {
        TextAsset charactornamedata = (TextAsset)Resources.Load("charactordata");
        string charactorname = charactornamedata.text;
        string[] charactornames = charactorname.Split(',');
        for(int i = 0;i < charactornames.Length - 1;i += 2)
        {
            charactornamedic.Add(charactornames[i].Trim(), charactornames[i + 1].Trim());
        }
    }
    private void Start()
    {
        nameset();
    }
    private void OnTriggerStay2D(Collider2D collision)
    {
        charactorname.text = charactornamedic[collision.name];
    }

nameset()部分が変更されていて、Resourcesフォルダ内にキャラクターの情報を書いたtxtファイルを置きそれをnameset内で読み込み、その文字列をSplitで分解しfor文でDictionaryにTrimしながら追加していく感じです。これを使うとメインのコードのほうがいくらキャラクター数が増えてもコードの量が増えることはないのでエレガントと言ってもいいと思います。しかしResourcesフォルダーから読み込むのはUnityが非推奨にしていたような気がするので読み込むのではなく普通にtxtファイルを入れたほうがいい気がしますが、こっちのほうが行数が減るためこっちにしておきますw
ちなみにtxtファイルはこの様になっています。

zombie,ゾンビ,
slime,スライム,
enemy,敵,
villager,村人,

最後に

今回はコードをエレガントにする試みをしてみました。
同じコードをこっちのほうがエレガントだ!って言うのがあればぜひコメントしてください〜!
ではまた。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1