パズルゲームの作り方講座の第3回ではunityスクリプトの書き方・使い方の導入を行いました。
前回の記事↓
第4回では、大きく分けて次の2つの処理を作成していきます。
- ボールを落とす位置の調整
- ボールの衝突判定の詳細設定
Unityではこうした機能追加を簡単に行えるように多くのメソッドや物理エンジンの機能が用意されています。便利な乱数の使い方もここで紹介します。
パズルゲームのボールを落とす位置の調整
まず、前回BallGeneratorから生成されるボールを落とす位置がゲームフィールド中央部でした。ここでフィールド上部からボールを落とすように調整します。
BallGeneratorの位置が低いので、BallGeneratorの位置をインスペクタから次の位置に変更しましょう。
オブジェクト名 | Position |
BallGenerator | (0, 12, 0) |
transform.localpositionを使って相対位置を指定する
では、次に実際にボールを生成する位置を変更する命令を追加しましょう。
BallGeneratorクラスのUpdate関数内を次のようにしましょう。
1 2 3 4 5 6 7 8 9 10 11 |
void Update() { cnt++; cnt%=MAXCNT; if(cnt==0) { GameObject gameObject = Instantiate(ballObj); gameObject.transform.parent = this.transform; gameObject.transform.localPosition = Vector3.zero; } } |
localPositionは親オブジェクト(BallGenerator)の相対位置を設定する変数です。localPositionにVector3.zeroで(0,0,0)の位置を与えると、子オブジェクトは親オブジェクトの位置に変換されて代入されます。
つまり、BallGeneratorの位置を変えるとボールの生成位置も変わるようになります。
すると次のように高い位置から落ちるようになります。
実際にコードを書くとわかりますが、ボールの落ちてくる角度が上記画像のようになっていないと思います(真下に落ちちゃってますよね)。
UnityのRandom.Rangeメソッドで落下するボールに角度を付ける
ボールの落下に角度をつけるためにもう一文コードを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 |
void Update() { cnt++; cnt%=MAXCNT; if(cnt==0) { GameObject gameObject = Instantiate(ballObj); gameObject.transform.parent = this.transform; gameObject.transform.localPosition = Vector3.zero; gameObject.GetComponent<Rigidbody>().AddForce(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-60.0f, 60.0f)) * Vector3.down * 10f, ForceMode.Impulse); } } |
gameObject.GetComponent<Rigidbody>().AddForce(Quaternion.Euler(0, 0, UnityEngine.Random.Range(-60.0f, 60.0f)) * Vector3.down * 10f, ForceMode.Impulse);
という行を追加しました。
UnityEngine.Random.Range(最小値, 最大値)は最小値から最大値未満の乱数を返すメソッドでUnityで用意されたものになります。
ballGeneratorで生成したボールがただ垂直落下しかしない問題に対処するために「-60~60度の範囲でボールを落とす方向を変える処理」を書いています。
この行は処理の内容が難しいので詳しい解説は割愛します(クォータニオンやオイラー角といった概念を使います。やや高度な物理・数学なのでひとまずスルーして先に進みましょう)。
ボールの衝突判定の設定 Unityのタグ機能とスクリプトを活用しよう
パズルゲームの作り方講座の第2回で、衝突判定について解説していきました。この衝突判定が発生したタイミングで処理を行う関数がUnityには用意されています。この処理を使って、ボール同士の衝突を検知する処理を書いていきます。
まずはBallObjectという名前でスクリプトを作成しましょう。
作成したら、プレハブ内のゲームオブジェクトBallにスクリプトBallObjectを追加しましょう。
スクリプトでの衝突判定の扱い方
衝突判定を検知する関数一覧は以下の通りです。
関数名 | 詳細 |
OnCollisionEnter | 衝突した1フレームのみ実行 |
OnCollisionStay | 衝突している間実行 |
OnCollisionExit | 衝突しなくなった1フレームのみ実行 |
今回は衝突した瞬間を使いたいため、OnCollisionEnter関数を使用します。Update関数の下に次のようなOnCollisionEnter関数を書いてみましょう。
1 2 3 4 5 6 7 8 9 |
void Update() { //---- 省略 ---- } void OnCollisionEnter(Collision other) { //ボールにぶつかったとき Debug.Log("ぶつかった!"); } |
書き終えたら、実行してみましょう。すると、Console上(例では画面右下)でゲームオブジェクトが衝突した際に「ぶつかった!」と表示されます。
【Tips】Unityのタグ(Tag)とは
先ほどのコードでは、ボールとフィールドが衝突した場合でも「ぶつかった!」と表示されてしまう問題があります。どのオブジェクトがぶつかったかを識別するために、ここからはタグ(Tag)を使用していきます。
タグは、ゲームオブジェクトを分類するときに使用する機能です。
まずは、プレハブ上のBallのインスペクタを開いてみましょう。
初めはTagが「Untagged」になっています。これをクリックして、Add Tagを選択してください。
そして、Tagsのリストの右下の+ボタンを押して「Ball」タグを追加してみてください。
最後に、Ballのインスペクタに戻ってTagをBallに設定します。これでタグをつけることができました。
それでは、衝突したオブジェクトがボールか否かを識別するコードを書いていきましょう。
次のようなコードを書いてください。
1 2 3 4 5 6 7 8 9 10 11 12 |
void OnCollisionEnter(Collision other) { //ボールにぶつかったとき if(other.gameObject.tag == "Ball") { Debug.Log("ボールにぶつかった!"); } else { Debug.Log("ボールじゃないところにぶつかった!"); } } |
このgameObject.tagを使ってタグ名を取得していることが分かります。タグ名がBallであるかどうかをif文により分岐させて出力を分けました。
それではこの状態で実行してみましょう。
ボール同士がぶつかった際は「ボールにぶつかった!」を、それ以外の時は「ボールじゃないところにぶつかった!」と表示されている様子が確認できます。
おさらいと次回予告
今回は、2つの処理をスクリプトに書いていきました。
- ボールを落とす位置の調整
- ボールの衝突判定の詳細設定
次回は、マウス入力の検知に関する処理について説明していきます。
次回の記事↓
パズルゲーム講座が動画になりました。
動画も合わせてチェック!
コメント
こんにちは。
unityの勉強中で当サイトを参考にさせていただいております。
1点「ボールを落とす位置の調整」でUnityのバージョンによって動作しない箇所がありましたので、コメントさせて頂きます。
—-
UnityEngine.Random.RandomRange(-60.0f,60.0f)
は
Random.Range(-60.0f,60.0f)
—-
こんにちは。ご報告ありがとうございます!
うちのサイトだとパズルゲーム講座が一番古い無料講座になるので一回2020LTSとかで再追試など進めて必要に応じて修正加筆進めていきます。