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

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

ただいまの
回答率

88.78%

Unity2D Update関数以外でゲームオブジェクトを呼びたい

受付中

回答 1

投稿 編集

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

tomatoma...

score 15

初めに、私は現在Unity2Dでアンドロイドアプリを制作しております。

また、私自身プログラミング初心者ということもあり、ネット上で公開されているソースコードを参考にして作っているため、理解困難な箇所があるかも知れませんが、ご了承お願い致します。

制作中のアプリ内容としてはシューティングゲームを作っています。
また、『プログラム自体は正常に流れています』

しかしながら、実機のアンドロイドにてビルドしテストを行うと動作が重いことに気付きました。

幾つか自分で原因を考えてみたのですが、
『一番の原因はUpdate関数にGameObjectを大量に生成している』
からなのではないかと思っています。

そのコードを以下に記載させて頂きます。

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

using UnityEngine.UI;
using CompletedAssets;


namespace CompletedAssets
{

    public class boss1_move : MonoBehaviour
    {
        public GameObject boss0_bullet_prefab;
        private int shot_time;//生存、発射時間
        private float rad;    //弾用角度
        private float rad2;   //弾用角度2
        private float rad3;   //弾用角度3

        // ヒットポイント
        public int hp;

        // スコアのポイント
        public int point = 100;

        private Slider slider;

        // Spaceshipコンポーネント
        SpaceshipBoss spaceship;

        //void Start()
        IEnumerator Start()
        {
            // boss_t = 100; //ボス体力初期設定
            shot_time = 0;//生存、発射時間初期設定
            rad = 0f;//弾用角度初期設定
            rad2 = 0f;//弾用角度2初期設定

            slider = GameObject.FindGameObjectWithTag("EnemyHPSlider1").GetComponentInChildren<Slider>();

            slider.maxValue = hp;

            // スライダーの現在値の設定
            slider.value = hp;


            // Spaceshipコンポーネントを取得
            spaceship = GetComponent<SpaceshipBoss>();

            // canShotがfalseの場合、ここでコルーチンを終了させる
            //if (spaceship.canShot == false)
            if (hp <= 0)
            {
                yield break;
            }

        }

        void Update()
        {

            if (shot_time > 1 && shot_time < 99)
            {
                transform.Translate(0, -0.018f, 0);//移動
            }

            if (shot_time > 100 && shot_time < 1200)
            {
                if (shot_time % 5 == 0)
                {
                    Vector2 e0 = transform.position;//自機と敵の角度計算
                    float etx = Player.pos - e0.x;//自機と敵の角度計算
                    float ety = Player.pos - e0.y;//自機と敵の角度計算
                    rad = Mathf.Atan2(ety, etx);//自機と敵の角度計算

                    for (float ang = -7.8f; ang <= -5.4f; ang += 0.4f)//自機狙い6方向弾幕(1フレームに6発発射)青弾用
                    {
                        GameObject shot = Instantiate(boss0_bullet_prefab, transform.position, transform.rotation) as GameObject;//敵弾生成
                        boss0_bullet_move s = shot.GetComponent<boss0_bullet_move>();//boss0_bullet_moveスクリプトを取得
                        s.Create_rad_ds_bu_ex_ey(rad + ang + 0.1f, 0.1f, 0, 2.4f, -0.5f);//boss0_bullet_moveスクリプトのCreate_rad_ds_bu_ex_ey関数に弾の初期情報を渡す
                    }

                    for (float ang2 = -7.8f; ang2 <= -5.4f; ang2 += 0.4f)//自機狙い6方向弾幕(1フレームに6発発射)ピンク弾用
                    {
                        GameObject shot = Instantiate(boss0_bullet_prefab, transform.position, transform.rotation) as GameObject;//敵弾生成
                        boss0_bullet_move s = shot.GetComponent<boss0_bullet_move>();//boss0_bullet_moveスクリプトを取得
                        s.Create_rad_ds_bu_ex_ey(rad - ang2 - 0.15f, 0.1f, 1, -2.4f, -0.5f);//boss0_bullet_moveスクリプトのCreate_rad_ds_bu_ex_ey関数に弾の初期情報を渡す
                    }
                }
                if (shot_time % 16 == 0)//8方向回転弾幕(1フレームに8発発射)
                {
                    for (rad = 0f; rad < 6.28f; rad += 0.8f)//弾発射角度が6.28になるまで発射、6.28で一回転(3.14の2倍)青弾用
                    {
                        GameObject shot = Instantiate(boss0_bullet_prefab, transform.position, transform.rotation) as GameObject;//敵弾生成
                        boss0_bullet_move s = shot.GetComponent<boss0_bullet_move>();//boss0_bullet_moveスクリプトを取得
                        s.Create_rad_ds_bu_ex_ey(rad + rad2, 0.1f, 0, 0, 0);//boss0_bullet_moveスクリプトのCreate_rad_ds_bu_ex_ey関数に弾の初期情報を渡す
                    }
                    rad2 += 0.5f;//発射角度プラス
                    for (rad = 0f; rad < 6.28f; rad += 0.8f)//弾発射角度が6.28になるまで発射、6.28で一回転(3.14の2倍)ピンク弾用
                    {
                        GameObject shot = Instantiate(boss0_bullet_prefab, transform.position, transform.rotation) as GameObject;//敵弾生成
                        boss0_bullet_move s = shot.GetComponent<boss0_bullet_move>();//boss0_bullet_moveスクリプトを取得
                        s.Create_rad_ds_bu_ex_ey(rad + rad3, 0.1f, 1, 0, 0);//boss0_bullet_moveスクリプトのCreate_rad_ds_bu_ex_ey関数に弾の初期情報を渡す
                    }
                    rad3 -= 0.5f;//発射角度マイナス
                }
            }

            shot_time += 1;
            if (shot_time >= 1300) shot_time = 100;//ボスの行動を8方向回転弾幕に戻す

        }

        void OnTriggerEnter2D(Collider2D c)
        {
            // レイヤー名を取得
            string layerName = LayerMask.LayerToName(c.gameObject.layer);

            // レイヤー名がBullet (Player)以外の時は何も行わない
            if (layerName != "Bullet (Player)")
                return;

            // PlayerBulletのTransformを取得
            Transform playerBulletTransform = c.transform.parent;

            // Bulletコンポーネントを取得
            Bullet bullet = playerBulletTransform.GetComponent<Bullet>();

            // ヒットポイントを減らす
            hp = hp - bullet.power;

            // ★(追加)この一行を追加しないとスライダーバーの目盛りが変化しません!
            slider.value = hp;

            // 弾の削除
            Destroy(c.gameObject);


            // ヒットポイントが0以下であれば
            if (hp <= 0)
            {
                // スコアコンポーネントを取得してポイントを追加
                FindObjectOfType<Score>().AddPoint(point);

                // 爆発
                spaceship.Explosion();

                // エネミーの削除
                Destroy(gameObject);

                 Destroy(transform.root.gameObject);

            }
              else
               {
            // Damageトリガーをセット
                spaceship.GetAnimator ().SetTrigger ("Damage");

                }
        }


          void OnTriggerEnter2D(Collider2D coll)//当たり判定
          {
              if (coll.tag == "ship_bullet")//自機弾が当たった時
              {
                  Destroy(coll.gameObject);//自機弾削除
                  boss_t -= 1;//ボス体力マイナス
                  if (boss_t <= 0)//体力が0になったら
                  {
                      Destroy(gameObject);//ボス削除
                      for (int i = 0; i < 50; i++)
                      {
                          Instantiate(explosion_prefab, new Vector3(-4f + 8f * Random.value, 0f + 4f * Random.value, 0), Quaternion.identity);//爆破表示
                      }
                      //  time_table.game_time = 0;//ゲーム時間を最初に戻す
                      Destroy(gameObject);
                  }
          GameObject.Find("Canvas").GetComponent<UIcontroller>().AddScore();//得点プラス
              }

          }
   }
}

以上がコードとなります。

試したこと

・FPSのターゲットを60に設定
→効果はあったが、(shot_time > 100 && shot_time < 1200)の処理中にFPSが100を超える。

・クオリティ設定を低く変更
→効果の実感なし

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

+1

原因を見つけたい場合はMemory Profilerを使いましょう。
実機とつなげて確認すればどこで処理が跳ね上がっているか見ることができます。(スクリプト側の負荷なのか、グラフィック側の負荷なのかなど)
https://docs.unity3d.com/ja/2019.4/Manual/ProfilerMemory.html

もしくは一旦機能をオミットするのも手です。ボスが弾を撃ってこない設定で動かしたら軽くなるかを確認します。

ひたすらインスタンス化しているのが問題なようだったら
この手のゲームでまず思いつくのは弾のオブジェクトプールです。ひたすらインスタンス化するのではなく必要な分だけ作ってあとは使い回すやり方になります。
画面外に出たものや、なにかにあたったものはDestroyするのではなく非表示にして保管しておきます。弾をインスタンス化する際に保管してある弾があればそちらを再利用するという考え方です。

第01回 オブジェクトプーリング
https://github.com/unity3d-jp-tutorials/2d-shooting-game/wiki/%E7%AC%AC01%E5%9B%9E-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%83%97%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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