リヨスケのチラシ裏

学んだことを書き留めていく自分のための技術メモです。

【Unity】メイン画面上にマウスに追従する望遠カメラ画面を表示したい

狙撃銃のスコープのような望遠画面をメインカメラの画面の上に表示し、FPSのようにマウスで動かせるようにしたメモです。

 

↓のような感じに。

f:id:riyosuke_13:20180513114527g:plain

 

カメラを用意

メインカメラとは別に新規にカメラを用意し、transformをメインカメラと同じ位置に設定します。

狙撃銃のようなスコープにしたいので、インスペクターの「Field of View」を調整します。(今回は2に設定)

f:id:riyosuke_13:20180513115229p:plain

f:id:riyosuke_13:20180513115252p:plain

このようにぐっと拡大して表示されるようになります。

 

カメラをメインカメラの画面上に配置する

今の状態ではメインカメラを完全に隠してしまっていうるので、メインカメラ画面の上に小さく表示されるようにします。

レンダーテクスチャというものを作成し、スコープ用カメラの映像をリアルタイムで表示するテクスチャを用意。

それをGUIのイメージのテクスチャとして設定して画面上に表示するようにします。

こちらのサイトを参考にしました。

gametukurikata.com

 

手順は以下のとおり

  1. ProjectからCreate→「Render Texture」でレンダーテクスチャを作成
  2. 用意したスコープ用カメラの「Target Texture」に作成したレンダーテクスチャを設定
  3. Hierarchyに新規にCanvasを作成し、その子として「Raw Image」作成
  4. 「Raw Image(Script)」コンポーネントの「Texture」にレンダーテクスチャを設定

f:id:riyosuke_13:20180513120619p:plain

見辛いので赤枠で囲っていますが、メインカメラ画面の上にスコープ用カメラの画面が小さく表示されるようになりました。

 

マスクをかける

このままではスコープっぽくないので、マスクをかけて丸く表示されるようにします。

ヒエラルキービューのCanvasを右クリックし、Panelを作成します。

Panelのインスペクターで「Add Componet」→「UI」→「Mask」を選択。

「Source Image」から「knob」を選択して大きさを調整します。

f:id:riyosuke_13:20180513120738p:plain

このPanelの子として先ほどのスコープ用画面のRow Imageを配置してやると、以下のようにマスクがかけられた状態で表示されます。

f:id:riyosuke_13:20180513120805p:plain

 

スクリプトの作成

スコープ用の画面をメインカメラ上に表示するところまで実装できました。

次に、このスコープ用の画面をマウスの動きにぴったり合わせて動くようにします。

 

以下の方法をとりました。

  1. メインカメラからレイを投げる
  2. レイが衝突したコライダーの情報からpositionを取得する
  3. positionをワールド空間のものからスクリーン空間のものへ変換する
  4. 変換したpositionをスコープ用画面のRectTransformに渡す

ソースコードは以下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ScopeRendar : MonoBehaviour {

    RectTransform scopeRect;
    private float camRayLength = 80000f;

    void Start () {
        scopeRect = GetComponent<RectTransform>();
    }

    void Update () {
        // メインカメラからマウス位置までレイを取得
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        // 以下のRaycasで投げられたレイが衝突したコライダーの情報を詰め込むオブジェクトを用意
        RaycastHit floorHit;
        // レイを投げ、コライダーに衝突した場合はfloorHitにそのコライダーの情報を詰めて以降の処理を実施する
        if (Physics.Raycast(ray, out floorHit, camRayLength)) {
            // 第2引数であるレイが衝突したコライダーのpositionを、ワールド空間のものからメインカメラ画面のスクリーン空間のものへ変換する
            scopeRect.position = RectTransformUtility.WorldToScreenPoint(Camera.main, floorHit.point);
        }
    }
}

 まずScreenPointToRay関数で画面上のマウス位置に相当するワールド空間へのレイを取得します。

平面である画面の座標を立体であるワールド座標にうまく変換した上でレイを発してくれます。

 

次に、Raycast関数を使ってレイが衝突したコライダーの情報を取得します。

outキーワードによってあらかじめ用意したRaycastHit型のオブジェクトにコライダー情報を詰めてくれます。

ソースコード上の80000fはレイを投げる最大距離であり、今回の数値設定はテキトーです(汗

 

取得したコライダー情報から座標を抜き出し、RectTransformUtilityのWorldToScreenPoint関数でワールド座標からスクリーン座標へ変換し、スコープ用画面に渡します。

guiにはTransformではなく、RectTransformで位置を調整する必要があります。

 

作成したスクリプトをスコープ用画面にアタッチします。

この時に、Row Imageの方にアタッチするとマスクが動かずに取り残されてしまいます。

なのでマスクであるPanelにアタッチし、親子関係を利用して一緒に動くようにします。

 

これでマウスに合わせて動くスコープができ・・・ま・・・

f:id:riyosuke_13:20180513121611g:plain

できてない。スコープ画面の中身が動いてないです。。

スコープ用カメラの向きををマウス位置に合わせて動かすのを忘れていました(汗

 

スクリプトを作成。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ScopeContoroller : MonoBehaviour {

    private float camRayLength = 80000f;

    void Start () {

    }
    
    void Update () {
        Aim();
    }

    void Aim() {
        RaycastHit floorHit;
        if (Physics.Raycast(GetRayFromMainCamera(), out floorHit, camRayLength)) {
            transform.LookAt(floorHit.point);
        }
    }

    public Ray GetRayFromMainCamera() {
        return Camera.main.ScreenPointToRay(Input.mousePosition);
    }
}
 

 先と同様にメインカメラから投げたレイの衝突情報から座標を取得し、LookAt関数でサブカメラの向きを変更します。

今回はどちらもワールド座標なので変換は必要ありません。

 

このスクリプトをスコープ用カメラにアタッチすれば今度こそ冒頭のような動きになります。

 

 

 

マウス位置を取得してスコープ用画面を動かすのはいちいちレイなんて投げなくても直接Input.mousePositionを変換して渡してやればいけるかなと思ったのですが、なぜかうまくいきませんでした。

あとは、メインカメラからのレイを取得する部分などコードが重複しているところを共通化したいですね。

ネームスペースをちゃんと活用すればまとめられるのかな?

要勉強です。

【Unity】パーティクルだけ残して親オブジェクトを消す

パーティクルだけ残して親オブジェクトを消そうとしてハマったのでメモ。

 

結論から言うと、以下のように対処しました。

  1. 親オブジェクトを消したいタイミングで透明化
  2. パーティクルの再生が終わったらパーティクルシステムの"Stop Action"でDestroyする。

経緯としては、「爆弾」を投げて「ターゲット」に当たったら爆発エフェクトを残して爆弾とターゲットを消すということをやろうとしてました。

はじめはパーティクルシステムの"Stop Action"でDestroyするだけで済むと思っていたのですが、これだとパーティクルの再生が終わるまで爆弾が出っぱなしになってしまいます。

そこでいくつか試してみました。

 

親オブジェクトである爆弾を破棄

無理だろうなと思いましたが一応やってみました。

無理でした。

当然ながら親オブジェクトが破棄された時点で子オブジェクトであるパーティクルも破棄されます。

破棄ではなく無効でも同じことでした。

 

パーティクルのプロパティーでなんとかする

パーティクルの生存時間を極端に短くし、"Start Speed"を早めに設定して短い時間で展開するように設定しました。

さらに"Simulation Speed"を3にしてWorldの時間よりも高速で再生するように。

パーティクルの再生が終わるまでオブジェクトが消えないのは変わりませんが、一瞬の出来事なので気にならないといえば気になりません。

ただこれだと爆発などの速いエフェクトならまだしも、ゆっくりのエフェクトだけ残すということができないのでボツ。

 

親オブジェクトを透明化

ようは削除したように見えさえすればいいので、破棄するのではなくパーティクルの再生が終わるまで親オブジェクトを一旦透明にすることに。

オブジェクトを透明化するにはそのオブジェクトが持つ"Mesh Renderer"をスクリプト内から操作します。

MeshRenderer meshRenderer = sphere.GetComponent<MeshRenderer>();

meshRenderer.material.color = new Color(0, 0, 0, 0.0f);

 Color()の4つ目の引数のAlpha値であり、これを0にすると透明にな・・・らない。

オブジェクトが黒くなるだけで透明になりません。なぜ。

調べてみると"Rendering Mode"がデフォルトの"Opaque"は透明部分を持つことのない設定のようです。

なのでこれを"Fade"に変えてやると無事透明にすることができました。

ちなみに"Fade"の場合はAlphaを0に近づけていくと名前の通りフェードアウトしていくように透明になります。

一方で"Transparent"は完全な透明ではなく、ガラスのような質感の透明なオブジェクトになります。

"Cutout"の場合は半透明という状態が存在せず、100%不透明か完全な透明かしかありません。

デフォルトの"Opaque"は0に近づけていくとオブジェクトが黒くなっていきます。

 

さて、これで親オブジェクトを見え無くすることができましたが破棄されたわけではないのでパーティクルはしっかり再生されます。

そして再生後に"Stop Action"で今度こそ親オブジェクトを消してしまえば目的達成です。

 

おまけでつまづいたこと

爆弾を連続で同じ場所に投げたとき、1つ目の「見えないけど存在している」爆弾に2つ目の爆弾が当たってしまう現象が起きました。

先と同様にDestoryすることはできないので、爆弾が何かにぶつかったときに爆弾の持っているコライダーを無効化することで対処しました。

これで同じ場所になげても爆弾同士がぶつからずに済みます。

 

あるいはタグでぶつかる対象を制御する方が早いかもしれませんね。

 

【Unity】Perticleシステムのプロパティーを確認

パーティクルシステムに触れたのでプロパティーのメモを。

 目次だけでひどいことに・・・

メインモジュール

Duration

パーティクルを発生させる時間の長さ。値の時間が1サイクル分になる。

Looping

これにチェックが入っているとDurationで設定した時間を再生し終わるとすぐに最初からループする。

Prewarm

Loopingが有効の時のみ動作。チェックを入れるとすでに1サイクル完了した状態で初期化される。

たとえば、長い時間ゆっくりと進み続けるパーティクルの場合、Prewarmがオフの場合は最初のパーティクルが出現するところから始まるが、Prewarmがオンの場合はパーティクルの動作が開始した直後から1サイクル分のパーティクルが展開された状態になっている。

Start Delay

パーティクルの放出を始めるタイミングを遅らせる。

Start Lifetime

パーティクルの最初の生存期間。この値が大きいほど長い時間パーティクルが残り続ける。

Start Speed

各パーティクルの初速。大きいほど速く放出される。

3D Start Size

各軸のサイズを別々に管理できる。(横長のパーティクルにしたりできる)

Start Size

各パーティクルの最初のサイズ。

3D Start Rotation

各軸の回転を別々に管理できる。パーティクルを傾けて放出させられる。

Start Rotation

各パーティクルの最初の回転角度(傾き)。

Randamize Rotation Direction

各パーティクルの回転方向をランダムで決定する。

Start Color

各パーティクルの最初の色。

Gravity Modifier

パーティクルにかかる重力値。0で無重力。

Simulation Space

Local : そのパーティクルがアタッチされたオブジェクトと一緒にすでに放出されたパーティクルも移動する。

Wold : アタッチされたオブジェクトが動いてもすでに放出されたパーティクルは一緒に動かない(放出点は動く)

Custom:選択したカスタムのオブジェクトと一緒に動く。

Simulation Speed

パーティクルシステム全体を更新するスピード。値が大きいと早送りになる。

Delta Time

Scaled : Time ManagerのTime Scaleに従う。

Unscaled : ゲームの時間が止まっても(ポーズなど)パーティクルは動き続ける。

Scaling Mode

親オブジェクトのスケールに依存するかなどの設定を行う。

Play on Awake

オブジェクトが生成された時にパーティクルを自動的に起動するか否か。

Emitter Velocity

速度計算方法。RigidbodyとTransformのどちらの動きを追跡して速度計算を行うか。

Max Particles

同時に存在できるパーティクルの最大数。

Auto Random Seed

オンにするとパーティクルを再生するたびに違った動きを見せる。オフにすると再生するたびに全く同じように放出される。

Random Seed

Auto Random Seedgaが無効かつ特有の繰り返しが可能なエフェクトを作成する際に使用する。

Stop Action

パーティクルが全て終了した時に指定したアクションを実行させる。

Disable : パーティクルの再生が完了したらそのパーティクルの親オブジェクトを無効(非アクティブ)にする。

Destroy : パーティクルの再生が完了したらそのパーティクルの親オブジェクトを破棄する。

Callback : 親オブジェクトにアタッチされたスクリプト内のOnParticleSystemStopped()を呼び出す。

 

ここまでがメインモジュールで設定できるプロパティーです。

多い・・・

でもまだまだそのほかのモジュールがたくさんあります。

さすがに多すぎるのでモジュールのメモだけにして各モジュールのそれぞれのプロパティーは省略します。

その他のモジュール

Emmision

放射の頻度や量を調整。バースト(設定した時間・量・間隔でパーティクルを放出)の調整はこのモジュールで行う。

Shape

エミッター(バーティクルの放出源)の形状の設定を行う。

Velocity Over Lifetime

パーティクルの再生中の速度制御を行う。x,y,z軸ごとの速度も指定できる。

Limit Velocity Over Lifetime

パーティクル再生中の速度減少の制御を行う。空気抵抗によりパーティクルが減速するような表現ができる。

Inherit Velocity

エミッターから継承されるパーティクルのスピードをどうするかの制御を行う。とのことですが実際に動かしてみてもよくわかりませんでした。。。

Force Over Lifetime

時間経過によるパーティクルの加速の制御を行う。

Color Over Lifetime

時間経過によるパーティクルの透明度の変化の制御を行う。

Color By Speed

パーティクルの速度変化によるパーティクルの色の変化を制御する。爆発の火の粉が減速するにつれて暗い色になったりなどの表現ができる。

Size Over Lifetime

パーティクルの再生時間に応じてパーティクルのサイズを変化させる。カーブによって設定し、吹き出す炎が徐々に大きくなった後急激に小さくなる表現などができる。

Size By Speed

パーティクルの速度に応じてサイズを変化させる。ランダムな速度でパーティクルが放出される際に早いものは小さく、遅いものは大きくしたい時に便利。

Limit Velocity Over Lifetimeと併用してしまうと放出後にサイズが変化してしまうため、前述の表現とはそぐわなくなる注意。

Rotation Over Lifetime

パーティクルの移動に伴う回転を制御する。舞う木の葉などの表現に便利。

Rotation By Speed

パーティクルの速度に伴う回転を制御する。転がるものに速度にあった回転をかけたい場合に便利。

External Forces

Terrainのwind zonesによってパーティクルが吹き飛ばされるようにできる。

Noise

パーティクルに乱気流のような「揺らぎ」を発生させる。

Collision

固形オブジェクトとの衝突判定の設定を行う。

Trigger

パーティクルがコライダー内に出入りする際にスクリプトの処理を呼び出すことができる。

Sub Emitters

ブエミッターの設定を行う。パーティクルが発生した時、衝突した時、破棄された時にトリガーを設定可能。複数管理ができる(パフォーマスへの影響に注意)。

Texture Sheet Animation

テクスチャをパーティクルとして使用することできる(パラパラ漫画みたいに?)。その制御を行う。

Lights

パーティクルにプレハブとして作成したLightを割り当て設定できる。

Trails

パーティクルにトレイル(尾を引くようなエフェクト)を設定できる。

Custom Data

パーティクルにアタッチするカスタムのデータ形式をエディターで定義できる。

Renderer

パーティクルのレンダリングに関する設定を行う。このモジュールのMaterialに何も設定されていないとピンク色(エラーカラー)の四角が放出される。

 

 

ほんとに多い・・・

でもどれも設定をカチカチするだけで簡単にそれっぽいエフェクトが作れるので是非マスターしたいですね。

 

 

【Unity】Mecanimでアニメーションを作成した雑メモ

Mecanimシステムを使ってアニメーションを作成したときに触ったものをメモります。

 

Animation Clipを作成する

  1. アニメーションを設定したいオブジェクトを選択した状態で、ツールバーの「Window」→「Animation」
  2. 画面真ん中らへんにある「Create」ボタンをクリックして任意の名前で保存(Animation Clipが作成される)

    f:id:riyosuke_13:20180401203101j:plain

    すでにAnimation Clipがあり、新しく追加する場合は、Animationウィンドウ左上のドロップダウンリストから「Create New Clip」を選択し、任意の名前で保存する
  3. 「Add Property」から「Sprite Renderer」を選択
    スプライトをプロジェクトビューからドラッグ&ドロップし、任意の時間の場所にキーフレーム(Keyframe)をセットする
最後のに追加するスプライトは、持続させたい時間の後にもう一つ同じものをセットさせてやる必要があります。

 

AnimatorウィンドウでAnimation Clipの遷移を管理する

Animatorウィンドウを開く(以下のいずれかの方法で)
  • ツールバーの「Window」→「Animator」
  • プロジェクトビューのいずれかのAnimation Clipをダブルクリック

    f:id:riyosuke_13:20180401203107j:plain

最初から用意されている「Entry」「Any State」「Exit」の3つのノードがあります。

  • Entry:アニメーションを開始するときはEntryノードから遷移する
  • Any State:現在の状態にかかわらずに特定のアニメーションに遷移したいときに使用する
  • Exit:アニメーションを終了させる場合はExitノードに遷移する

初期位置だとExitノードはやたら遠くにあるので画面が小さい場合は見えないかもしれないので、動かして確認します。(気づかずにちょっとハマりました。。。)
すでにAnimation Clipが存在している場合は、それらもAnimationウィンドウに表示されます。(画像の中だと「Walk」と「Jump」)

1Animation Clipにつき1ノードですね。

 

ノードをつなぐ

遷移元のノードを右クリック→「Mate Transition」を選択すると、矢印が伸びます。

この状態で遷移先のノードをクリックすると遷移ができるようになります。

この矢印を選択した状態でインスペクターから詳細な設定が可能です。

f:id:riyosuke_13:20180401204354j:plain

 

 条件を満たしたときに遷移させる

  1. Animatorウィンドウ左上の「Parameters」タブを開くf:id:riyosuke_13:20180401204351j:plain
  2. 「+」ボタンをクリックし「Trigger」を選択し、任意の名前を付ける
  3. 遷移条件を設定したい矢印をクリックして選択し、インスペクターの「Conditions」の「+」をクリック

    f:id:riyosuke_13:20180401204823j:plain

  4. リストの中から作成したTriggerを選択する

 

このTriggerをスクリプトで呼び出す場合は、AnimatorコンポーネントのSetTrigger関数を使用します。

あらかじめAnimatorを宣言し、初期化しておいて以下のように呼び出したいTriggerの名前を引数に渡してやるとTriggerを起動?することができます。

this.animtor.SetTrigger("呼び出したいTriggerの名前");

 

 

とりあえず触ったもののメモ程度なので、Animationについてきちんと調べるのはまた今度。

 

【Unity】Rigidbody 2DのBody Typeについて

Rigidbody 2DとRigidbodyではInspectorで設定できる内容が大分違ったので調べてみました。

 

Body Type

選択肢が以下の3つあり、どれを選ぶかによってそのあとの設定項目も変わる(増減する)ようです。

  • Dynamic (動的)
    重力などの外部からの力に影響を受ける
    他のどのタイプとのBody Typeとも衝突できる
  • Kinematic (キネマティック)
    Dynamicがうけるような重力や力の影響を受けない
    衝突の検知は物理クエリを使用し、移動はスクリプトを使用する
    衝突はDynamicとのみ発生する(他のKinematicやStaticとは衝突しない)
    力の影響を受けないため、衝突しても動かない
  • Static (静的)
    全く動かないオブジェクトとしてふるまう
    衝突判定はDynamicとのみ発生?

 

Dynamic (動的)

設定できる項目が一番多いBody Typeです。

Unity上で計算される重力などの外部からの力の影響を受けます。重力によって下方向に引っ張られるし、摩擦などの影響も受けます。

当然、他のオブジェクトにぶつかられたりして発生する力の影響も受けます。

 

衝突判定はDynamic、Kinematic、Staticのタイプとも発生します。

ただし、「Simulated」のチェックを外した場合はこれらの力の影響を受けなくなります。

 

Kinematic (キネマティック)

Dynamicで設定できた質量や減衰値、重力などの項目が消えています。

これは、Kinematicが重力などの外部の力の影響を受けないからのようです。

つまりKinematicに設定されたオブジェクトは他のオブジェクトにぶつかられたりしてもびくともしません。

ただ、スクリプトの制御によって動かすことはできます。

 

Rigidbody2DをアタッチせずにCollider2Dをアタッチした静的コライダーをトランスフォームをいじるなどしてうごかそうとすると物理エンジンのパフォーマンスに多大な影響を与えるらしく、非推奨とされています。

Kinematicであればその問題が解決されるというわけですね。

 

衝突判定はDynamicとのみ発生し、他のKinematicやStaticとは発生しません。

外部の力を全く受けず、プレイヤーなど動的なオブジェクトを蹴散らしてでも決められた動きをさせたいときに使えそうです。

「Kinematicだけどすべてのオブジェクトと衝突判定を出したい!」というときには「Use Full Kinematic Contacts」にチェックを入れると可能なようです。

衝突した場合はやはりびくともしない無限の質量を持ったオブジェクトのふるまいをするとのこと。

こちらも「Simulated」の項目はあり、チェックを外した場合は衝突判定は発生しなくなります。

 

Static (静的)

設定できる項目が「Material」と「Simulated」の2つしかありません。

StaicはRigidbody2DをアタッチせずにCollider2Dのみをアタッチした静的コライダーと同じふるまいをします。

つまり、全く動かす気のない足場や障害物などの設定に向いています。

じゃあ静的コライダーとStaticにしたRigidbody2Dの何が違うのかというと、衝突判定というか、Colliderの有効・無効を効率的に切り替えられる点、とのこと。

コスト管理を意識するときにこちらの設定に気を回せるといいみたいですね。

 

 

・・・と、公式リファレンス必死に読んでたけど以下の記事が死ぬほど分かりやすかったです。

tsubakit1.hateblo.jp

もっと早く見つけたかった。。。

【Part3】チュートリアルの玉転がし_スクリプト編【Unity勉強】

チュートリアル01 玉転がしゲームで使用したスクリプトについてのメモです。

 

FixedUpdate

 

玉を動かす際に使用しました。
Updateが1フレームごとに呼び出されるのに対し、
FixedUpdateは一定時間(デフォルトは0.02秒)ごとに呼び出されます。

 

フレーム/秒(fps)はコンピュータの処理速度に依存するので、必ずしも一定間隔なわけではないので、
1フレームごとに呼び出されるUpdateは不規則なタイミングで呼び出されることになります。

 

FixedUpdateはフレーム毎ではなく決められた時間間隔で呼び出されるので、規則的なタイミングで呼び出されます。

物理演算を行うRigidbodyの処理はUpdateではなくFixedUpdate内に書くべきなようです。
逆にInputの処理はFixedUpdateではなくUpdate内に書くべきだそうです。

理由についてはこの方の記事が分かりやすかったです。 

mediamonster.blog.fc2.com

 

Input.GetAxis()

 

玉を動かすための力をかける方向を制御する際に使用しました。
GetAxis()の引数に"Vertical"や"Horizontal"など(axisNameというらしい)を渡してやることで、
その軸のにおける値を返してくれるようです。

今回のチュートリアルスクリプトだとこのInputクラスのメソッドをFixedUpdate内に書いていたけど、いいのでしょうか。。。

 

 

Component.GetComponen

 

スクリプト上から、そのスクリプトをアタッチしているゲームオブジェクトのコンポーネントを取得する際に使用しました。

例えば、スクリプトをアタッチしたゲームオブジェクトからRigidbodyコンポーネントを取得したい場合は以下のように
Rigidbody rb = GetComponent<Rigidbody>();
とすることで、Rigidbodyクラスのインスタスの参照を取得することができます。
参照を取得したインスタスから、そのクラスが持つメソッドを呼び出すことができます。

 


Rigidbody.AddForce

 

玉を動かすための力を与える際に使用しました。
上記のGetComponetで取得したRigidbodyクラスのインスタスから呼び出し、引数にGetAxisで取得した軸方向の値と、
その値にかける力の大きさを渡してやりました。
例)
rb.AddForce(x軸への力, y軸への力, z軸への力) 他にも、Vector3を引数として利用する方法があったり、力のかけ方の詳細を設定するForceModeを渡すこともできるようです。

 


OnCollisionEnterとOnTriggerEnter


どちらも衝突判定時に処理を行いたいときに使用しました。
OnCollisionEnterは玉が壁と接触したときに、
OnTriggerEnterは玉がアイテムと接触したときに使用しました。

 

で、ColisionとToriggerでどう違うのか。
自分も調べて余計に混乱しているのですが、とりあえず、程度の認識で言うと、
「衝突させるオブジェクトのColliderのIs Triggerにチェックが入っているか否か」

 

Insperctorビューの〇〇ColliderにはIs Triggerという項目があり、こいつにチェックを入れるとRigidbodyを持ったオブジェクトが接触しても衝突判定を行わなくなります。
接触するけど衝突しないってなんだと思いましたが、ようするにぶつかってもすり抜けるよ、ということのようです。
ただし、OnTriggerEnterのうような、「OnTrigger〇〇」の呼び出しは行われるのでこれらの中に処理を書いてやればオブジェクトが接触対象に触れたときなどにイベントを発生させることができます。

 

Is Triggerにチェックを入れない場合はRigidbodyを持ったオブジェクトが接触した場合に衝突判定が発生します。
すり抜けずに止まるなり跳ね返るなりするよーってことですかね。
このときに呼ばれるのがOnCollisionEnterのような、「OnCollision〇〇」になります。
Is Triggerにチェックが入っていなくても、ぶつかる側・ぶつかられる側どちらもRigidbodyを持っていない場合は衝突判定は発生しないので注意です。

 

  • 接触するけどすり抜けて、かつなんらかのイベントを発生させたい(アイテムに触れたら回復!とか)ときは、Is Triggerにチェックを入れてOnTrigger系
  • 接触したらすり抜けず、かつなんらかのイベントを発生させたい(ぶつかって跳ね返りつつダメージ発生!とか)ときは、Is Triggerにチェックを入れずOnCollision系

 

・・・で、あってるでしょうか?

詳しい検証を行っている以下の記事を参考に、かなり噛み砕いて解釈しています。

gametukurikata.com

 


SceneManagement


玉が壁にぶつかったら最初からやり直しという機能をつける際に使用しました。
実際に使ったのはSceneManager.GetActiveScene().buildIndexとSceneManager.LoadScene()です。

 

SceneManagerは名前の通りシーンを管理するためのクラスです。
SceneとSceneManagerという構造体を持ちます。

 

・・・やばい、知識が足りてないので後日SceneManagement単体でしっかり調べたいと思ます。

 

ひとまず今回使用したGetActiveScene()とLoadScene()について。

 

GetActiveScene()は現在アクティブなシーンを取得します。
チュートリアル内では、アクティブなシーンを取得した後さらにSecne構造体の持つ変数のbuildIndexからそのシーンのインデックスを取得しています。

 

LoadScene()はシーンの名前あるいはインデックスを引数として受け取り、対応したシーンをロードします。
今回は上記のGetActiveScene().buildIndexで取得したインデックスを渡してロードすることにより、ゲームのリスタート機能を実装しています。

 

 

衝突判定とSceneManagementについては後日深掘りが必要ですね・・・。

【Part2】チュートリアルの玉転がし【Unity勉強】

チュートリアルで玉転がしゲームを作ったので、そのときのメモえを。

unity3d.com

 

オブジェクトを作成したい

Hierarchyビューで「Create」。以下から作成したいものを選ぶ。
 Create Empty:空のゲームオブジェクトを作成する。
 Create Enpty Child:選択中のゲームオブジェクトの子オブジェクトを作成する(階層化)。
 3D Object:3Dのオブジェクトを作成する。
 2D Object:2Dのオブジェクトを作成する。
 Light:光源を作成する。
 Audio:音源を作成する。
 Video:映像プレイヤーを作成する。
 UI:UIを作成する。
 Vuforia:AR(拡張現実)を作成する際に利用するオブジェクトを作成する。
 Camera:カメラを作成する。

 

オブジェクトの位置や向き、大きさを変えたい

Inspectorビューから操作する。

Transform

 オブジェクトの座標や角度、サイズの管理

 Position:座標

 Rotation:回転

 Scale:サイズ

 

オブジェクトの色を変えたい

Unityでは、オブジェクトの色を変える場合、まずMaterialを作成する。

Materialの作成はProjectブラウザから行う。

選択したMaterialのInspectorビューで、Albedoの項目から色を設定できる。

この色を設定したMaterialを色を変えたいオブジェクトにドラッグ&ドロップすることで、オブジェクトの色を変えることができる。

色以外にもMaterialで色々設定できる。

 

コンポーネント

オブジェクトに様々な機能や属性を持たせることができる。

コンポーネントの追加は対象のオブジェクトのInspectorビューから、「Add Comonet」をクリックすることでできる。

物理演算を適用したいとき

 「Phiysics」→「Rigrtbody」

スクリプトを適用したい

 「New Script」→ スクリプト名の入力とC#かJSかを選択

 

タグ

オブジェクト一つひとつに設定できる。

スクリプトなどで、特定のタグにだけある動作や反応をさせたいときなどに利用できる。

もともといくつか用意されているが、自分で新規に追加したい場合は以下の操作で行う。

  1. メニューバー→Edit→ProjectSettings→Tags And Layers。
  2. InspectorビューでTagsメニュー。
  3. +を押して、New Tagに追加したいタグの名前を入力する。

 

太陽光の輝度を操作したい

HierarchyビューのDirectionalLightを選択し、InspectorビューでLightコンポーネントのIntesityを操作する。

 

UIの作成

UIを表示するCanvasを用意する。

 HierarchyビューのUI→Canvas

テキストを表示したい場合はUI→textを選択。

 

Canvasの大きさの設定はCanvas Scale Modeから行う。

Constant Pixel Sizeモード

 UIの大きさをピクセルに対する単純な倍率で指定する。

 Scale Factorで画面の倍率を指定する。

Scale With Screen Sizeモード

 画面のサイズによってUIの位置や大きさが変わる。