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

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

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

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

Unity

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

Q&A

2回答

404閲覧

unityがフリーズして動かなくなります

summerxxx

総合スコア2

C#

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

Unity

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

1グッド

1クリップ

投稿2024/03/17 04:47

編集2024/03/20 04:35

実現したいこと

前提として、playerControllerというスクリプトを持っているオブジェクトはプレイヤーと呼ぶことにし、pushControllerというスクリプトを持っているオブジェクトはオブジェクト+アルファベット(例えば、オブジェクトA、オブジェクトB)と呼ぶことにする。

プレイヤーがpushControllerのスクリプトをもつオブジェクトAと同じ位置に移動するとき、オブジェクトAはプレイヤーの進行方向に押し出されるような形で移動してほしい。
左からプレイヤー、オブジェクトA、オブジェクトB、オブジェクトCが4つ並んで位置するとき、プレイヤーが右に移動すればオブジェクトA、オブジェクトB、オブジェクトCは全部右方向に移動してほしい。

参考として画像を載せます。
イメージ説明

発生している問題・分からないこと

プレイヤーの隣に位置するオブジェクト(pushContorollerを持っている)が二つ以上あるとき、プレイヤーがそれらを押し出そうと移動すると、unityがフリーズして動かなくなります。
一つのオブジェクトを押し出すときは基本的にはフリーズしませんが、たまにフリーズします。

エラーメッセージ

error

1エラーメッセージはありません。

該当のソースコード

特になし

PlayerController

1private LevelManager levelManager; 2private PushController[] pushcontroller; 3 4void Start() 5{ 6 levelManager = GameObject.Find("LevelManager").GetComponent<LevelManager>(); 7} 8 9public void Left() 10{ 11 PushController[] pushcontrollers = GameObject.FindObjectsOfType<PushController>(); 12 StopController[] stopcontrollers = GameObject.FindObjectsOfType<StopController>(); 13 transform.position += new Vector3(-1, 0, 0); 14 Vector3 pos = Rounding.Round(transform.position); 15 transform.position = pos; 16 Task.Delay(100); 17 foreach (StopController obj in stopcontrollers) 18 { 19 if (obj.enabled) 20 { 21 obj.PositionSearch(); 22 obj.PositionCheck(); 23 } 24 } 25 foreach (PushController obj in pushcontrollers) 26 { 27 if(obj.enabled) 28 { 29 obj.PositionSearch(); 30 obj.PositionCheck(); 31 } 32 } 33} 34public void Right() 35{ 36 PushController[] pushcontrollers = GameObject.FindObjectsOfType<PushController>(); 37 StopController[] stopcontrollers = GameObject.FindObjectsOfType<StopController>(); 38 transform.position += new Vector3(1, 0, 0); 39 Vector3 pos = Rounding.Round(transform.position); 40 transform.position = pos; 41 Task.Delay(100); 42 foreach (StopController obj in stopcontrollers) 43 { 44 if (obj.enabled) 45 { 46 obj.PositionSearch(); 47 obj.PositionCheck(); 48 } 49 } 50 foreach (PushController obj in pushcontrollers) 51 { 52 if(obj.enabled) 53 { 54 obj.PositionSearch(); 55 obj.PositionCheck(); 56 } 57 } 58} 59public void Up() 60{ 61 PushController[] pushcontrollers = GameObject.FindObjectsOfType<PushController>(); 62 StopController[] stopcontrollers = GameObject.FindObjectsOfType<StopController>(); 63 transform.position += new Vector3(0, 1, 0); 64 Vector3 pos = Rounding.Round(transform.position); 65 transform.position = pos; 66 Task.Delay(100); 67 foreach (StopController obj in stopcontrollers) 68 { 69 if (obj.enabled) 70 { 71 obj.PositionSearch(); 72 obj.PositionCheck(); 73 } 74 } 75 foreach (PushController obj in pushcontrollers) 76 { 77 if (obj.enabled) 78 { 79 obj.PositionSearch(); 80 obj.PositionCheck(); 81 } 82 } 83} 84public void Down() 85{ 86 PushController[] pushcontrollers = GameObject.FindObjectsOfType<PushController>(); 87 StopController[] stopcontrollers = GameObject.FindObjectsOfType<StopController>(); 88 transform.position += new Vector3(0, -1, 0); 89 Vector3 pos = Rounding.Round(transform.position); 90 transform.position = pos; 91 Task.Delay(100); 92 foreach (StopController obj in stopcontrollers) 93 { 94 if (obj.enabled) 95 { 96 obj.PositionSearch(); 97 obj.PositionCheck(); 98 } 99 } 100 foreach (PushController obj in pushcontrollers) 101 { 102 if (obj.enabled) 103 { 104 obj.PositionSearch(); 105 obj.PositionCheck(); 106 } 107 } 108}

pushController

1private LevelManager levelManager; 2private PushController pushController; 3private GameObject a; 4private GameObject b; 5private GameObject c; 6private GameObject d; 7 8void Start() 9{ 10 levelManager = GameObject.Find("LevelManager").GetComponent<LevelManager>(); 11 a = GetObjectA(); 12 b = GetObjectB(); 13 c = GetObjectC(); 14 d = GetObjectD(); 15} 16 17// Update is called once per frame 18void Update() 19{ 20 21} 22 23private GameObject GetObjectA() 24{ 25 Vector3 targetPosition = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y + 1, gameObject.transform.position.z); 26 GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(); 27 foreach (GameObject obj in allObjects) 28 { 29 Vector3 position = obj.transform.position; 30 if (position == targetPosition) 31 { 32 return obj; 33 } 34 } 35 return null; 36} 37private GameObject GetObjectB() 38{ 39 Vector3 targetPosition = new Vector3(gameObject.transform.position.x + 1, gameObject.transform.position.y, gameObject.transform.position.z); 40 GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(); 41 foreach (GameObject obj in allObjects) 42 { 43 Vector3 position = obj.transform.position; 44 if (position == targetPosition) 45 { 46 return obj; 47 } 48 } 49 return null; 50} 51private GameObject GetObjectC() 52{ 53 Vector3 targetPosition = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y - 1, gameObject.transform.position.z); 54 GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(); 55 foreach(GameObject obj in allObjects) 56 { 57 Vector3 position = obj.transform.position; 58 if (position == targetPosition) 59 { 60 return obj; 61 } 62 } 63 return null; 64} 65private GameObject GetObjectD() 66{ 67 Vector3 targetPosition = new Vector3(gameObject.transform.position.x - 1, gameObject.transform.position.y, gameObject.transform.position.z); 68 GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(); 69 foreach(GameObject obj in allObjects) 70 { 71 Vector3 position = obj.transform.position; 72 if (position == targetPosition) 73 { 74 return obj; 75 } 76 } 77 return null; 78} 79public void PositionCheck() 80{ 81 a =GetObjectA(); 82 b =GetObjectB(); 83 c =GetObjectC(); 84 d =GetObjectD(); 85} 86public void PositionSearch() 87{ 88 if(a != null && a.transform.position == this.transform.position) 89 { 90 List<GameObject> S = new List<GameObject>(); 91 S.Add(gameObject); 92 Vector3 M = new Vector3(0, -1, 0); 93 PositionMove(S, M, a); 94 95 } 96 if (b != null && b.transform.position == this.transform.position) 97 { 98 List<GameObject> S = new List<GameObject>(); 99 S.Add(gameObject); 100 Vector3 M = new Vector3(-1, 0, 0); 101 PositionMove(S, M, b); 102 } 103 if (c != null && c.transform.position == this.transform.position) 104 { 105 List<GameObject> S = new List<GameObject>(); 106 S.Add(gameObject); 107 Vector3 M = new Vector3(0, 1, 0); 108 PositionMove(S, M, c); 109 } 110 if (d != null && d.transform.position == this.transform.position) 111 { 112 List<GameObject> S = new List<GameObject>(); 113 S.Add(gameObject); 114 Vector3 M = new Vector3(1, 0, 0); 115 PositionMove(S, M, d); 116 } 117} 118 119private void PositionMove(List<GameObject> s, Vector3 m, GameObject player) 120{ 121 Vector3 P = this.transform.position; 122 P += m; 123 124 bool loopContinue = true; 125 126 while (loopContinue) 127 { 128 Collider2D[] colliders = Physics2D.OverlapCircleAll(P, 0.4f); 129 if (colliders.Length > 0) 130 { 131 foreach (Collider2D collider in colliders) 132 { 133 PushController pushController = collider.GetComponent<PushController>(); 134 StopController stopController = collider.GetComponent<StopController>(); 135 if (pushController != null && pushController.enabled) 136 { 137 s.Add(collider.gameObject); 138 } 139 else if (stopController != null && stopController.enabled) 140 { 141 player.transform.position += m; 142 loopContinue = false; 143 } 144 else 145 { 146 foreach (GameObject obj in s) 147 { 148 obj.transform.position += m; 149 } 150 loopContinue = false; 151 } 152 } 153 P += m; 154 } 155 else 156 { 157 for(int i = s.Count - 1; i >= 0; i--) 158 { 159 Debug.Log(s[i]); 160 } 161 loopContinue = false; 162 } 163 } 164}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

タスクマネージャーでCPUやメモリが圧迫されていないか確認しましたが、問題ありませんでした。

無限ループの可能性を考えて、Debug.Logを使いしらべてみました。下記の①②の画像はpushControllerスクリプトのPositionMoveメソッドの部分です。画像①で実行すると無限ループが発生したのですが、cs180をDebug.Logに変更した画像②で実行すると無限ループは発生せず、画像③のように正常に動くようになりました。ですので、私は無限ループの可能性はないと考えています。


イメージ説明

イメージ説明

イメージ説明

補足

わかりにくい箇所や説明不足の箇所について、質問いただけると助かります。

shinoharat👍を押しています

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

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

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

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

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

shinoharat

2024/03/18 06:06

一つのオブジェクトを押し出すことはできますか? たとえば、プレイヤーの右にオブジェクトXがあり、Xの右が空の場合、正常にオブジェクトXを右に押せますか?
summerxxx

2024/03/19 02:15

オブジェクトが一つなら押し出すことはできます。 しかし、プレイヤーの上にオブジェクトX、下にオブジェクトYがある場合(Xの上は空、Yの下は空)、どちらかのオブジェクト押し出そうとするとフリーズしてしまいます。
shinoharat

2024/03/21 04:35

プレイヤーが持っているスクリプトは playerController のみでしょうか? それとも、playerController と pushController の両方を持っていたりしますか?
summerxxx

2024/03/22 04:15

プレイヤーはplayerControllerとpushControllerの両方を持っていて、playerControllerは有効で、pushControllerは有効ではない状態です。
guest

回答2

0

・PositionCheck と PositionSearch の順序を変える
・Rounding.Round を Vector3 で比較する前に入れる

以上の 2 点を試して頂くことはできますか?

PlayerController

1private LevelManager levelManager; 2 3void Start() 4{ 5 levelManager = GameObject.Find("LevelManager").GetComponent<LevelManager>(); 6} 7 8private void Move(Vector3 moveVector) 9{ 10 transform.position += moveVector; 11 transform.position = Rounding.Round(transform.position); 12 Task.Delay(100); 13 PushController[] pushcontrollers = GameObject.FindObjectsOfType<PushController>(); 14 StopController[] stopcontrollers = GameObject.FindObjectsOfType<StopController>(); 15 foreach (StopController obj in stopcontrollers) 16 { 17 if (obj.enabled) 18 { 19 obj.PositionSearch(); 20 } 21 } 22 foreach (PushController obj in pushcontrollers) 23 { 24 if(obj.enabled) 25 { 26 obj.PositionSearch(); 27 } 28 } 29} 30 31public void Left() 32{ 33 Move(new Vector3(-1, 0, 0)); 34} 35 36public void Right() 37{ 38 Move(new Vector3(1, 0, 0)); 39} 40 41public void Up() 42{ 43 Move(new Vector3(0, 1, 0)); 44} 45 46public void Down() 47{ 48 Move(new Vector3(0, -1, 0)); 49}

PushController

1private LevelManager levelManager; 2 3void Start() 4{ 5 levelManager = GameObject.Find("LevelManager").GetComponent<LevelManager>(); 6 allObjects = GameObject.FindObjectsOfType<GameObject>(); 7} 8 9private GameObject GetObject(Vector3 moveVector) 10{ 11 Vector3 targetPosition = new Vector3(gameObject.transform.position.x, 12 gameObject.transform.position.y, gameObject.transform.position.z); 13 targetPosition += moveVector; 14 targetPosition = Rounding.Round(targetPosition); //この行を追加しました。 15 GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(); 16 foreach (GameObject obj in allObjects) 17 { 18 Vector3 position = obj.transform.position; 19 if (position == targetPosition) 20 { 21 return obj; 22 } 23 } 24 return null; 25} 26 27public void PositionSearch() 28{ 29 PositionSearch(new Vector3(0, 1, 0)); 30 PositionSearch(new Vector3(1, 0, 0)); 31 PositionSearch(new Vector3(0, -1, 0)); 32 PositionSearch(new Vector3(-1, 0, 0)); 33} 34 35private void PositionSearch(Vector3 moveVector) 36{ 37 GameObject targetObject = GetObject(moveVector); 38 if(targetObject != null && Rounding.Round(targetObject.transform.position) == this.transform.position) 39 { 40 List<GameObject> S = new List<GameObject>(); 41 S.Add(gameObject); 42 Vector3 M = new Vector3(0, -1, 0); 43 PositionMove(S, M, targetObject); 44 } 45} 46 47private void PositionMove(List<GameObject> s, Vector3 m, GameObject player) 48{ 49 Vector3 P = this.transform.position; 50 P += m; 51 52 bool loopContinue = true; 53 54 while (loopContinue) 55 { 56 Collider2D[] colliders = Physics2D.OverlapCircleAll(P, 0.4f); 57 if (colliders.Length > 0) 58 { 59 foreach (Collider2D collider in colliders) 60 { 61 PushController pushController = collider.GetComponent<PushController>(); 62 StopController stopController = collider.GetComponent<StopController>(); 63 if (pushController != null && pushController.enabled) 64 { 65 s.Add(collider.gameObject); 66 } 67 else if (stopController != null && stopController.enabled) 68 { 69 player.transform.position += m; 70 loopContinue = false; 71 } 72 else 73 { 74 foreach (GameObject obj in s) 75 { 76 obj.transform.position += m; 77 } 78 loopContinue = false; 79 } 80 } 81 P += m; 82 } 83 else 84 { 85 for(int i = s.Count - 1; i >= 0; i--) 86 { 87 s[i].transform.position += m; 88 } 89 loopContinue = false; 90 } 91 } 92} 93

投稿2024/03/20 05:17

uni2

総合スコア256

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

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

summerxxx

2024/03/21 02:21

回答ありがとうございます。試してみましたが解決できませんでした。 ・positioncheckとpositionsearchを入れ替える これを実行した場合、順序は以下のようになります。 プレイヤーが動く→positioncheck四方にあるオブジェクトをtargetobjectに定義する→positionsearchでプレイヤーとtargetobjectのpositionが被ってないかチェックする。 結果はプレイヤーがオブジェクトと同じ位置になっても、PositionMoveは実行されませんでした。 positioncheckを先に実行してしまうと、常にプレイヤーの四方にあるオブジェクトがtargetobjectに定義されてしまいます。プレイヤーの右隣にオブジェクトAが存在した場合、オブジェクトAはtargetobjectに定義されます。しかしプレイヤーが右に移動するとすぐにpositioncheckが実行されていまい、移動後のpositionの右隣にあるオブジェクトがtargetobjectになります。そこからpositionsearchが実行されてもプレイヤーと同じ位置にあるオブジェクトAはtargetobjectではないので,PositionMoveが実行されることはありません。 おそらくこれが上手くいかなかった理由だと思います。
uni2

2024/03/21 02:31

そうでしたか。 PositionCheck と PositionSerach の意味合い的に Check してから Serach をしないと 昔の位置関係を考慮して移動する事になってしまうと思ったのですが 勘違いのようでした。 申し訳ございません。
guest

0

恐らくですが PositionSearch で
複数回 PositionMove を実行している関係で
1回目の PositionMove で重なった後に
2回目の PositionMove を実行した場合に
無限ループしているように見えます。

Right を実行した場合は
右方向のみチェックすることが
挙動として正しいならば
それで治ると思われます。

他の修正方法を具体的に提案するのは難しいですが
StopController という変数名から推測するに
foreach で回す際に、先に StopController を全て調べた後に
PushController の処理に移動する必要があるように見えます。
この文章では分かりにくいと思いますので
サンプルコードを添付します。

これが合っている可能性は低いかもしれませんが
是非一度お試しください。

private void PositionMove(List<GameObject> s, Vector3 m, GameObject player) { Vector3 P = this.transform.position; P += m; bool loopContinue = true; while (loopContinue) { Collider2D[] colliders = Physics2D.OverlapCircleAll(P, 0.4f); if (colliders.Length > 0) { bool isExec = false; foreach (Collider2D collider in colliders) { StopController stopController = collider.GetComponent<StopController>(); if (stopController != null && stopController.enabled) { player.transform.position += m; isExec = true; loopContinue = false; } } if(!isExec) { foreach (Collider2D collider in colliders) { PushController pushController = collider.GetComponent<PushController>(); if (pushController != null && pushController.enabled) { s.Add(collider.gameObject); isExec = true; } } } if(!isExec) { foreach (Collider2D collider in colliders) { foreach (GameObject obj in s) { obj.transform.position += m; } loopContinue = false; } } P += m; } else { for(int i = s.Count - 1; i >= 0; i--) { Debug.Log(s[i]); } loopContinue = false; } }

投稿2024/03/19 06:17

編集2024/03/19 06:23
uni2

総合スコア256

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

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

summerxxx

2024/03/20 03:49

回答ありがとうございます。試してみましたが解決できませんでした。
uni2

2024/03/20 04:05

そうでしたか。 お力になれず申し訳ございません。
summerxxx

2024/03/20 04:31

いえいえ、ご回答ありがとうございました。 一つ質問させていただきたいのですが、下記に記載しているご回答いただいた一部の箇所についてもう少し詳しく伺いたいです。プレイヤーがオブジェクトAと重なるとき、PositionSearchからPositionMoveは1回しか実行されないと自分では認識しているので、複数回PositionMoveが実行するということが理解できません。 宜しくお願い致します。 「恐らくですが PositionSearch で 複数回 PositionMove を実行している関係で 1回目の PositionMove で重なった後に 2回目の PositionMove を実行した場合に 無限ループしているように見えます。」
uni2

2024/03/20 05:29

コードを再度読んでみた所 私が間違っている可能性が高そうでした。 申し訳ございません。 PositionCheck は上下左右の 4 方向に GetObject○ を実行しているため a, b, c, d の 2 種類以上が null でなくなる可能性があると思われます。 その場合に PositionMove の 2 番目の引数が調査した方向と逆向きのように見えるため 〇.transform.position == this.transform.position を 他の方向でも満たす可能性があるように見えたためそう言ったのですが 重ならないようにプログラミングされているならば そういった現象は起こりそうにないですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問