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

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

新規登録して質問してみよう
ただいま回答率
87.20%
Unity

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

受付中

unity for文の処理について

BRAK
BRAK

総合スコア0

Unity

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

0回答

0評価

0クリップ

549閲覧

投稿2021/03/07 03:05

編集2022/01/12 10:55

マップ生成時のfor文の処理について

2Dゲームでマップ生成時に縦11横18の文字コード × 9 回を読み込んでfor文を回してマップを生成したのですが、ビルドしたら
マップが生成されなかったのですが、これは処理が間に合わなかったということでしょうか。

処理順を変えたら、プレイヤーが生成される時とされない時があったので、恐らく処理が間に合わなかったのだと思います。

また、読み終わるまで処理を続けたいのですが、どうすればよろしいでしょうか。

考えていることは、
・スクリプトを9個に分けて個々で処理をさせる
・描画するマップ位置のみ生成する(書いてきたコードがすべて破綻してしまうので厳しいです)
しか思いつきません

他に良い方法はないでしょうか。

ものすごい長いですが

定義(特に見る必要はなし)

C#

コード /// <summary> /// イベントブロック説明をJsonから取得します /// </summary> JsonInfo ji; /// <summary> /// 生成する初期位置 /// </summary> readonly Vector2 createInitPos = new Vector2(-8.5f, 5.5f); #region 生成するオブジェクト #region ステージごとに変わるタイル //----------WALL----------// [Header("Wall")] /// <summary> /// 壁 /// </summary> [SerializeField] WallsClass[] wc; //----------BackGround----------// [Header("BackGround")] /// <summary> /// 背景 /// </summary> [SerializeField] BackGroundClass[] bc; //----------Decoration----------// [Header("Decoration")] /// <summary> /// 装飾 /// </summary> [SerializeField] DecorationClass[] dc; #endregion #region 全ステージ共通のタイル //----------PLAYER ENEMY GOAL----------// [Header("Player/Goal")] /// <summary> /// プレイヤー /// </summary> [SerializeField] GameObject player; [SerializeField] GameObject goal; [Header("Enemy")] /// <summary> /// エネミー /// </summary> [SerializeField] GameObject[] enemy; //----------JUMP----------// [Header("Jump")] /// <summary> /// 初期位置 /// </summary> [SerializeField] GameObject initPos; /// <summary> /// ジャンプ台 /// </summary> [SerializeField] GameObject[] jumpObj; //----------EventItem----------// [Header("EventItem")] [SerializeField] GameObject[] item; //----------EventBlock----------// [Header("EventBlock")] [SerializeField] GameObject[] block; //----------EventBlock----------// [Header("Move")] [SerializeField] GameObject moveObj; [SerializeField] GameObject[] catArrow; #endregion #endregion /// <summary> /// 各ステージフロア作成 /// </summary> /// <param name="tileNum">タイルナンバー</param> /// <param name="pos">生成位置</param> /// <param name="floor">生成元の親オブジェクト</param> /// <param name="floorNum">現在のフロア数</param> delegate void TileMap(string tileNum, Vector2 pos, GameObject floor, int floorNum); TileMap[] tileList; TileMap tile; readonly string[] pathName = { "Wall", "PlayerGoal", "Enemy", "Jump", "Move", "EventItem", "EventBlock", "BackGround", "Decoration" }; /// <summary> /// 生成カウント /// </summary> int counter = 0; /// <summary> /// 矢印用カウンタ― /// </summary> int arrowCounter = 0; /// <summary> /// ステージ番号 /// ステージ選択時にセットします /// </summary> static int fileNum = 0; /// <summary> /// ステージ内のフロア数 /// </summary> readonly static int[] floorCount = { 3, 8 }; /// <summary> /// 現在のステージのフロア数を返します /// </summary> public static int FloorCount { get { return floorCount[fileNum]; } } /// <summary> /// 各ステージのX,Y長さ /// </summary> readonly Vector2[] stageVec = { new Vector2(19 - 1, 11 + 1), new Vector2(20 - 1, 11) }; /// <summary> /// 横のステージのフロア数 /// </summary> readonly static int[] stageX = { 3, 4 }; public static int StageX { get { return stageX[fileNum]; } } /// <summary> /// ステージ番号 /// </summary> public static string stageID = "";

Awake時、読み込む関数を格納

CreateStage()
フロアによって位置を変えて各フロアの位置を出します

C#

コード private void Awake() { //ステージ番号のステージを作成します fileNum = GameManager.Instance.StageNo; //fileNum = 0; //現在のステージ番号を指定します stageID = string.Format("stage{0}", fileNum + 1); ji = new JsonInfo(); ji.MapJson(); tileList = new TileMap[] { SwicthWALL,//壁を生成 SwitchPlayerGoal,//プレイヤーとゴールを生成 SwitchEnemy,//敵を生成 SwitchJump,//ジャンプ台を生成 SwitchMove,//フロア移動 SwitchEventItem,//イベントアイテムを生成 SwitchEventBlock,//イベントブロックを生成 SwitchBack,//背景生成 SwitchDecoration//デコレーション生成 }; //ステージ作成 CreateStage(); //オブジェクトを破棄します //Destroy(gameObject); } #region マップ生成読み込み /// <summary> /// ステージの作成 /// </summary> void CreateStage() { //CSVからデータを読み込む for (int sNum = 0; sNum < FloorCount; sNum++) { //余りが横 float stageVecX = sNum % StageX; //商が縦 float stageVecY = sNum / StageX; var vec = Vector2.zero; //このステージの横縦長さ * ステージのx(横のフロア)とy(縦のフロア)の何番目か + 作成する初期位置 vec.x = stageVec[fileNum].x * stageVecX + createInitPos.x; vec.y = (-stageVec[fileNum].y) * stageVecY + createInitPos.y; //ステージを格納する空のオブジェクトを作成(フロアごとに分けてここに入れます) var obj = Resources.Load<GameObject>("StageEmpty"); var floor = Instantiate(obj, transform.position, Quaternion.identity); floor.name = sNum.ToString(); for (int i = 0; i < tileList.Length; i++) { var stageNo = fileNum + 1; var filePath = string.Format("Stage/Stage{0}/{1}/{2}", stageNo, sNum + 1, pathName[i]); CSVRead(filePath, i, floor, vec, sNum); } } }

CSVRead() CSVからの読み込み(JSON)

C#

コード /// <summary> /// CSVファイルの読み込み /// </summary> void CSVRead(string stageTagName, int num, GameObject floor, Vector2 createPos, int floorNum) { //csvファイルの検索 var csvFile = Resources.Load(stageTagName) as TextAsset; if (csvFile == null) return; //csvファイルの読み込み var reader = new StringReader(csvFile.text); //数字文字を解析しステージを作成します StringMozi(reader, num, floor, createPos, floorNum); }

StringMozi() CSVの文字 (例え)横11行縦18列の読み込み

C#

コード /// <summary> /// ファイルの内の","で文字を区切ります /// </summary> void StringMozi(StringReader reader, int num, GameObject floor, Vector2 createPos, int floorNum) { var pos = createPos; tile = tileList[num]; //読み取り対象がなくなるまで繰り返します while (reader.Peek() != -1) { //一行づつ読み込みます string line = reader.ReadLine(); string[] split = line.Split(',');//,で区切ります foreach (var tileNum in split) { //現在の作成物 tile(tileNum, pos, floor, floorNum); //生成位置を変更します pos.x += 1; } //xを初期位置yを-1下げたところから生成を再開しします pos.x = createPos.x; pos.y -= 1; } //生成カウントの初期化 counter = 0; arrowCounter = 0; }

もしかしたら、JSONのデータから値を割り当てる際にUnity上では正常に動いていたけど、ビルドすると壊れることが起こっているのかもしれません。

フロア生成順の際にJsonから参照するブロックを生成したときにブロックのみ生成されてそこでfor文が死んだような現象が起こったので、わからないですが。。

      SwicthWALL,//壁を生成
SwitchPlayerGoal,//プレイヤーとゴールを生成
SwitchEnemy,//敵を生成
SwitchJump,//ジャンプ台を生成
SwitchMove,//フロア移動

この順番だと、Moveまで生成されます。しかし、EnemyやMoveもJsonを参照しているので訳が分かりません。

イメージ説明

良い質問の評価を上げる

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

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

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

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

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

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

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

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

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

fiveHundred
fiveHundred

2021/03/07 03:32

Unityでは基本的な処理はシングルスレッドなので、処理が間に合わない場合は他の基本的な処理も行われないため、フリーズや処理落ちという形になる気がします。 あくまで私の意見で違うかもしれませんが、メモリ不足が原因なのではないかと推測します。 いずれにせよ、現状では情報が少なくて状況がつかめないので、せめてコードぐらいは提示してくれると回答しやすくなると思います。
BRAK
BRAK

2021/03/07 03:34 編集

回答ありがとうございます。 帰宅したらコード載せます。 よろしくお願いします。
fiveHundred
fiveHundred

2021/03/07 12:12

tileListに格納されている「Swicth~」という関数はどうなっていますか?
BRAK
BRAK

2021/03/07 12:14

そこは、CSVから読み込んだ文字がたとえば1だったら草むらのタイルを置くという処理になっています。 swicth文で場合分けしています。 それをそれぞれで行っています。 prefabsの配列からタイルを取り出す形です。
BRAK
BRAK

2021/03/07 12:16 編集

```C# コード void SwicthWALL(string tileNum, Vector2 pos, GameObject floor, int floorNum) { //ステージごとの壁を生成します string[][] wallNo = new string[2][] { new string[]{ "22", "23", "24", "28", "29", "278", "279", "280", "284", "285", "534", "535", "536"}, new string[]{"6","7","8","9","262","263","264","265","518","519","520","521","770", "1031","1032","1033","1034","1286","1287","1288","1289","1542","1543","1544","1545"} }; //読み込んだ文字数値がwallNo配列にあるかを解析し、配列番号のオブジェクトを //現在のフロアに生成します。 if (!OnMozi(wallNo[fileNum], tileNum, 0)) { //wc[ステージ番号][wallNoの番号]のオブジェクトを生成 InstantObj(wc[fileNum].walls[SetNumber(wallNo[fileNum], tileNum)], pos, floor); } } ```
BRAK
BRAK

2021/03/07 12:21

また、Jsonのデータを参照するオブジェクトもあります。
BRAK
BRAK

2021/03/07 12:32

//JSON内で定義した連想配列を割り当てるためのクラス ```C# コード [System.Serializable] //ブロックの説明 public class Block:ID { public BlockFloor[] floor; } /// <summary> /// フロア内のブロック /// </summary> [System.Serializable] public class BlockFloor { public string[] name; /// <summary> /// 次の面に移動するフラグを持つブロック /// MeatObjとCatArrowを表示させる /// </summary> public string[] jumpFloor; /// <summary> /// イベントブロック /// </summary> public string[] ev; /// <summary> /// ゴールブロック /// </summary> public string[] goal; public string GetName(string type, int num) { string ret = null; switch (type) { case "ev": ret = ev[num]; break; case "goal": ret = goal[num]; break; } return ret; } } ``` //Jsonから値を参照するクラスが継承するIDクラス //GetDataNo()ここ参照しデータを割り当てていきます // ---> もしかしてジェネリック型がよくないとかありますか? ```C# コード /// <summary> /// 全てのJsonが持つStageID /// </summary> [System.Serializable] public class ID { public string id; /// <summary> /// StageIdから指定のJsonListに格納された要素を見つけます /// </summary> /// <typeparam name="T">IDクラスを継承しているJsonのクラスT</typeparam> /// <param name="dataId">現在のstage番号</param> /// <param name="data">Jsonクラス</param> public static T GetDataNo<T>(List<T> data, string dataId) where T : ID { //ステージIDのリスト配列番号を取得 var dataNo = data.Find(dt => dt.id == dataId); if (dataNo == null) { Debug.LogError("sceneId:名前が違う,id名が配列外エラー"); Debug.LogError("scenarioName:名前が違う,Resourcesの中にあるJsonファイルを参照"); } //そのステージ名が何番目にあるかを取得 var index = data.IndexOf(dataNo); return data[index]; } } ``` //Jsonブロッククラス ```C# コード //クラスに格納 [System.Serializable] public class BlockList { public List<Block> blocks = new List<Block>(); } ``` //Switch~でオブジェクトを生成する時に参照する関数(たとえばブロッククラス) //Jsonデータからの割り当て ```C# コード //Jsonで定義したクラス ブロックリスト public BlockList blockList; /// <summary> /// 指定のブロックに値を代入 /// </summary> /// <param name="stageId">ステージ名</param> /// <param name="blockName">ブロック名(ev,goal)</param> /// <param name="num">生成カウント(何番目か)</param> /// <param name="block"></param> /// <param name="floorNum">現在のフロア数</param> public void SetBlock(string stageId, string blockName, BlocksScript block, int num, int floorNum) { //ブロッククラスを定義 var b = ID.GetDataNo(blockList.blocks, stageId).floor[floorNum]; //ブロックの説明を取得 var des = b.GetName(blockName, num); //移動はあるか var f = b.jumpFloor[num]; //名前 var name = b.name[num]; //値の代入 block.SetBlock(des, name, f); } ```
BRAK
BRAK

2021/03/07 12:36 編集

ADVパートも作成しており、その出力の時にもここのJSONの関数を使っています。 その際にもJSONからシナリオを読みだせなかったので、もしかしたらビルドしたときにおかしくなっているということもあるかもしれません。(----> Unity上では動きます)
fiveHundred
fiveHundred

2021/03/07 23:56

その様子だと、私はちょっと分からないですね。すいません。 「ブロックを生成しようとする度に、Resources.Loadでプレハブを毎回ロードしている」ということがあるかもしれないと思っていたのですが、見た感じそうでもなさそうですし。
1570p
1570p

2021/03/08 02:30

jsonデータの読み込みが出来ているかの確認が必要ですね。 なんとなくですが、script execution orderが関係あるかも?とも思いました
BRAK
BRAK

2021/03/08 03:49

five Hundredさんありがとうございます。
BRAK
BRAK

2021/03/08 03:51

ビルド上でのJSONデータの読み込みが部分的に欠落しているという感じですかね。 確認してみます。
BRAK
BRAK

2021/03/08 03:55

script execution orderについて今調べましたが、スクリプトの実行順序は変えました。 もしかしてここが問題という可能性がありますか。
1570p
1570p

2021/03/08 06:57

処理順を変えたら、とありましたのでjsonデータから生成されて初期化される前にそのデータを使用するメソッドが走ってしまっている可能性があるのかな?と思ったのです。これがエディタとビルドで変わるか?は不明です。 なのでJsonのデータが確実に読まれているか?を確認するのがまず先だと思います。 これに関しては読み込み関係をAwake、後の処理をStartに変更でも確認できます。すべてAwakeとかだと可能性の一つとしてあるかなぁ?と。Awake中に別のオブジェクトを初期化して使うみたいな事をするとnullったりした記憶がありますので。 少なくともfor文自体の問題ではなく、その中の処理の問題のはずです。
BRAK
BRAK

2021/03/08 07:08

Jsonの読み込みはAwakeで処理しており。ほかはStartで分けて処理はしております。 これでエディタ上で確実に動いているので問題はないと思うのですが、、一度確認してみます。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

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

Unity

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