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

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

新規登録して質問してみよう
ただいま回答率
85.53%
C#

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

27820閲覧

【Unity】実行ボタンを押すとフリーズしてしまう

intenseG

総合スコア34

C#

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

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

2グッド

2クリップ

投稿2017/03/31 06:19

###前提・実現したいこと
囲碁の詰碁問題(将棋でいうところの詰将棋)を出題するアプリを制作中なのですが、ある日、Unityで実行ボタンを押した途端メモリ使用率が97%以上に跳ね上がり、パソコンがフリーズしてしまいました。

そこで、グーグル大先生にお尋ねしてみたところ**「無限ループしてる」「処理が重い」**というのが原因の候補にあがってきたのですが、、

まず、無限ループしている箇所がないかを確認しましたが、ありませんでした。
となると「処理が重い」というのが原因だと思うのですが、どの箇所の処理が重いのかが全く検討もつかず途方に暮れています。

Unity画面

###発生している問題
実行するとメモリ使用率が97%以上に跳ね上がり、フリーズしてしまいます。

###ソースコード

C#

1public class TsumegoManager : MonoBehaviour 2{ 3 int panelCountX = 0; //横の石数 4 int panelCountY = 0; //縦の石数 5 public GameObject stonePrefab; //石のひな型 6 7 public GameObject panelBasePosi; //生成した石を置く親オブジェクト 8 List<StoneManager> stoneList; //生成した石のスクリプトリスト 9 10 List<List<int>> correctArray; //正解配置格納リスト(複数) 11 List<int> selectArray; //選択配置格納リスト(偶数黒 奇数白) 12 int pushIndex = 0; //選択インデックス(偶数黒 奇数白) 13 14 public Image correctImg; //正解画像 15 public Image wrongImg; //不正解画像 16 public Image blockImg; //画面タップ防止用画像 17 18 void Start() 19 { 20 //石のリストと配置リストを初期化 21 stoneList = new List<StoneManager>(); 22 selectArray = new List<int>(); 23 24 //配置する石数 25 panelCountX = 4; 26 panelCountY = 8; 27 28 //ステージの問題(左上からの石の並びを1次元配列で表現) 29 string stageInfo = "0,0,0,0,2,2,2,2,2,1,1,0,2,1,0,0,2,0,1,0,0,2,1,0,0,2,1,0,0,2,2,2,0,0,0,0"; 30 //カンマで分割 31 string[] stageArray = stageInfo.Split(','); 32 33 //正解用配列を生成 34 correctArray = new List<List<int>>(); 35 //解答手順をあるだけ生成して格納 36 List<int> correct1 = new List<int> { 104, 143, 130 }; 37 correctArray.Add(correct1); 38 39 //1パネルのサイズ 40 float panelWid //元は60.0fth = 53; 41 42 //一番左上のポジション 43 float panelInitPosiX = 0.0f; 44 float panelInitPosiY = 0.0f; 45 panelInitPosiX = -1.0f * panelWidth * (panelCountX / 2.0f - 0.5f); 46 panelInitPosiY = 1.0f * panelWidth * (panelCountY / 2.0f - 0.5f); 47 Debug.Log(panelInitPosiX); 48 Debug.Log(panelInitPosiY); 49 50 //石の配置(左上から右上 一段下がって左からの順序) 51 //縦 52 for (int i = 0; i < panelCountY; i++) 53 { 54 //横 55 for (int j = 0; j < panelCountX; j++) 56 { 57 //石を生成 58 GameObject obj = (GameObject)Instantiate(stonePrefab); 59 //親オブジェクトを設定 60 obj.transform.parent = stonePrefab.transform; 61 //拡大率を1に設定 62 obj.transform.localScale = Vector3.one; 63 //ポジションを設定 64 obj.transform.localPosition = new Vector3(panelInitPosiX + panelWidth * j, panelInitPosiY - panelWidth * i, 0); 65 66 //スクリプトを取得してリストに追加 67 StoneManager stoneManager = obj.GetComponent<StoneManager>(); 68 stoneList.Add(stoneManager); 69 70 //インデックスを算出 71 int index = i * panelCountX + j; 72 73 //ボタンの名前をインデックスにする 74 //ボタン押したときに使います。 75 stoneManager.komaBtn.gameObject.name = index.ToString(); 76 77 //石の設定 78 if (int.Parse(stageArray[index]) == 0) 79 { 80 //石なし タップするボタンが活性 81 stoneManager.setKomaInfo("NONE"); 82 } 83 else if (int.Parse(stageArray[index]) == 1) 84 { 85 //白い石 ボタン非活性 86 stoneManager.setKomaInfo("WHITE"); 87 } 88 else if (int.Parse(stageArray[index]) == 2) 89 { 90 //黒い石 ボタン非活性 91 stoneManager.setKomaInfo("BLACK"); 92 } 93 } 94 } 95 96 //ブロック画像を非表示 97 blockImg.gameObject.SetActive(false); 98 } 99 100 //石のボタンを押下時処理 101 public void pushKoma(GameObject obj) 102 { 103 //タップしたインデックスを取得 104 int tapIndex = int.Parse(obj.name); 105 106 //選択リストに追加(黒) 107 selectArray.Add(tapIndex); 108 109 //黒い石を配置 110 stoneList[tapIndex].setKomaInfo("BLACK"); 111 112 //プッシュ回数を1プラス 113 pushIndex += 1; 114 115 //チェック処理 116 checkKoma(); 117 } 118 119 //チェック処理 120 void checkKoma() 121 { 122 //絞り込んだ新しい配列を生成 123 List<List<int>> nextArray = new List<List<int>>(); 124 125 //複数回答分回す 126 for (int i = 0; i < correctArray.Count; i++) 127 { 128 129 //リストを取得 130 List<int> array = correctArray[i]; 131 132 //1手1手見ていく 133 //1つでも違う手だったら除外 134 bool isOk = true; 135 for (int j = 0; j < pushIndex; j++) 136 { 137 if (selectArray[j] != array[j]) 138 { 139 isOk = false; 140 } 141 } 142 //今の手とすべて同じ場合 143 if (isOk) 144 { 145 //絞り込みのリストに追加 146 nextArray.Add(array); 147 } 148 } 149 150 //絞り込みの件数によって分岐 151 if (nextArray.Count == 0) 152 { 153 //全部不正解 154 wrongImg.enabled = false; 155 blockImg.gameObject.SetActive(true); 156 } 157 else 158 { 159 //クリア判定 160 //絞り込みが1件ですべてタップした場合 161 if (nextArray.Count == 1 && nextArray[0].Count == pushIndex) 162 { 163 //クリア 164 correctImg.enabled = false; 165 blockImg.gameObject.SetActive(true); 166 } 167 else 168 { 169 //残った配列からランダムに選ぶ 170 int random = Random.Range(0, nextArray.Count); 171 List<int> next = nextArray[random]; 172 173 //選択配列に追加(白) 174 selectArray.Add(next[pushIndex]); 175 176 //白い石を設定 177 stoneList[next[pushIndex]].setKomaInfo("WHITE"); 178 179 //プッシュ回数を1プラス 180 pushIndex++; 181 182 //絞り込み配列に入れ替える 183 correctArray = nextArray; 184 } 185 } 186 } 187 188 //もう一度ボタン押下処理 189 public void pushOnce() 190 { 191 //正解or不正解画像を非アクティブにする 192 correctImg.enabled = false; 193 wrongImg.enabled = false; 194 //画面を読み込みなおす 195 SceneManager.LoadScene("Problem"); 196 } 197}

C#

1public class StoneManager : MonoBehaviour 2{ 3 4 public Image blackStoneImg; 5 public Image whiteStoneImg; 6 public Button komaBtn; 7 8 void Start () 9 { 10 11 } 12 13 //石の情報をセット 14 public void setKomaInfo(string kbn) 15 { 16 if (kbn == "WHITE") 17 { 18 //白石の設定 19 whiteStoneImg.gameObject.SetActive(true); 20 komaBtn.gameObject.SetActive(false); 21 } 22 else if (kbn == "BLACK") 23 { 24 //黒石の設定 25 blackStoneImg.gameObject.SetActive(true); 26 komaBtn.gameObject.SetActive(false); 27 } 28 else if (kbn == "NONE") 29 { 30 //石なしの設定 31 whiteStoneImg.gameObject.SetActive(false); 32 blackStoneImg.gameObject.SetActive(false); 33 komaBtn.gameObject.SetActive(true); 34 } 35 } 36}

###試したこと
・時間をあけて実行、日を変えて実行
・2重ループのループ回数を減らす

###補足情報(言語/FW/ツール等のバージョンなど)
Unity歴:1ヶ月
開発ツール:Unity5.5.2f1 Personal(64bit)

【PCスペック】
OS:win7 64bit
CPU:Intel Corei7 3610QM 2.30GHz
RAM:8GB
グラフィックボード:Intel(R) HD Graphics 4000

Apple_Candy, Satokingy👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

以下のコードが原因なんじゃないですか?

//親オブジェクトを設定 obj.transform.parent = stonePrefab.transform;

これだとループする度にプレハブの子要素にオブジェクトが追加されて、Instantiateでそれらの子要素も含めて生成されてメモリを食ってしまうのではないでしょうか?(くわしいことはよくわ)
実際簡易的なコードで試して見たら止まりましたw

投稿2017/03/31 07:49

doubutweet

総合スコア141

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

intenseG

2017/03/31 10:04

指摘の箇所のstonePrefabをpanelBasePosiに修正してみたら実行することができました! ありがとうございました!
guest

0

doubutweet さんがおっしゃっているのが正解だと思います。

//石を生成 GameObject obj = (GameObject)Instantiate(stonePrefab); //親オブジェクトを設定 obj.transform.parent = stonePrefab.transform;

親オブジェクトを設定と書いてありますが、つまり stonePrefab の子オブジェクトを増やすことと同義です。

1ループ目は

stonePrefab └ stonePrefab (Clone 1)

となるでしょうが、2ループ目ではすでに stonePrefabの子要素も一緒に Instantiate されますので

GameObject obj = (GameObject)Instantiate(stonePrefab); の obj には1ループ目でセットされた子要素も含まれ以下のようになります。

stonePrefab └ stonePrefab (Clone 2) └ stonePrefab (Clone 1) <= 1ループ目に生成された子供

for文でループするたびに一度にコピーするオブジェクトが増えていってしまいます。
stonePrefabの他に、親オブジェクトを用意してあげるのが良いと思います。

投稿2017/03/31 10:11

kanitaoru

総合スコア204

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

intenseG

2017/04/01 22:09

分かりやすい説明ありがとうございます! かなり助かりました! 1人で悩んでましたが、質問すれば一発でしたね(汗
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問