[Unity] Dictionaryを使ってif文を減らしたい(非エンジニア)

unityバージョン:2019.4.25f1

if文だけで条件分岐を管理していたら訳分からなくなってきたので他の方法を模索中

例えばキャラクターの挙動において攻撃中はジャンプや移動ができないなど、状態によってできるできないをif文だけで条件分岐していると状態の数が増えれば増えるほど分岐が複雑になる

そこでDictionaryを使ってなんとかできないかやってみた

Dictionaryの参考元
C# Dictionary<T> の使い方(まとめ)
http://programmers.high-way.info/cs/dictionary.html

Dictionaryについて

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleScript1 : MonoBehaviour//class名はファイル名と同じにする
{
    // status(任意の名前)というDictionaryを宣言
    // 二つの値を紐付けて保持できる
    // 値の変数型はそれぞれ指定できる ここではstring型とbool型
    // 下記の左側の値をKeyと呼ぶ 右側の値をValueと呼ぶ
    private Dictionary<string, bool> status = new Dictionary<string, bool>
    {
        { "StatusA" , false },
        { "StatusB" , false },
        { "StatusC" , false },
        { "StatusD" , false },
    };
    void Start()
    {
        //statusはDictionaryの名前
        if ( status.ContainsKey( "StatusA" ) )
        {
            //処理  条件:Keyの中に"StatusA"という値がある
        }
        if ( !status.ContainsKey( "StatusA" ) )
        {
            //処理  条件:Keyの中に"StatusA"という値がない
        }
        if ( status.ContainsValue( true ) )
        {
            //処理  条件:Valueの中にtrueがある
        }
        if ( !status.ContainsValue( true ) )
        {
            //処理  条件:Valueの中にtrueがない
        }
        if (status[ "StatusB" ] == false)
        {
            //処理  条件:"StatusB"というKeyに紐づいているValueの値がfalse
        }
        
        //"StatusC"に紐づいているValueの値を取得する 
        bool aaa; //値を取得するための変数
        status.TryGetValue( "StatusC" , out aaa );
        Debug.Log( aaa );//Consoleウィンドウに出力 Consoleの場所:Window >> General >> Console
        
        //"StatusD"に紐づいているValueの値をtrueに更新する
        status[ "StatusD" ] = true;
        
        //"StatusE"というKeyとそれに紐づくValueの値falseを追加
        status.Add( "StatusE", false );
        
        //"StatusE"というKeyを削除
        status.Remove( "StatusE" );
    }
}

変数の型
bool
      trueとfalseの値を持てる変数
int         整数の値を持てる変数
float     浮動小数(0.1とか)の値を持てる変数 値を代入するときは数字の後にfをつける
string 文字列を値として持てる変数 値を代入するときは""で挟む

Dictionaryを使ってひとつの処理を実行中は他の処理を実行不可にする

Valueの値にひとつでもtrueがあればif文で分岐した後switch文で該当の処理だけ実行するようにしてみた

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleScript2 : MonoBehaviour//class名はファイル名と同じにする
{
    // status(任意の名前にできる)というDictionaryを宣言
    // 二つの値を紐付けて保持できる
    // 値の変数型はそれぞれ指定できる ここではstring型とbool型
    // 下記の左側の値をKeyと呼ぶ 右側の値をValueと呼ぶ
    private Dictionary<string, bool> status = new Dictionary<string, bool>
    {
        { "StatusA" , false },
        { "StatusB" , false },
        { "StatusC" , false },
    };
    void Update()
    {
        //statusにtrueがない時の処理
        if(!status.ContainsValue( true ))
        {
            //KEY_DOWNメソッドの呼び出し 内容は後述のKEY_DOWNメソッド
            KEY_DOWN();
        }
        //statusにtrueがあった時の処理
        else if(status.ContainsValue( true ))
        {
            //statusのValueを調べてtrueがあったらKeyの値を取得してforeachを中断する
            //Keyの値取得用の変数の宣言
            string _state = "";
            
            //foreachでstatusの値を順番に調べる
            //このforeach文の中ではiという変数がstatusの代わりになる
            foreach(var i in status)
            {
                //Valueの値を順番に取得してtrueがあるか確認
                if(i.Value == true)
                {
                    //trueがあったらKeyを取得してforeachを中断
                    _state = i.Key;
                    break;
                }
            }
            //取得したKeyで条件分岐して条件を満たした処理を実行
            switch(_state)
            {
                case "StatusA":
                    AAA(); //AAAメソッドの呼び出し
                    break;
                case "StatusB":
                    BBB(); //BBBメソッドの呼び出し
                    break;
                case "StatusC":
                    CCC(); //CCCメソッドの呼び出し
                    break;
            }
            //KEY_UPメソッドの呼び出し 内容は後述のKEY_UPメソッド
            KEY_UP();
        }
    }
    
    //各メソッド
    private void AAA ()
    {
        //StatusAの時の処理
    }
    private void BBB ()
    {
        //StatusBの時の処理
    }
    private void CCC ()
    {
        //StatusCの時の処理
    }
    
    //statusのValueの値をキー入力で更新する
    // キーを押した時の処理
    private void KEY_DOWN ()
    {
        // Aキーを押した時、"StatusA"のValueをtrueに更新
        if(Input.GetKeyDown(KeyCode.A))
        {
            status["StatusA"] = true;
        }
        // Bキーを押した時、"StatusA"のValueをtrueに更新
        else if(Input.GetKeyDown(KeyCode.B))
        {
            status["StatusB"] = true;
        }
        // Cキーを押した時、"StatusA"のValueをtrueに更新
        else if(Input.GetKeyDown(KeyCode.C))
        {
            status["StatusC"] = true;
        }   
    }
    // キーを離した時の処理
    private void KEY_UP ()
    {
        // Aキーを離した時、"StatusA"のValueをfalseに更新
        if(Input.GetKeyUp(KeyCode.A))
        {
            status["StatusA"] = false;
        }
        // Bキーを離した時、"StatusA"のValueをfalseに更新
        else if(Input.GetKeyUp(KeyCode.B))
        {
            status["StatusB"] = false;
        }
        // Cキーを離した時、"StatusA"のValueをfalseに更新
        else if(Input.GetKeyUp(KeyCode.C))
        {
            status["StatusC"] = false;
        }
    }
}

Dictionary以外の記述について補足

メソッドについて
正確な定義は理解できていないので詳しい説明はできません
自分で調べるか下記のサイトなどを参考にしてみてください
ここではScript内のUpdateの記述が冗長になるので使っていますが正確な使い方かはわかりません

「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
https://wa3.i-3-i.info/word1906.html
https://wa3.i-3-i.info/diff97function.html

foreachについて
繰り返し処理をするためのもの
ここではDictionaryの中身を確認するために値の取得とif文での値の確認をDictionary内の値の個数分だけ繰り返し行なっている

foreachの説明はこちらを参考にしてみてください
【C#入門】foreachの使い方(break、continueでの制御も解説)
https://www.sejuku.net/blog/41892

switch文について
条件分岐をするためのもの
switch文よりif文が好まれる場合もある

キー入力について
if文と一緒に記述することでキー入力に合わせて処理を実行できる

Input.GetKeyDown(KeyCode.A)
Aキーを押した時だけtrueを取得
それ以外はfalse

Input.GetKey(KeyCode.A)
Aキーを押している間trueを取得
それ以外はfalse

Input.GetKeyUp(KeyCode.A)
Aキーを離した時だけtrueを取得
それ以外はfalse

UnityのKeyCodeリファレンス
https://docs.unity3d.com/ja/2019.4/ScriptReference/KeyCode.html

勉強中なので説明が間違っている可能性があります自分でも調べて確認してみてください


この記事が気に入ったらサポートをしてみませんか?