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

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

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

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

Unity

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

3668閲覧

【Unity】配列変数に代入しようとするとフリーズする

kimityan555

総合スコア7

C#

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

Unity

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2017/12/03 06:51

編集2017/12/04 03:37

###前提・実現したいこと
Unityで車を動かす実験をしています。
WheelColliderなどですでにトルクをかけれているので後は、MT車を再現するべくエンジンの回転数とアクセル開度から出力トルクを求めれるようにしたいと思っています。
そこで、CSVファイルにそのデータを大雑把にまとめたマップファイルを作って、それを配列変数に読み込もうとしたのですが、変数への代入時にフリーズしてしまいます。

後述するソースコードのうち、先頭の変数がマップを代入したい変数、最後の二重Forの中のTorqueMap[i,j] = というのがフリーズする行です。

CSVファイルは縦11、横5のデータで、読み込み自体はできています。

###発生している問題・エラーメッセージ
実行すると初期化中にUnity自体がフリーズしてしまいます。
コメントアウトを使ってフリーズした個所を調べたところ先ほどの行に行きつきました。
エラーメッセージ等は一切出てきません。
出てくる前にフリーズです。

###該当のソースコード

C#

1public float[,] TorqueMap; 2public string FilePath; 3 4void Start () { 5 //MapFileに読み込み 6 StreamReader MapFile = newStreamReader(Application.dataPath +FilePath); 7 //読み込んだデータをstring型に変換 8 string MapStr = MapFile.ReadToEnd( ); 9 System.StringSplitOptions option =StringSplitOptions.RemoveEmptyEntries; 10 11 //行ごとに分ける 12 string [ ] lines = MapStr.Split(new char [ ] { '\r', '\n' }, option); 13 //カンマ分けの準備(区分けする文字を設定する) 14 char [ ] spliter = new char [1] { ',' }; 15 //行数 16 int h = lines.Length; 17 //列数 18 int w = lines[0].Split(spliter, option).Length; 19 20 21 //配列の要素数を宣言 22 Debug.Log (h + "," + w); 23 TorqueMap = new float[h , w]; 24 25 //行データを切り分けて,2次元配列へ変換する 26 for(int i = 0; i < 4; i++) 27 { 28 string [ ] splitedData = lines [i].Split(spliter, option); 29 for(int j = 0; j < 4; j++) 30 { 31 TorqueMap [i, j] = int.Parse(splitedData [j]); 32 } 33 } 34}

###試したこと
フリーズした行を

c#

1TorqueMap [1, 1] = int.Parse(splitedData [j]);

のようにしたところ動作しました。
しかし動作はするのですが「IndexOutOfRangeException: Array index is out of range.」というエラーが常に出続けています。

c#

1TorqueMap = new float[h , w];

という行を

c#

1TorqueMap = new float[11 , 5];

としても同じでした。

配列の数を決定するときの変数h、wをデバッグで表示させても11、5で問題はなかったです。

###補足情報
Unityは最新版で、スプリクトエディタにはMonoDevelopを使っています。
言語はC#です。

C言語自体は3年ほど遊んでますが、Unityは初めて1か月程度でいまだに独特の文法に慣れていません。
Unityで配列変数を使ったのは今回が初めてで、宣言の時点で結構躓いてます。

おそらくとっても単純なミスな気がしますが、3時間にらめっこしても自分にはわかりませんでした。

###追加
TorqueMapを利用する関数

c#

1//エンジンの駆動トルクを配列から算出する 2public float EngineTorque(float RPM, float Axel) 3{ 4 float Axel0, Axel50, Axel100; 5 int i = 0; 6 7 //配列の中からRPMの次に大きい回転数を探す 8 while (true) 9 { 10 if (TorqueMap [i, 0] <= RPM) { 11 i++; 12 } 13 } 14 //開度ごとにトルクを算出 15 Axel0 = TorqueMap[i - 1,1] + (TorqueMap[i,1] - TorqueMap[i - 1,1]) * RPM / (TorqueMap[i,0] - TorqueMap[i - 1,0]); 16 Axel50 = TorqueMap[i - 1,2] + (TorqueMap[i,2] - TorqueMap[i - 1,2]) * RPM / (TorqueMap[i,0] - TorqueMap[i - 1,0]); 17 Axel100 = TorqueMap[i - 1,3] + (TorqueMap[i,3] - TorqueMap[i - 1,3]) * RPM / (TorqueMap[i,0] - TorqueMap[i - 1,0]); 18 //Axelに応じた値を出力 19 if (Axel < 0.5) { 20 return Axel0 + Axel50 * Axel * 2; 21 } else { 22 return Axel50 + Axel100 * Axel * 2; 23 } 24} 25 26//エンジンの抵抗を配列から算出する 27public float EngineResistanceTorque(float RPM) 28{ 29 int i = 0; 30 31 //配列の中からRPMの次に大きい回転数を探す 32 while (true) 33 { 34 if (TorqueMap [i, 0] <= RPM) { 35 i++; 36 RPM = RPM - 500; 37 } 38 } 39 i = 5; 40 //抵抗をトルクを算出 41 return TorqueMap[i - 1,3] + (TorqueMap[i,3] - TorqueMap[i - 1,3]) * RPM / (TorqueMap[i,0] - TorqueMap[i - 1,0]); 42} 43 44//エンジンの回転状態、タイヤへの出力をシミュレーションする 45public float EngineOutputTorque(float GearRaito_T, float GearRaito_F, float Axel, float Clutch) 46{ 47 return EngineTorque (EngineRPM, Axel) * Clutch * GearRaito_T * GearRaito_F; 48 //EngineRPM = EngineRPM + (EngineTorque (EngineRPM, Axel) - EngineTorque (EngineRPM, Axel) * Clutch * GearRaito_T * GearRaito_F - EngineResistanceTorque(EngineRPM)) / 8f * 10f * 35f * 180f / 3.14f; 49 EngineRPM = 1000; 50}

外部から呼び出されるのはEngineOutputTorqueのみです。
上の二つは配列のがばがばなデータからそれらしい値を計算して出すようにしたつもりのプログラムでたぶん式は間違っています。
EngineOutputTorqueの式も、とりあえず頭の中の理論で組み立てたもので、おそらく間違っています。

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

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

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

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

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

fiveHundred

2017/12/03 09:31

私の環境で試してみましたが、csvがそのままでは読み込めないぐらいで、特にフリーズするようなことはありませんでした。試しにcsvをStreamingAssetsディレクトリへ移動し、「StreamReader MapFile = newStreamReader(Application.dataPath +FilePath);」を「StreamReader MapFile = new StreamReader(Application.streamingAssetsPath + "/" + FilePath);」にしてみてください。それでも直らない場合は、記載していない箇所やcsv自体に問題がありそうな気がします。特に、Start()は一度しか呼ばれないはずなのに、エラーが「常に出続ける」のは違和感を感じますので、Start()以外にTorqueMapを使っている箇所はないか確かめてください。
kimityan555

2017/12/03 13:17 編集

StreamingAssetsにデータを移して動かしてみました。 それでもやっぱり変わりませんでした。 エラーが大量に吐き出されているのは、作成した配列をもとにデータを出力する計算部分です。 TorqueMapを常に参照しているためだと思うのですが、どの値を参照してもエラーが出っぱなしです。 いままでC++ではこんなことなかったのですが、何となく配列自体がうまく宣言されていない感じがします。
fiveHundred

2017/12/04 01:05

そうだとすると、その計算部分やそれ以降の処理に問題があるのではないかと思います。念のためその処理を行っているソースも記載してください。(Unityではエラーが出るとその場で関数が終了する仕様なので、エラーが出ると関数は終了するためフリーズしないが、逆に正常だとそうならずフリーズするような処理が行われてしまうという考えです)
guest

回答1

0

ベストアンサー

単純に無限ループしてません?

C#

1while (true) 2{ 3 if (TorqueMap [i, 0] <= RPM) { 4 i++; 5 RPM = RPM - 500; 6 } 7}

投稿2017/12/04 03:45

ozwk

総合スコア13512

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

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

kimityan555

2017/12/04 05:36

あっ…確かにそうですね… 抜け出す処理を書き忘れてました。 ただ、追加しても動作は変わりませんでした。 動作したところでここは無限ループだったのでしょうが、 そこで、CSVの中身をそのまま配列変数の初期化のところに書き込んだところ、式がおかしいせいで、出力される値はめちゃくちゃですが、動作はしました。 エラーも、使っていない変数があるというもの以外出ていません。 配列の数を調べてもちゃんと11,5で宣言されており、iとjを整数に置き換えれば、フリーズすることなくどこにでも書き込めました。
ozwk

2017/12/04 08:02

TorqueMap [i, j] = int.Parse(splitedData [j]); の前辺りでsplitedData [j]の内容を表示してみて、数字以外の文字列や空文字、空白になっていませんか?
kimityan555

2017/12/04 13:22

その行をコメントアウトして Debug.Log (int.Parse(splitedData [j]))としてみましたが、すべて配列通りの結果が返ってきました。 そこでもう一度問題の行のコメントアウトを外したところ、正常に動作しました。 宣言だけして、初期化をしていなかったからいけなかったのかと思い、配列の初期化を消して、元に戻したのですが、それでも動作し、もともとのプログラムに戻しても動きました。 原因はわからないですが、Unity側のバグだったのだと思われます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問