サークル獏の佐藤敏 Unityとか備忘録

サークル獏の佐藤敏がUnityとかで知ったTipsを書いておく備忘録です。

派生クラスのインスタンスを全部生成してDictionaryに入れるとか

どーんと派生クラスの一覧を得る便利なコード

esprog.hatenablog.com
@es_programさんのこういった記事がある。
 
 

自分用の使い道を考える

で、使い方として考えたのが、例えば「色々なボイス反応を返すクラスのインスタンスを全部自動生成して、辞書からアクセスできるようにする」っていう形。

あまり良い使い方でもないかもしれないが、調教SLGとかだと「パラメータで色々分岐するのでExcelの表みたいなので完全管理は難しい」ケースがあるのでこんな感じが割と使い勝手良かったりする。
(本来ならLuaとかのスクリプトに担当させて、いちいちコンパイルが走らないようにするのがカシコイのかもしれない)

以下のスクリプトのTestScriptをUnityで適当なempty objectとかにアタッチして実行すると、こんな実行結果が得られる。
f:id:VinSatoo:20180808133902p:plain

もっといいやり方があってもご愛敬。
 
 

スクリプト部分

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

abstract public class VoiceResItem //抽象クラス
{
    public string name { get; set; }
    public virtual string GetResponse(int obey, bool damaged) {
        return "";
    }
}

public class VoiceHateResItem : VoiceResItem //派生クラス
{
    public VoiceHateResItem() {
        name = "憎悪";
    }

    public override string GetResponse(int obey,bool damaged) {
        if (damaged)
            return "うっ……くっ……!";
        switch (obey) {
            case 0:
                return "大嫌い!";
            case 1:
                return "きらい。";
            default:
                return "そういうことやめてよ";
        }
    }
}

public class VoiceLoveResItem : VoiceResItem //派生クラス
{
    public VoiceLoveResItem() {
        name = "好き";
    }

    public override string GetResponse(int obey, bool damaged) {
        if (damaged)
            return "私は……っ";
        switch (obey) {
            case 0:
                return "何よ…";
            case 1:
                return "別にイヤじゃないっていうか";
            default:
                return "好き。";
        }
    }
}

public class VoiceResManager //それらを管理
{
    Dictionary<string, VoiceResItem> dic;

    public VoiceResManager() {
        dic = new Dictionary<string, VoiceResItem>();

        var classesList = Assembly
.GetAssembly(typeof(VoiceResItem))
.GetTypes()
.Where(t => {
    return t.IsSubclassOf(typeof(VoiceResItem)) && !t.IsAbstract;
});

        foreach (Type type in classesList) {
            MakeDic((VoiceResItem)Activator.CreateInstance(type));
        }

    }

    void MakeDic(VoiceResItem resItem) {
        dic[resItem.name] = resItem;
    }

    public string GetResponse(string key, int obey, bool damaged) {
        if (dic.ContainsKey(key)) {
            return dic[key].GetResponse(obey, damaged);
        }

        Debug.Log("エラー");
        return "";
    }
}

public class TestScript : MonoBehaviour
//Unityで実際に使ってみる用 適当なEmpty Objectにでもアタッチして実行
{
    VoiceResManager voiceResManager;
    void Start() {
        voiceResManager = new VoiceResManager();
        for (int i = 0; i < 3; i++) {
            Debug.Log(voiceResManager.GetResponse("憎悪", i,false));
            Debug.Log(voiceResManager.GetResponse("好き", i, false));
        }
        Debug.Log(voiceResManager.GetResponse("憎悪", 0,true));
        Debug.Log(voiceResManager.GetResponse("好き", 2, true));
        Debug.Log(voiceResManager.GetResponse("普通", 1,true));
    }
}