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

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

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

Q&A

解決済

2回答

542閲覧

unityのスクリプトで、”すべての条件を満たすとき”実行するようなコードを書きたい

545498_ho

総合スコア4

0グッド

1クリップ

投稿2022/06/16 09:54

前提

unityで下の図にあるように、青い四角が壁の四角に近づくと、壁の一つ一つの色が赤に変わるように実装しています。
(ml-agentでの実装を行っております)

イメージ説明

実現したいこと

実現したい事は以下の2点です。

①色が変わったその一回だけアクションを実行させたい

②壁のすべての色を変えた時にアクションが実行されるようにコードを書きたい

発生している問題①

一つ一つの壁のGameObjectは以下のコードによって取得しています。
wall_Objects = GameObject.FindGameObjectsWithTag("Wall");

以下のコードでは、赤の壁であれば毎ステップアクションが実行(報酬を得る)ことになってしまいます。
そうではなく、壁が白から赤になった時だけアクションが実行されるようにしたいです。
上の画像でいうと、すべとの壁を赤にするまで10回だけアクションを実行させるということです。

public override void OnActionReceived(ActionBuffers actionBuffers) { for (int i = 0; i < wall_Objects.Length; i++) { if (wall_Objects[i].GetComponent<Renderer>().material.color == Color.red) { SetReward(0.01f); } } }

発生している問題②

全ての壁を赤にしたときに実行するようなコードを書きたいです。
以下のように、すべてが赤という条件の時、報酬を与えたいです。

if () { SetReward(1f); EndEpisode(); }

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

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

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

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

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

guest

回答2

0

ベストアンサー

1 は説明がわからないので 2 だけ

c#

1using System.Linq; 2 3(略) 4 if (wall_Objects.All(x => x.GetComponent<Renderer>().material.color == Color.red)) 5 { 6 print("All red"); 7 }

投稿2022/06/16 10:48

bboydaisuke

総合スコア5275

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

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

0

オブジェクト決まってるなら、Listとかで壁管理したらいいと思います

サンプルを簡略化するために無理やり作ってますが
下記はアタッチすると自動的にCubeを作るスクリプトです。生成時にリストに追加します。
クリックすると赤く塗れますが、1回塗ると監視リストから外れるので2回目は塗れなくなります。
全部塗り終わる(=監視リストがなくなる)ことで、全部塗られたことがわかります。

cs

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Test3 : MonoBehaviour 6{ 7 public int cnt1 = 5; 8 public int cnt2 = 5; 9 public List<GameObject> items = new List<GameObject>(); 10 11 // Start is called before the first frame update 12 void Start() 13 { 14 for (int i = 0; i < cnt1; i++) 15 { 16 for (int j = 0; j < cnt2; j++) 17 { 18 var go = GameObject.CreatePrimitive(PrimitiveType.Cube); 19 go.transform.position = new Vector3((i-1) * 5, (j-1) * 10 / 5, 0); 20 items.Add(go); 21 22 } 23 } 24 } 25 26 // Update is called once per frame 27 void Update() 28 { 29 if (Input.GetMouseButtonDown(0)) 30 { 31 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 32 RaycastHit hit = new RaycastHit(); 33 34 if (Physics.Raycast(ray, out hit)) 35 { 36 if (items.Contains(hit.collider.gameObject)) 37 { 38 hit.collider.gameObject.GetComponent<Renderer>().material.color = Color.red; 39 items.Remove(hit.collider.gameObject); 40 Debug.Log("SetReward!"); 41 42 if(items.Count <= 0) 43 { 44 Debug.Log("All Red!"); 45 } 46 } 47 } 48 } 49 } 50} 51

質問内容に振り返るとwall_Objects = GameObject.FindGameObjectsWithTag("Wall");で対象を全部取れるので、こいつらを監視すれば良いかと思います。

本当はイベントとか使ったり、壁側に責任をもたせたりしてスマート化すると思いますが
上記コードはすぐテストできるようにざっくり作ってます。

投稿2022/06/16 10:33

hogefugapiyo

総合スコア3302

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問