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

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

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

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

Unity

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

Q&A

解決済

2回答

1383閲覧

unityでGameobject型のリストのcountが0になる。

lain62

総合スコア6

C#

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

Unity

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

0グッド

0クリップ

投稿2021/04/30 14:58

編集2021/04/30 15:01

unityでアイテム(下の画像で選択されているオブジェクト)がバー(アイテムの真下にある棒状のオブジェクト)に当たったら現在のボールの数を倍に増やすようなコードを書いています。

BallManager.csというファイルで、まずヒエラルキーに最初からあるFirstBallというGamaObjectを取得してGameObject型のList(ballと定義)に追加しています。
この時点では当たり前ですがball.Count=1です。しかしこれをItemManager.csという別のファイルからball.Countを含む関数(DoubleBall)を呼び出した時なぜかball.Count=0とコンソールに表示されてしまいます。
どのようにしたらballの要素数をItemManager.csから参照できるのでしょうか。
以下BallManagerとItemManagerのファイルで、BallManagerはBallのPrefabとFirstBallに、ItemManagerはヒエラルキーのItemにそれぞれアタッチしています。

作業環境はUnity 2019.4.10f
VS 2019
Win 10
です。

BallManager

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class BallManager : MonoBehaviour 6{ 7 8 // Start is called before the first frame update 9 //ボールを格納するリスト 10 11 public List<GameObject> ball = new List<GameObject>(); 12 public GameObject instanceBall; 13 14 15 List<Rigidbody> rb = new List<Rigidbody>(); 16 17 Vector3 ballInitSpeed; 18 19 void Start() 20 { 21 //最初のボール 22 GameObject firstBall = GameObject.Find("FirstBall"); 23 ball.Add(firstBall); 24 Debug.Log("最初の"+ball.Count); 25 26 //最初のボールの初速 27 ballInitSpeed = new Vector3(100, 300, 0); 28 29 rb.Insert(0, firstBall.GetComponent<Rigidbody>()); 30 rb[0].AddForce(ballInitSpeed); 31 32 instanceBall= Resources.Load("Ball") as GameObject; 33 34 // ballCount = 1; 35 36 37 } 38 39 // Update is called once per frame 40 void Update() 41 { 42 43 44 // Debug.Log("ballCount" + ball.Count); 45 46 47 } 48 49 50 public void DoubleBall() 51 { 52 Debug.Log("呼び出された後のカウント"+ball.Count); 53 54 //増える分のボールをballに格納 55 foreach (var item in ball) 56 { 57 // Debug.Log("呼び出された"); 58 59 //ボールを現在存在するボールのそれぞれから分裂させる 60 Instantiate(instanceBall,item.transform.position,Quaternion.identity); 61 62 //ballリストのインデックスを倍にする 63 ball.Add(instanceBall); 64 65 66 } 67 68 //分裂したボールに初速度を与える 69 for (int i = ball.Count/2; i < ball.Count-1; i++) 70 { 71 rb.Insert(i, instanceBall.GetComponent<Rigidbody>()); 72 73 ballInitSpeed = new Vector3(Random.Range(-1000, 1000), Random.Range(-1000, 1000), 0); 74 rb[i].AddForce(ballInitSpeed); 75 } 76 77 78 } 79 80 81} 82

ItemManager

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class ItemManager : MonoBehaviour 6{ 7 public GameObject item; 8 // public GameObject[] balls; 9 10 BallManager ballManager; 11 Vector3 itemPos; 12 13 public GameObject ball; 14 15 16 // Start is called before the first frame update 17 void Start() 18 { 19 itemPos = new Vector3(-0.15f,2.2f,0); 20 21 // Instantiate(item,itemPos,Quaternion.identity); 22 23 } 24 25 // Update is called once per frame 26 void Update() 27 { 28 29 30} 31 32 //バーにアイテムがぶつかったら 33 public void OnCollisionEnter(Collision other) 34 { 35 Debug.Log("aaaa"); 36 if (other.gameObject.tag=="Bar") 37 { 38 ballManager = ball.GetComponent<BallManager>(); 39 //ボールを増やす 40 ballManager.DoubleBall(); 41 42 43 Destroy(gameObject); 44 45 46 47 } 48 } 49 50} 51

イメージ説明

また当方unityもc#も初心者であるため、もっといい,ボールを2倍にする実装方法などあればご教授いただきたいです。
よろしくお願いします。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/05/01 04:10

BallManagerを複製されるballにつけるのですか? Countが0になる原因はこれっぽい。 ItemMamagerでCollision判定がするんですか?ItemManagerがどういう意味で作ったスクリプトなのかは分かりませんが… いろいろおかしい気がします
lain62

2021/05/01 05:24

ItemManagerはアイテムの生成(まだ実装していない)とアイテムの破棄を担当しています。衝突判定のできるスクリプトがアタッチされていないオブジェクトの衝突検知の仕方が分からなかったのでアイテムに直接スクリプトをアタッチしています。 BallManagerはprefabにつけるとよくないのですか。
退会済みユーザー

退会済みユーザー

2021/05/01 05:33

シーンに元から存在しているFirstBallそれにアタッチされているBallManagerスクリプトと prefabでInstantiateされたballにアタッチされるBallManagerスクリプトは別のインスタンスっていう部分は大丈夫ですか?
lain62

2021/05/01 05:45

その点を忘れていました...。参照型の話ですね。 ということは空のゲームオブジェクトを作ってそこでボールの管理をした方がいいのでしょか
lain62

2021/05/01 06:01

ItemManagerのBallをFirstBallに差し替えたら無事分裂してカウントが増えました。 ただボールが倍々ではなく一つずつしか増えないですね。
退会済みユーザー

退会済みユーザー

2021/05/01 06:01

どの様に管理するか?は自由ですので手法論についての回答は難しいです。 実現したい事(どういった動作をさせたいか?)を書いていただければ私なりのコードは提示できるかもしれません。
lain62

2021/05/01 06:26

ボールが倍々に増えるブロック崩しを作っています。 ブロック(まだ一つしか配置していませんが)を崩すと1/2の確率でアイテムが崩れたブロックから生成し、重力に沿って落ちていきます。アイテムが左右キーで移動できる(実装済み)バーに触れるとアイテムは破棄され現在sceneに存在しているボールがそれぞれ二つずつに分裂し、ドラえもんのバイバインのようにボールが二倍に増えます。下に落ちすぎたボールやバーに触れずに落ちたアイテムは破棄されます。 このボールが増える動作をGameObject型のListで管理しようとしていました。最初からボールは1つ存在していないとゲームは成り立たないためFirstBallを用意してBallManagerを割り当てていました。しかしヒエラルキーのItemにアタッチしていたItemManagerのインスペクタのBallをFirstBallに差し替えたところカウントが正常に働きましたがボールが一つずつしか増えない(倍々にならない)所で詰まっています。動作している様子は以下から確認できます(https://drive.google.com/file/d/1D2DSoGLehpb5XeFh22ppEz75pc-BGNHw/view?usp=sharing)
guest

回答2

0

ベストアンサー

方法の一つとして回答します。方法なのでこのやり方が正しい、間違っているという話ではないです。

まず、BallManagerを空のGameObject(とりあえずBallManagerという名前にしましょう)にアタッチします。ボールを複製する部分は同じような感じにしたつもりです。
ただ、追加したいballのListを別で作成しています。Listを回している最中にその同一のListに追加するっていう行為は問題があったはず、、、

public class BallManager : MonoBehaviour { public List<GameObject> balls = new List<GameObject>(); public GameObject ballPrefab; public void DoubleBalls() { var newBalls = new List<GameObject>(); foreach(var ball in balls) { var ballObj = Instantinate(ballPrefab, ball.transform.position, Quaternion.identity); newBalls.Add(ballObj); } foreach(var ball in newBalls) balls.Add(ball); } }

次に生成用のBall(instanceBallのprefab)にBallスクリプトを作ってそれをアタッチします。
ちょっと強引な気もしますが、ヒエラルキーからBallManagerというオブジェクトを見つけて、その中のBallManagerスクリプトのballsという管理用のListに自身から登録させます。
削除された時にBallManagerの中の自身も削除しなければいけません。
存在しない参照がリストに残ってしまいます。

public class Ball : MonoBehaviour { void Start() { GameObject.Find("BallManager").GetComponent<BallManager>().balls.Add(this.gameObject); } void OnDestroy() { GameObject.Find("BallManager").GetComponent<BallManager>().balls.Remove(this.gameObject); } }

FirstBallが必要であればこのBallスクリプトをアタッチしてください。ball自体を別で生成する(例えばキーが押されたら1つ目のボールを生成する、など)ならFirstBall自体も必要ないです。

発動の条件はitemからDoubleBallsメソッドを呼ぶとして、分裂する(倍々に増える)という部分だけですがこれで出来ると思います。

投稿2021/05/01 09:06

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

lain62

2021/05/01 10:01 編集

ありがとうございます!できました! ただBallManagerとprefabにくっついてるBall両方でAddしちゃってるらしくボールが3倍ずつ増えてしまったので,Ballスクリプトのstart内をコメントアウトしたら倍々に増えるようになりました。 実は以前のスクリプトでは実行するとunityが停止していたのですが、これはforeach内でListの要素を増やしているために起こっていたんですね。
guest

0

Instantiate(instanceBall,item.transform.position,Quaternion.identity); //ballリストのインデックスを倍にする ball.Add(instanceBall);

この部分を

var createBall = Instantiate(); ball.Add(createBall);

にしてみてください.これでListの数が増えると思います.

上のコードではリストに追加していたものは生成したオブジェクトではなくPrefabのためうまく追加できないのではないかと考えています(Objectの内部IDが同じだから..?,詳しいことは分かりませんが

投稿2021/05/01 02:35

編集2021/05/01 02:37
ayousanz

総合スコア258

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

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

lain62

2021/05/01 10:00

ありがとうございます! 色んな所がおかしかったみたいです。 解決できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問