二代目備忘録

適当に勉強した事を忘れないように講座風に書き留めたりするブログ。

Unity備忘録14頁目「当たり判定」

江上宿六です。

 

当たり判定と書いてますけど割とあやふやな単語ですよね。 まぁ、衝突判定と

重なり判定をまとめて当たり判定と言うみたいなものだと思っていますが。

 

というわけで当たり判定です。 判定を行うにはRigidbodyとColliderが必要に

なりますが、CubeやSphereには最初からColliderがついています。 そして共に

Rigidbodyは追加しているのであとは判定をするだけなのですが、その前に

少しだけColliderを見てみましょう。

f:id:y6yegami:20180719114005p:plain

CubeについているCollider、BoxColliderです。 箱形のColliderでEditColliderを

クリックすると箱形になっているのがわかります。 Centerで中心点、Sizeで

サイズをそれぞれ変える事が出来ます。

f:id:y6yegami:20180719114644p:plain

f:id:y6yegami:20180719114653p:plain

試しにこんな風に値を変更してEditColliderを押すと、こんな風に判定を持つのが

わかると思います。 実際こんな風にする人は居ないでしょうけども。

IsTriggerという項目も大事なんですけど、そこは後回しにしておきます。

 

さて実際に判定を行っていきますが、そんなに難しくありません。

Cubeを操作するスクリプトを開き、記述していきます。

f:id:y6yegami:20180719115948p:plain

OnCollisionEnterという関数を作りました。 Colliderを持つオブジェクト同士が

衝突するとこの関数が呼ばれるので、この中に処理を書けば良いだけなのです。

引数で渡されたのが衝突したオブジェクトで、それを破棄するようにしています。

では実行してみましょう。

f:id:y6yegami:20180719120541p:plain

まぁ、非常に残念な事に床が破棄されてしまいました。 重力がかかると

一番最初に衝突するから当然ですが、まぁ、判定はちゃんと行われたわけです。

でも床には消えてもらいたくないので、区別して判定を行えるようにします。

 

メニューバーのEditからProjectSettings→TagsAndLayersを選択すると

インスペクターに表示されるのでTagsの所を開きます。

f:id:y6yegami:20180719124210p:plain

f:id:y6yegami:20180719124358p:plain

最初は何も入っていないので、+ボタンを押してPlane、Sphereという感じで

タグを作っていきます。 出来たらそれぞれオブジェクトにタグを設定します。

f:id:y6yegami:20180719124949p:plain

まずはPlaneを選択してインスペクター上部ののTagをクリックし、リストから

Planeを選択します。 続いてプロジェクトビューのSphereGeneratorを選択し、

同様にSphereを選択します、これでタグの設定が出来ました。 スクリプト

書き換えましょう。

f:id:y6yegami:20180719130605p:plain

衝突したオブジェクトのタグがSphereなら破棄する、という感じにしました。

f:id:y6yegami:20180719130947p:plain

実行すると床は破棄されずに残っており、CubeとSphereが衝突するとSphere

破棄されるようになりました。 後者は画像では分かりにくいですけども。

当たり判定はこんな感じでしょうか。

 

それでColliderのIsTriggerという項目なんですけども、これにチェックを入れると

衝突時に物理的な挙動が発生しなくなり、そのまま通り抜けていくようになります。

そしてオブジェクト同士が接触している間に判定を行ったりする事ができます。

f:id:y6yegami:20180719133217p:plain

 ↓

f:id:y6yegami:20180719133223p:plain

CubeのColliderのIsTriggerにチェックを入れ実行し、床に乗っかることなく

Cubeが落下していった時のログです。 IsTriggerにチェックを入れた場合は

それを判定する所の関数名もOnTriggerEnter等に変わるので注意です。

 

因みにでもなんでもないですが、OnCollisionの方にもStayとExitがあります。

Cubeが床に乗ってる時はCollisionStayが呼ばれる事になります。 Sphere

Destroyした時にはExitは発生していません。 という風に色々確認してみるのも

勉強になると思います。

 

今回はこんな感じで終わりです。 床を破棄してしまったのはガチの

アクシデントで、その流れでタグについても説明する事になってしまいました。

 

Unity備忘録13頁目「ランダム位置生成」

江上宿六です。

 

我ながら今回は面白みのない題材だとは思いますが、とりあえずやっていきます。

まぁ、ここまで作ったものだとただ単純にSphereが落ち続けるだけなので少し

手を加えてみることにします。 SphereGeneratorに追記します。

f:id:y6yegami:20180717150119p:plain

 目標時間が経過した時に行われる処理の中です。 float型のpxとpyを宣言し、

それぞれRandom.Rangeで値を取得しています。 これは引数1と引数2の間の値を

ランダムに返してくれるもので、ここのpxの場合は-5.0f~5.0f、pzは0.0f~10.0fを

得る事が出来ます。

 

このRandom.Rangeは少し注意が必要で、float型の場合は引数2の値を

受け取ることが出来ますが、int型にした場合でRandom.Range(0,10)とした場合は

10を受け取ることが出来ません。 覚えておくと良いと思います。

f:id:y6yegami:20180717151029p:plain

だいたいこんな感じで違う位置に生成されるのが確認出来ると思います。

もう少し何かやってみましょうか。 ヒエラルキーのCreateから3DObject→

Planeを選択してPlaneを追加してください。 これは平面ですね。 出来たら

インスペクターから位置を(0,0,5)に設定し、ゲームを実行してみましょう。

f:id:y6yegami:20180717151652p:plain

Planeの上にSphereが溜まっていき、Sphere同士が衝突して転がっていき

Planeからはじき出されていく、というそこそこ愉快な感じのものが出来ました。

 

更に何かアレンジしてみましょうか。

少し前にやった様にCubeを配置し、それを操作キャラとして動かして

Sphereを押し出してやるとか、そういう感じの事をしましょう。

ではC#Scriptを追加し、Cube用のスクリプトを書きましょう。 

f:id:y6yegami:20180718145650p:plain

6行目、mxとmzはGetAxisを使って傾きを取得するものです。

7行目のRigidbodyはこのスクリプト内でオブジェクトに追加されている

Rigidbodyを操作する為に宣言されたもので、宣言時はまだ空っぽです。

Start内でGetComponentを使ってRigidbodyを使える状態にしています。

 

Update内はGetAxisで取得した値を基に移動ベクトルを生成していて、

20行目で、this.rigidBody.positionにそのベクトルを加えています。 なんか

今まで通りにtransform.positionでも良さそうな気はしますが、Rigidbodyを

使っている場合はRigidBodyの方にした方が好ましいというのを見ましたので。

f:id:y6yegami:20180718144329p:plain

Sphereとぶつかる度にふわふわふらふらするCube君の出来上がりです。

こういう感じの環境と操作キャラが居るとなかなかそれだけでゲームっぽいです。

 

今回はこんな感じで。 次回は当たり判定関係で何かやりたいと思います。

Unity備忘録12頁目「時間経過で自動生成」

江上宿六です。

 

だいたい前回の続きなんですけども、Prefabについては掘り下げていないので

タイトルに関しては変わっています。 プロジェクトやシーンはそのままです。

 

さて前回はクリックしたらSphereを生成するように作りましたが、今回は

時間経過によって自動で生成するようにしてみます。 難しい事はないです。

早速SphereGeneratorスクリプトを編集します。

f:id:y6yegami:20180715174803p:plain

変わった所と言えば7行目、deltaというfloat型の変数が宣言されている点と、

10行目、Update内でそのdeltaにTime.deltaTimeを加算している所、11行目で

そのdeltaが1.0f以上ならdeltaを1.0f減算し、Instantiateをするという感じに

なっている所ですね。

 

Time.deltaTimeですが、これは前回のUpdateが呼ばれてから再び呼ばれるまでに

かかった時間を保持するもので、自分の環境で確認した所だいたい0.0166とか

入っていました。 その値をdeltaに加算していき1.0になるタイミングというのは

1秒が経過した時になるわけなんです。

 

1秒が経過したらプレハブからオブジェクトを生成し、再び1秒を測るために

1.0を引いています。 これ教本だとdeltaを0にしてるんですけど、個人的に

気持ちが悪いので1.0引いてます、誤差でしょうけども。 では実行しましょう。

f:id:y6yegami:20180715175143p:plain

こんな感じで正確には分からないにしても1秒くらいの感覚で生成されています。

時間を計れることで出来るのは敵や弾の時限生成だけでなく、幅広く使う事が

出来るので覚えておくと役に立つと思います。

 

この生成間隔をいじるには、もちろんif文の1.0を変えれば良いわけですけども、

なんとなくこういう方法を提案してみます。

f:id:y6yegami:20180715175745p:plain

 targetという変数をpublicで宣言し1.0で初期化しました。 if文の所の1.0や

条件が通ったときにdeltaから引く値をtargetにしました。 これでこのtargetの

1.0を変更すれば自由に生成間隔を変えられますね。

f:id:y6yegami:20180715180049p:plain

だけだと思ったら大違いです。 publicにしてるのでインスペクターから

生成間隔をいじることが出来るんですよね、これ。 便利だなあ。

f:id:y6yegami:20180715180338p:plain

極端に小さい値にして遊ぶのは基本です、しかしだいたい0.0166くらいが限度。

それくらいに一回くらいしかUpdateは呼ばれませんからね、基本的に。

 

という事で今回はここまでにしますか。 

次回は、とりあえず乱数とかについて記してみるかもしれません。

なんとなく思った事。

江上宿六です。

 

備忘録を綴っていくのは理解が進むので良いんですけども、Unityに関連した

内容でなければあまり意味は無いなあとか。 もちろん既存の知識を使うのに

Unityではどうすれば良いかを確認して記すのには意味があると思いますけど、

乱数を使ったりとか、それだけの頁があっても何かなあと思ったわけです。

 

とりあえずいくつかそういう内容の書き溜めてある頁があるわけですが、

さらっと流してもっとUnityっぽいというかゲーム制作に関わる部分について

書いていきたい感じですね。 それともう一つの悩みはこっちにかける時間が

若干長くて企画の方が今一つ進まないところですかね。

 

あの空間の話は、あんまり気分じゃないかも。 フレはわんさか増えるけど

かまってちゃんだし、周りも割と構ってくれるけど、なんか悪いなあって。 それに

どちらかというとかまってちゃんに構ってあげたい方でもあるんだよなあ、自分。

金と環境と勇気と行動力があればなあ。

Unity備忘録11頁目「Prefabを作ってみる2」

江上宿六です。

 

前回は結局Prefabを作れなかったという情けない感じでしたけども今回こそです。

では早速作りましょう。 実はPrefabを作るのは簡単で、オブジェクトを

ヒエラルキーからプロジェクトビューにドラッグするだけです。

f:id:y6yegami:20180714184434p:plainf:id:y6yegami:20180714184536p:plain

こんな感じでプロジェクトビューに追加されました、これがPrefabです。

名前がこのままだと何かアレといいますか微妙なのでSphereGeneratorにします。

名前変更と同時にヒエラルキーSphereも名前が変わりました。 この2つは

連動したオブジェクトだということですね。 ですがこのヒエラルキーの方の

SphereGenerator(改名後)は要らないのでDeleteしてしまってください。

 

さて、ではいかにしてこのSphereGeneratorを使うかです。 ここでもまた

スクリプトの出番となります。 C#Scriptを追加し、こちらもSphereGeneratorと

名付けます。 ちょっと融通が利いてない感じでアレですが、記述します。

f:id:y6yegami:20180714190129p:plain

6行目でGameObject型のspherePrefabをpublicで宣言しています、これは

後ほど説明するので今はスルーします。 Update内ではキー入力を取得してます。

見ての通り左クリックをすると中が実行されるようになっています。

 

その中身が大切なんですね。 まずGameObjectのsphereを宣言し、それに

Instantiate(spherePrefab)を代入しています。 これはspherePrefabを複製した

ようなものをsphereに代入して、シーンに生成しているというわけなんです。

 

謎の学校例えをしてみますが、

 

・テストの問題を作る←オブジェクトを作る

・それを印刷できる状態にする←Prefabにする

・印刷する←Prefabを指定してInstantiateする

 

伝わったかどうかはアレですけど、Prefabというのはオブジェクトの設計図で

その設計図を元にオブジェクトを生成するのがInstantiateという事です。

 

as GameObjectというのはキャストです。 Instantiateで得られるのは確か

Object型なので、強制的にGameObject型にしています。 問題は無いようです。

その後のsphere.transform.positionは、その生成されたオブジェクトの位置を

(0,5,0)に設定しています。

 

それではCreateEmptyでヒエラルキーに空のオブジェクトを追加し、

スクリプトをアタッチしたら実行して画面をクリックしてみましょう。

 

はい、何も起きませんというか、何かエラーっぽいのが出ます。 ここで実行して

完成という下書きを書いてしまったため、戒めの為にこんな書き方にしました。

本当に大事な事を忘れていました。

 

えー、それではスクリプトがアタッチされた空のオブジェクトを選択して

インスペクターを見てみましょう。

f:id:y6yegami:20180715161629p:plain

なんの変哲も無い、と思いきやなんか今までのとは雰囲気が違います。

Cubeをいじってた時にはなかったSpherePrefabという項目が増えています。

これは何かというと、SphereGeneratorの中身を振り返ってみましょう。

 

publicでsphereGeneratorというGameObjectを宣言しています。

このようにpublicで宣言を行う事で、インスペクターに表示されるようになり、

外部から数値を変更出来たり、オブジェクトを渡す事が出来るようになるのです。

これをアウトレット接続といいます。

 

じゃあ何を接続するかですが、変数名などからなんとなく分かると思います。

Prefabです、SphereGeneratorです。 アタッチするのと同様にPrefabを

インスペクターのSpherePrefabの所にドラッグ&ドロップしてやります。

f:id:y6yegami:20180715162811p:plain

f:id:y6yegami:20180715162823p:plain

接続するとこんな感じになります。 では実行してクリックしてみましょう。

f:id:y6yegami:20180714200759p:plain

クリックしたらした分だけ指定の場所(0,5,0)にSphereが生成され、それぞれ

下に落ち、消えていくと思います。 連打しすぎるとSphere同士がぶつかって

変な挙動をするかもしれませんが、そこは単に愛嬌です。

 

このようにPrefabを作る事によって同じようなオブジェクトを大量に生成したり

色々な事が出来るわけなんです。 次回はPrefabを使って時限でオブジェクトを

生成したり、そういう事をやると思います。