質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.36%

  • C#

    4777questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    2308questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

C#で遺伝的アルゴリズムの組み方がいまいちわかりません

解決済

回答 1

投稿 2017/11/25 18:19 ・編集 2017/11/25 20:05

  • 評価
  • クリップ 0
  • VIEW 209

rinmeda317

score 4

前提・実現したいこと

大学生です。
Unityで遺伝的アルゴリズムを利用して2Dタワーディフェンスゲームを作ろうとしているのですが、C#に触れるのが初めてなもので、理論は理解していてもどうスクリプトを組めばいいのかわからず、スクリプト例を見ててわからなかった用語(IEnumerable、yield、paramなど)をネットなどで調べても専門用語ばかりで理解ができず、難航しています。

実装したい機能の流れとしては、
・プレハブでオブジェクトを10個作成し、一定間隔で右折もしくは左折させて移動させるために0なら右折、1なら左折というように0と1の配列を作成して読み込ませる
・世代終了時に最もx座標値が大きかった2個体を選択
・一点交叉をして次世代の10個体の配列を作成する
・作成した配列をもう一度新しくプレハブで作成したオブジェクトに適用する
・x座標値が一定の値を超えたら終了
というものを想定しています。

現時点で実現したいもののできていないことは大体以下の通りです。

・プレハブで作成したオブジェクト"Runba"に番号を振りたい
・各Runbaが保持する配列を別のスクリプトに渡したい。
・配列のメソッドの呼び出し方がわからない。

他にもまだまだ課題はありますが、まず解決しなければならないのはこのあたりだと思います。
ソースコードは書きかけゆえ不完全で煩雑なものですし、上記の文章もわかりづらい表現になってしまっていることは承知の上ですが、私一人の力ではもうどうすることもできません。どうかよろしくお願いします。

追記
RunbaGenerator.csの「obj.name = Runba.name」を「obj.name = "Runba" + i」と書き換えてみたら一つ目の問題は解決しました。

発生している問題・エラーメッセージ

エラーメッセージ
Assets/Runbamove.cs(25,13):error CS0103:The name 'Gene' dose not exist in the current context
これを解消するために何を追加で記入するべきかがわかりません

該当のソースコード

//RunbaGenerator.csの内容
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RunbaGenerator : MonoBehaviour {

    public GameObject Runba;
    float span = 10.0f;
    float timer = 0;

    // Use this for initialization
    void Start () {
    }

    //初期遺伝子の作成
    public int[] OriginGene () {
        int[] Gene = new int [10];
        for(int i = 0; i < 10 ; i++){
            Gene [i] = Random.Range(0,2);
        }
        return Gene;
    }

    // Update is called once per frame
    void Update () {
        timer -= Time.deltaTime;//時間の取得
        if (timer < 0) {
            for (int i = 1; i < 11; i++) {
                GameObject obj = Instantiate (Runba, new Vector3 (50, 1, i * 90), Quaternion.identity) as GameObject;//生成
                obj.name = Runba.name;//生成されたオブジェクトの名前をRunbaに変更
            }
            timer = span;//タイマーをリセット
        }
    }
}

//Runbamove.csの内容
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Runbamove : MonoBehaviour {

    // Use this for initialization

    float interval = 1.0f;
    float timer = 0;

    void Start () {
        Invoke ("DestroyObject", 10f);
        GetComponent<RunbaGenerator>().OriginGene();
        //Gene[] = 
    }

    // Update is called once per frame
    void Update () {
        timer -= Time.deltaTime;//時間の取得
        for(int i = 0; i < 10 ; i++){
            if (timer < 0) {
                int a = Gene [i];//曲がる方向を配列で決定
                if (a == 1) {
                    a = -30;
                } else {
                    a = 30;
                }
                Vector3 w = new Vector3 (0f, a, 0f);//回転
                transform.Rotate (w);
                timer = interval;
            }
        }
        Vector3 v = new Vector3 (0.5f, 0f, 0f);//移動
        transform.Translate (v);

        /*bool f0 = Input.GetMouseButton (0);//クリック時の反応
        if (f0) {
            Vector3 V0 = Input.mousePosition;
            V0.z += 3f;
            Ray ray = Camera.main.ScreenPointToRay (V0);
            RaycastHit hit;
            bool f = Physics.Raycast (ray, out hit, 1000);
            if (f) {
                if (hit.collider.gameObject.name == "Runba") {
                    gameObject.SetActive(false);//クリックされた場合ルンバを非表示
                }
            }//現行での問題点:クリックするとクリックしたものより左側のルンバも全部消える
        }*/
    }

    //今世代のGene[]を10個取得してGeneAlgorithm.csに渡すためのメソッド
    public int[] Genetic(){

    }

    void DestroyObject(){
        Destroy (gameObject);

    }
}

試したこと

課題に対してアプローチしたことを記載してください

補足情報(言語/FW/ツール等のバージョンなど)

Unityのバージョンは最新です

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • MasahikoHirata

    2017/11/25 18:49

    まずはエラーの意味を理解されるのが良いかと。’public int[] OriginGene () ’の内部変数の’Gene'が関数’Runbamove’から見えないから’何?’と言われていると思いますが。

    キャンセル

  • rinmeda317

    2017/11/25 19:23

    内部変数の読み込みのために追加で何かを書かなければいけないのは理解しています。何を記入すればいいのかがわからないのです…

    キャンセル

回答 1

checkベストアンサー

+4

Unityで遺伝的アルゴリズムを利用して
2Dタワーディフェンスゲームを作ろうとしている

質問者の方にとって、魅力的な題材なのは分かります。
遺伝的アルゴリズム(GA)」とかって、
生物の世代交代の仕組みを利用するコンセプトが面白いですよね。

しかし、難しいことをいっぺんにやろうとしている感じです。

C#、Unity、遺伝的アルゴリズム、タワーディフェンス、
どれも一冊の本になるくらいのテーマです。

最初はUnity抜きでC#の仕様だけ見てみるとか、
逆にUnityを学ぶときはまずUIだけいじってみるとか、
遺伝的アルゴリズムをやるなら、ゲーム部分はジャンケンにするとか、
逆にタワーディフェンスをやるなら、GAは抜きにするとか、
問題を分けて小さくして、各個撃破していきましょう。

個々のテーマに分解して、それぞれ集中して学ぶ方が、
最終的な成功率は高いでしょう。たとえると、急がば回れ。ウサギとカメ。


さて、上記だけだと、一般論だけでお茶を濁されているように
感じているかもしれませんから、プログラミングについても触れます。

ご自分で書いたコードなのに、自分で読んでも分かりにくいと思います。
だから、こうして質問しているんでしょう。

専門用語ばかりで理解ができず、難航しています。

質問者の方が自覚されているように、
仕様の理解不足という面がまずあるでしょう。


しかし、仕様とコードを分けて考えているでしょうから、あえて言うと、
コードと仕様を近づけていく、という発想に欠けています。

C#はオブジェクト指向言語ですので、OOPに向いています。
OOには、高凝集・疎結合とか、単一責務などの原理原則があります。

そこで、遺伝的アルゴリズムは、タワーディフェンス(たとえば回転や移動)と、
まったく別の関心事、別のドメインですから、クラスも分けます。

そして、「遺伝子」、「世代」、「交叉」、「淘汰」、「突然変異」など、
ドメインの用語に合わせて、フィールドやメソッドを作ります。

現状でも、「初期遺伝子の作成」「OriginGene」とかはありますが、
それだけでは不十分なので、さらに分離してください。責務を分離します。

そうしたら、タワーディフェンスのキャラクターのクラスからは、
GAの自作ライブラリを使う感じにします。つまり、内部の実装には触れない。

さらに言うと、GAライブラリは移動や回転をしている部分からは呼ばず、
なるべくファクトリから(だけ)使うことを考えます。
GAを使う以上、複数キャラを作るはずで、生成と相性が良いからです。

なお、最近のGAは、たとえば島に分けるとか、いろいろ工夫しており、
複雑になるようなら、名前空間(Javaでいうパッケージ)の単位で、
より大きくグループ化しても良いでしょう。というか、私なら分けちゃうかも。


もし、そうした方が上手くいくかどうか、疑問が残るようでしたら、
(クラス)ライブラリを使った経験に、照らし合わせてみてください。

いろんな言語の標準ライブラリで、
日付と画像を混ぜたり、数学とファイル操作を混ぜたり、
といったことは、まずありえないと思います。ないでしょ?

じゃあ、自分で作るクラスでも同様に
遺伝的アルゴリズムとタワーディフェンスを分けた方が、
使いやすいのではないでしょうか。

分割統治はプログラミングの王道です。
人間は一度に二つ以上のことを同時に考えるのが難しいので、
まして難しい専門領域なら、分けることをまず考えてください。
分けると分かりやすいので、コード上でも分けてください。

もちろん、分ける手間はありますが、デバッグの方が手間です。
どうせ今のバグを取りのぞいても、すぐ別のバグが湧いてきますから、
徹底的に分離してテストを書いた方が、結果的には早くできると思います。

最後に、今回の回答で設計の話を中心にしたのは、GAを使うレベルまで来ると、
ソースのIF文やFor文を追うだけでは対処療法でしかなく、
全体の設計ができてないと、正しく動かすのが難しいからです。

投稿 2017/11/25 20:21

編集 2017/11/25 20:44

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/25 21:19 編集

    回答ありがとうございます。
    確かにいっぺんにやるのは無理だと私も感じており、ゲーム云々は置いといてまずは遺伝的アルゴリズムに絞ってやろうとしているところです。
    さらに分離、ということはOriginGeneはルンバの挙動を制御するRunbamoveやプレハブでルンバを作成するRunbaGeneratorのクラスとは別の場所に書いた方がいいということでしょうか?

    キャンセル

  • 2017/11/25 21:38

    >別の場所に書いた方がいいということでしょうか?
    結論から言うとそうですが、
    たんに場所が別というだけでなく、完全に独立させます。

    「Runba」云々の名前や参照が入ってこないようにします。
    GAのドメインにそんな概念はないからです。

    しかしこれは、GAが難しいから分かりにくいかも。そこで、単純な例で考えてみます。

    たとえば、最新の日付のファイルを読み込むときに、
    日付とファイル操作の(クラス)ライブラリ自体は別々で、それを組み合わせて使う、
    自作ライブラリを書くにしても、日付とファイル操作は別々に作る、
    という例なら抵抗なく受け入れられると思うんですよ。

    GAも完全に分離しちゃって、タワーディフェンスの要素が
    【一切入らない】形で作ってしまって大丈夫です。
    タワーディフェンス以外にも使えるようになるので、むしろその方が使いやすいです。

    だって、言語の標準ライブラリはすでに使っておられるでしょうが、
    文字列操作とかに、ゲームの要素とか、一切入っていないですよね?
    ゲームで文字列が必要だとしても、外からAPIを叩くだけですよね?

    だから、GAを書くときは、タワーディフェンスのことをスッパリ忘れてしまって、
    まず独立したライブラリとかAPIにすることを、念頭に置いて作りましょう。

    そして、使うときに中を見なくてもよくなるまで抽象化します。
    だって、標準ライブラリは中を見なくても使えますから。

    このOO的なやり方だと、デバッグやテストが劇的に楽になるので、
    とくに難しいと感じる専門領域は、ライブラリ化しましょう。

    キャンセル

  • 2017/11/25 21:53

    言葉が足りず申し訳ありません、遺伝的アルゴリズムは遺伝的アルゴリズムでGeneAlgorithm.csという名前のファイルで独立させて書くつもりであり、只今その方向でスクリプトを組もうとしているところです。
    そこで配列の仕様がわからないという壁に当たりました。

    キャンセル

  • 2017/11/25 22:10

    >配列の仕様がわからない
    それなら、GAを組む前に、C#の仕様を少し調べると良いと思います。
    C#はメジャーな言語で情報も多いので、ネットや本で調べてください。

    結局、理解が中途半端なままだと、GAが原因か、C#が原因か、
    問題が混ざってしまって、また別の機会にデバッグで苦しみますから。
    今、目の前で詰まってる部分だけが気になるでしょうが、調べた方が早いです。

    たとえると、かけ算の九九を飛ばして、いきなり微積分ができないように、
    GAレベルをやるなら、配列のような基本仕様くらいは、押さえておきましょう。

    キャンセル

  • 2017/11/25 22:40

    ですよね…新たに本を探して調べるとします。
    拙い日本語ながら付き合ってくださって本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.36%

関連した質問

同じタグがついた質問を見る

  • C#

    4777questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    2308questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。