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

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

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

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Unity

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

配列

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

Q&A

解決済

1回答

1412閲覧

【Unity】動的に生成したオブジェクトのTransform.position.yをリストまたは配列に格納し、その中で最大値を取得したい。

RyotaTakada

総合スコア6

C#

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Unity

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

配列

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

0グッド

0クリップ

投稿2020/05/19 02:52

前提・実現したいこと

ブロックの積み上げゲーム

現状ではブロックを縦一列にしか積み上げていくことができず、遊びの幅が狭い状態です。
またブロック積み上げに伴うカメラ位置の上昇も、ブロックが3つ落とされるごとに一定間隔で上昇するという仕組みになっており、あまり柔軟性がない状態です。

上記の問題を以下の方法で解決したいと思っています。
●シーン内のブロックで"DroppedBlock"タグがついたものをリストまたは配列に格納
●格納されたGameObjectそれぞれのTransform.position.yを比較し、最大の値を出力
●出力された最大値をもとにカメラの上昇下降をコントロール

現状の仕組み

●メインカメラの子にGameOverトリガー(画面下部に配置されています)があり、ブロックがそのトリガーに触れるとゲームオーバー
●ブロックを3つ落とすごとにカメラ位置上昇
●落とす前のブロックのタグは"Block"、地面またはブロックに接地したブロックは"DroppedBlock"に変更

###わからないところ
シーン内のブロックで"DroppedBlock"タグを配列に格納するために
GameObject.FindGameObjectsWithTag("DroppedBlock");
を用いたのですが、格納されたオブジェクトそれぞれのTransform.position.yを比較する方法がわかりません。

最大値となるTransform.position.yさえ取得できてしまえば、カメラの位置を動的に変更することは可能だと思うのですが。。。

該当のソースコード

GameplayController.cs

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using DG.Tweening; 6using UnityEngine.SceneManagement; 7 8public class GameplayController : MonoBehaviour 9{ 10 11 public static GameplayController instance; 12 13 public BlockSpawner block_Spawner; 14 15 [HideInInspector] 16 public BlockScript currentBox; 17 18 public CameraFollow cameraScript; 19 private int moveCount; 20 21 public float blockSpeed; 22 23 GameObject[] stackedBlocks; 24 25 bool isChecked; 26 27 public Text text; 28 29 GameObject pauseMenu; 30 public RectTransform pause; 31 32 GameObject gameOverMenu; 33 34 void Awake() 35 { 36 if (instance == null) 37 instance = this; 38 39 blockSpeed = 5f; 40 } 41 42 void Start() 43 { 44 block_Spawner.SpawnBox(); 45 46 pauseMenu = GameObject.Find("PauseMenu"); 47 pauseMenu.SetActive(false); 48 gameOverMenu = GameObject.Find("GameOverMenu"); 49 gameOverMenu.SetActive(false); 50 } 51 52 void Update() 53 { 54 DetectInput(); 55 56 GameObject[] blocks = GameObject.FindGameObjectsWithTag("DroppedBlock"); 57 58 59 } 60 61 void DetectInput() 62 { 63 if (Input.GetKeyDown(KeyCode.Space)) 64 { 65 currentBox.DropBox(); 66 } 67 } 68 69 70 public void SpawnNewBox() 71 { 72 Invoke("NewBox", 2f); 73 } 74 75 void NewBox() 76 { 77 block_Spawner.SpawnBox(); 78 } 79 80 public void MoveCamera() 81 { 82 83 moveCount++; 84 85 if (moveCount == 3) 86 { 87 moveCount = 0; 88 cameraScript.targetPos.y += 2.5f; 89 } 90 91 } 92 93 public void PauseButton() 94 { 95 96 } 97 98 public void RestartGame() 99 { 100 UnityEngine.SceneManagement.SceneManager.LoadScene( 101 UnityEngine.SceneManagement.SceneManager.GetActiveScene().name); 102 } 103 104 public void ShowGameOverMenu() 105 { 106 gameOverMenu.SetActive(true); 107 } 108 109 public void StageList() 110 { 111 SceneManager.LoadScene("StageList"); 112 } 113 114}

BlockScript.cs(このスクリプトが各ブロックオブジェクトに付いています)

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class BlockScript : MonoBehaviour 6{ 7 private bool canMove; 8 9 private Rigidbody2D myBody; 10 11 private bool gameOver; 12 private bool ignoreCollision; 13 private bool ignoreTrigger; 14 15 private bool isDropped; 16 17 Rigidbody2D rb2D; 18 19 public AudioClip drop; 20 public AudioClip dropped; 21 AudioSource audiosource; 22 23 24 25 void Awake() 26 { 27 myBody = GetComponent<Rigidbody2D>(); 28 myBody.gravityScale = 0f; 29 } 30 31 void Start() 32 { 33 canMove = true; 34 35 GameplayController.instance.currentBox = this; 36 37 rb2D = GetComponent<Rigidbody2D>(); 38 39 audiosource = GetComponent<AudioSource>(); 40 41 } 42 43 void Update() 44 { 45 MoveBox(); 46 } 47 48 void MoveBox() 49 { 50 if (canMove) 51 { 52 Vector3 horizontal = new Vector3(Input.GetAxis("Horizontal"), 0.0f, 0.0f); 53 transform.position += horizontal * GameplayController.instance.blockSpeed * Time.deltaTime; 54 } 55 } 56 57 public void DropBox() 58 { 59 canMove = false; 60 myBody.gravityScale = 1; 61 62 audiosource.PlayOneShot(drop); 63 } 64 65 void Landed() 66 { 67 68 if (gameOver) 69 return; 70 71 72 ignoreCollision = true; 73 ignoreTrigger = true; 74 75 GameplayController.instance.SpawnNewBox(); 76 GameplayController.instance.MoveCamera(); 77 78 } 79 80 void RestartGame() 81 { 82 GameplayController.instance.RestartGame(); 83 } 84 85 void ShowGameOverMenu() 86 { 87 GameplayController.instance.ShowGameOverMenu(); 88 } 89 90 void OnTriggerEnter2D(Collider2D target) 91 { 92 if (ignoreTrigger) 93 return; 94 95 if (target.tag == "GameOver") 96 { 97 98 CancelInvoke("Landed"); 99 gameOver = true; 100 ignoreTrigger = true; 101 102 Invoke("ShowGameOverMenu", 2f); 103 } 104 } 105 106 void OnCollisionEnter2D(Collision2D target) 107 { 108 109 if (ignoreCollision) 110 return; 111 112 if (target.gameObject.tag == "Platform") 113 { 114 115 this.tag = "DroppedBlock"; 116 Invoke("Landed", 2f); 117 //ignoreCollision = true; 118 119 audiosource.PlayOneShot(dropped); 120 } 121 122 if (target.gameObject.tag == "DroppedBlock") 123 { 124 this.tag = "DroppedBlock"; 125 Invoke("Landed", 2f); 126 //ignoreCollision = true; 127 128 audiosource.PlayOneShot(dropped); 129 } 130 } 131}

補足情報(FW/ツールのバージョンなど)

実際の挙動を録画し、Youtubeに載せましたので、参考にしてください。
<挙動動画>

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

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

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

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

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

guest

回答1

0

ベストアンサー

LinqのMax関数でリストや配列から最大値が引っ張り出せるので、純粋に値だけならそれでどうでしょうか?

cs

1using System.Linq; //追加 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6 7public class Test : MonoBehaviour { 8 9 void Start(){ 10 // タグでオブジェクトを取得 11 GameObject[] blocks = GameObject.FindGameObjectsWithTag("DroppedBlock"); 12 13 // オブジェクトのポジションy を入れるためのリスト 14 List<float> positionList = new List<float>(); 15 16 // 取得したゲームオブジェクトのポジションをリストに追加 17 foreach(GameObject obj in blocks) { 18 positionList.Add(obj.transform.position.y); 19 } 20 21 // (Linq) Max関数を使って最大値を引っ張り出す 22 Debug.Log(positionList.Max()); 23 24 } 25 26} 27

参考
https://alunote.hatenablog.com/entry/2018/10/21/120000

投稿2020/05/19 03:12

hogefugapiyo

総合スコア3302

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

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

RyotaTakada

2020/05/19 05:53

なんと、そのような方法があるのですね! ありがとうございます。実際に試したところ、正常に動作しました! 現時点ではシーン内のブロックでy位置が最高のものの値が出力されているだけなので、 distance = Mathf.Abs(positionList.Max() - [地面オブジェクト表面のy値])として実際の距離を出してみたところ、こちらも正常に作動させることができました! 本当にありがとうございます。 救われました。m(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問