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

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

ただいまの
回答率

91.37%

  • C#

    4749questions

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

  • Unity

    2287questions

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

  • Unity3D

    779questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

【Unity】配列で取得したオブジェクトのスクリプトをまとめて実行したい

解決済

回答 2

投稿 2017/11/22 02:35

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

jum6948

score 10

前提・実現したいこと

配列を使って、オブジェクトを選択してまとめてスクリプトを実行させたい。
今回の場合だと、イベントフラグのあるコライダーに入った時、まとめてつららが4本落ちてくる。

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

今、書いているコードだと以下のエラーが出ます。

'Gameobject[]''GetComponents'の定義が含まれておらず、型'Gameobject[]'最初の引数を受け付ける拡張メソッドが見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。

該当のソースコード

C#で作っております。
【イベントフラグ】

public class EventBall_Turara : MonoBehaviour {

    [Header("反応時間")]
    public float t;
    public GameObject[] refObj;

    void OnTriggerEnter(Collider Collider)
    {

        //プレイヤーが範囲にいる間
        if (Collider.gameObject.tag == "Player")
        {
            t = 0;
        }
    }

    void OnTriggerStay(Collider Collider)
    {

        t += Time.deltaTime;

        //プレイヤーが範囲にいる間
        if (Collider.gameObject.tag == "Player")
        {
            AtackTurara a = refObj.GetComponents<AtackTurara>();
            if (a != null)
            {
                a.TuraraOn();
                Debug.Log("ざn");
            }
        }
    }
}


【つらら自身のプログラム】

public class AtackTurara : MonoBehaviour
{

    [Header("Effect")]
    public GameObject IceHit;       //つららが削れるエフェクト
    public GameObject IceBreak;     //つらら爆破
    public AudioClip BreakSe;
    protected GameObject clone;
    AudioSource aud;
    Rigidbody rb;
    GameObject GDirector;

    [Header("岩の能力")]
    public int HitPoint;
    public int HitPointMax = 50;
    public bool isDead = false;     //つららはこわれていないか?
    public bool isZimen = false;
    public bool isTuraraOn = false;
    int damage;

    [Header("生存時間")]
    public float liveTime;
    public float t;

    [Header("足音")]
    public AudioClip foot_iwa;          //土
    public AudioClip foot_water;        //水1
    public AudioClip foot_sand;         //砂
    public AudioClip foot_snow1;        //雪1
    public AudioClip foot_snow2;        //雪2

    public Quaternion TuraraRote;     //Yattackのエフェクトの角度

    // Use this for initialization
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        this.aud = gameObject.GetComponent<AudioSource>();
        GDirector = GameObject.Find("GameDirector");
        HitPoint = HitPointMax;
        rb.isKinematic = true;
    }
    void Update()
    {
        //体力が0以下になったら消滅する
        if (HitPoint <= 0)
        {
            //死亡判定有効
            isDead = true;
            Destroy(this.gameObject, 0.5f);
        }
        if (isTuraraOn ==true)
        {
            //重力
            rb.AddForce(Vector3.down * 7000);
        }


        //clone = Instantiate(IceBreak, transform.position, Rote);
    }

    public void TuraraOn()
    {
        isTuraraOn = true;
        rb.isKinematic = false;
    }

    private void OnCollisionEnter(Collision collider)
    {
        int r = Random.Range(0, 2);

        //何かに触れたら?
        if (collider.gameObject.tag == "Zimen_Tuti" ||
            collider.gameObject.tag == "Zimen_Isi"  ||
            collider.gameObject.tag == "Zimen_Wood" ||
            collider.gameObject.tag == "Zimen_Kusa" ||
            collider.gameObject.tag == "Zimen_Water"||
            collider.gameObject.tag == "Zimen_Sand" ||
            collider.gameObject.tag == "Zimen_Snow" ||
            collider.gameObject.tag == "Player"
            )
        {
            t = 0;
            isZimen = true;
        }
        //地面に刺さった時関連
        if (collider.gameObject.tag == "Zimen_Tuti" ||
            collider.gameObject.tag == "Zimen_Isi" ||
            collider.gameObject.tag == "Zimen_Wood" ||
            collider.gameObject.tag == "Zimen_Kusa" ||
            collider.gameObject.tag == "Player"
            )
        {
            this.aud.PlayOneShot(foot_iwa, 1F);
        }
        else if (collider.gameObject.tag == "Zimen_Water")
        {
            this.aud.PlayOneShot(foot_water, 1F);
        }
        else if (collider.gameObject.tag == "Zimen_Sand")
        {
            this.aud.PlayOneShot(foot_sand, 1F);
        }
        else if (collider.gameObject.tag == "Zimen_Snow")
        {
            if (r == 0)
            { // ランダムA
                this.aud.PlayOneShot(foot_snow1, 1F);
            }
            else if (r == 1)
            { // ランダムB
                this.aud.PlayOneShot(foot_snow2, 1F);
            }
        }

        //Playerと衝突したら消滅させる
        if (collider.gameObject.tag == "Player")
        {
            Destroy(this.gameObject, 0.5f);
        }

        //矢攻撃
        if (collider.gameObject.tag == "Arrow" ||
            collider.gameObject.tag == "WayArrow" ||
            collider.gameObject.tag == "WayExArrow")
        {//矢攻撃の攻撃判定に当たった時

            if (collider.gameObject.tag == "Arrow")
            {
                //ArrowMoveからダメージの値を取得する
                damage = collider.gameObject.GetComponent<ArrowMove>().damage;
            }
            if (collider.gameObject.tag == "WayArrow")
            {
                //ArrowWayMoveからダメージの値を取得する
                damage = collider.gameObject.GetComponent<ArrowWayMove>().damage;
            }
            if (collider.gameObject.tag == "WayExArrow")
            {
                //ArrowWayExMoveからダメージの値を取得する
                damage = collider.gameObject.GetComponent<ArrowWayExMove>().damage;
            }
            //判定が触れた所にエフェクト発生   
            foreach (ContactPoint point in collider.contacts)
            {
                //ダメージ量に応じてボイス変更
                GameObject effect1 = Instantiate(IceHit) as GameObject;
                effect1.transform.position = (Vector3)point.point;
                Destroy(effect1, 1.0f);
                rb.velocity += ((Vector3)point.point * 5.1f) / rb.mass;
            }

            //攻撃判定衝突したらダメージ
            HitPoint -= damage;

        }
        //剣攻撃1
        if (collider.gameObject.tag == "Blade_Hit1")
        {
            foreach (ContactPoint point in collider.contacts)
            {
                GameObject effect1 = Instantiate(IceHit) as GameObject;
                effect1.transform.position = (Vector3)point.point;
                Destroy(effect1, 1.0f);

                rb.velocity += ((Vector3)point.point * 25.1f) / rb.mass;
            }

            //ダメージをランダムで変える
            damage = Random.Range(100, 150);

            //攻撃判定衝突したらダメージ
            HitPoint -= damage;
        }
        //剣攻撃2
        if (collider.gameObject.tag == "Blade_Hit2")
        {
            foreach (ContactPoint point in collider.contacts)
            {
                GameObject effect1 = Instantiate(IceHit) as GameObject;
                effect1.transform.position = (Vector3)point.point;
                Destroy(effect1, 1.0f);

                rb.velocity += ((Vector3)point.point * 25.1f) / rb.mass;
            }

            //ダメージをランダムで変える
            damage = Random.Range(200, 250);

            //攻撃判定衝突したらダメージ
            HitPoint -= damage;
        }
        //剣攻撃3
        if (collider.gameObject.tag == "Blade_Hit3")
        {
            foreach (ContactPoint point in collider.contacts)
            {
                GameObject effect1 = Instantiate(IceHit) as GameObject;
                effect1.transform.position = (Vector3)point.point;
                Destroy(effect1, 1.0f);

                rb.velocity += ((Vector3)point.point * 25.1f) / rb.mass;
            }

            //ダメージをランダムで変える
            damage = Random.Range(500, 1000);

            //攻撃判定衝突したらダメージ
            HitPoint -= damage;
        }
        //バッシュ攻撃
        if (collider.gameObject.tag == "Bash")
        {
            foreach (ContactPoint point in collider.contacts)
            {
                GameObject effect1 = Instantiate(IceHit) as GameObject;
                effect1.transform.position = (Vector3)point.point;
                Destroy(effect1, 1.0f);

                rb.velocity += ((Vector3)point.point * 25.1f) / rb.mass;
            }

            //ダメージ与える
            damage = 150;

            //プレイヤーの弾と衝突したらダメージ
            HitPoint -= damage;
        }
    }

    private void OnCollisionStay(Collision collider)
    {
        //地面に刺さったら?
        if (collider.gameObject.tag == "Zimen_Tuti" ||
            collider.gameObject.tag == "Zimen_Isi" ||
            collider.gameObject.tag == "Zimen_Wood" ||
            collider.gameObject.tag == "Zimen_Kusa" ||
            collider.gameObject.tag == "Zimen_Water" ||
            collider.gameObject.tag == "Zimen_Sand" ||
            collider.gameObject.tag == "Zimen_Snow" ||
            collider.gameObject.tag == "Player"
            )
        {
            t += Time.deltaTime;

            //地面に刺さってliveTime秒経過したら
            if (t > liveTime)
            {
                //時間とともに消滅
                Destroy(this.gameObject);
            }
        }


    }
    //壊れる時、地面にささるか破壊された場合
    void OnDestroy()
    {
        //死んでいると
        if (isDead == true || isZimen == true)
        {
            EDead();
        }
    }
    //破壊時エフェクト表示
    void EDead()
    {
        if (clone == null)
        {
            this.aud.PlayOneShot(this.BreakSe);

            Vector3 pos = transform.position;
            pos.y += 3.5f;
            transform.position = pos;

            clone = Instantiate(IceBreak, transform.position, TuraraRote) as GameObject;
        }
    }
}

試したこと

【1】
手段を選ばなければ【GameObject[] refObj】;を使用せずに【refObj0】、【refObj1】、【refObj2】、【refObj3】を作って、同じスクリプトを4回実行することで動作はしました。
でも、これは違う気がします。

【2】
public int x;
AtackTurara a = refObj[x].GetComponent<AtackTurara>();
で、inspectorで同じ数字を設定したものの、動作せず。

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

【制作環境】 
Unity5.6.1f1 personal 
win10 
MicrosoftVisualStudio
つららのコードじゃなく、おそらく、イベントフラグがおかしいと思って入るのですが、つららのコードにリストされるのを許可するコードが必要なのかな?とも考えてみたり・・・。
やり方がわからないので、見当違いな質問をしていたら申し訳ありません。
よろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

GameObject[]は「GameObjectの配列」です。
GetComponentsは「対象のGameObjectに付いた指定のコンポーネントを全て取得する」メソッドなので、配列に対しては使用出来ません。

AtackTurara a = refObj[x].GetComponent<AtackTurara>();
本来ならこれで動作するはずです。(エラーが出ているなら提示してもらえると解決しやすいです)

その他の方法として、全てのつららオブジェクトを1つの親オブジェクトの子としておき、
親オブジェクトに対してGetComponentsInChildrenをすることでも一括取得出来ます。
Unityのコンポーネントを一括で取得する | Unityを使った3Dゲームの作り方(かめくめ)
(リンク先のコードはJavascriptなので適宜C#に読み替えてください)

投稿 2017/11/22 10:38

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/22 12:02

    つららの数が4なので、4にすると・・・

    IndexOutOfRangeException: Array index is out of range.
    EventBall_Turara.OnTriggerStay (UnityEngine.Collider Collider) (at Assets/Scripts/EventBall_Turara.cs:31)

    31行目
    AtackTurara a = refObj[x].GetComponent<AtackTurara>();

    プログラムの世界では、0が1だったのを思い出して、数字を変更して、動くには動いたのですが、xの指定した番号のみが落下するという結果になりました。
    x=0 ツララ0、x=1 ツララ1、x=2 ツララ2、x=3 ツララ3・・・

    MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
    Your script should either check if it is null or you should not destroy the object.
    UnityEngine.GameObject.GetComponent[AtackTurara] () (at C:/buildslave/unity/build/artifacts/generated/common/runtime/GameObjectBindings.gen.cs:38)
    EventBall_Turara.OnTriggerStay (UnityEngine.Collider Collider) (at Assets/Scripts/EventBall_Turara.cs:31)

    xが無いのにアクセスしてるぞって言ってるので、それを無理やり解決してみました。

    //プレイヤーが範囲にいる間
    if (Collider.gameObject.tag == "Player")
    {
    if (x > -1) {
    AtackTurara a = refObj[x].GetComponent<AtackTurara>();
    a.TuraraOn();
    if (a != null)
    {
    x -= 1;
    Debug.Log("ざn");
    }
    }
    }
    動作するようになりました!
    ・・・が、動作はしますが、この記述が正しいのかは、少し疑問は残ります。
    最終的にはつららを同時には落とそうとは思っていないのですが、前段階として乗ったら全て同時に落ちてきてほしいので、この動作は理想ではありません。
    (最終的にはつらら側のコードで落下までの時間を指定したい)

    お時間がよろしければいいので、sakura_hanaさんのご意見を賜りたいです。

    キャンセル

  • 2017/11/22 12:03

    ごめんなさい、後半の、インデントがおかしくなりました。

    キャンセル

  • 2017/11/24 09:48

    返答遅れて申し訳無いです。
    配列の中身を操作する場合、通常はforかforeachを使います。

    int size = refObj.length;
    for(int i=0; i < size; i++){
    refObj[i].GetComponent<AtackTurara>().TuraraOn();
    }

    foreach (GameObject item in refObj) {
    item.GetComponent<AtackTurara>().TuraraOn();
    }

    他、Linqという発展系もありますがプラットホームによってはエラーが出たりしますのでご自分で調べて頂けると幸いです。

    なお、負荷的にはいちいちGetComponentさせるべきではないので、
    可能ならGameObjectの配列ではなくAtackTuraraの配列にするとよいかと思います。

    キャンセル

  • 2017/11/27 12:09

    返答、ありがとうございます!
    いつも多角的な視点からの回答誠に感謝しております。
    配列の数字を取得する方法が今回が「int size = refObj.length;」という方法というのが勉強できて大変感謝しております。

    コードを持っているオブジェクトをそのまま配列することが出来るんですね。
    回答していただいた
    foreach (GameObject item in refObj) {
    item.GetComponent<AtackTurara>().TuraraOn();
    }
    をアドバイスしていただいたように書き換えたら動作しました。
    public AtackTurara[] refObj;
    foreach (AtackTurara item in refObj)
    {
    if (item != null)
    {
    item.TuraraOn();
    }
    }

    sakura_hanaさんの回答は、ただの回答じゃなく、いつもひとつふたつと、ステップアップできるすばらしい回答なので、大変感謝しております。今回もありがとうございました。
    teratailは、返答にも高評価できる機能が欲しいです。とりあえず、ワタクシの心のスコアを+1させて頂きます。

    キャンセル

0

refObj配列が初期化されてないように思うのですが、どうでしょうか?
C#私的超入門#1 配列

投稿 2017/11/22 09:06

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/22 10:40

    Unityの場合、publicな基本クラスの配列は勝手に初期化され、インスペクター上で初期値設定が出来ます。

    キャンセル

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

ただいまの回答率

91.37%

関連した質問

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

  • C#

    4749questions

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

  • Unity

    2287questions

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

  • Unity3D

    779questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。