まゆたまガジェット開発逆引き辞典

電子工作やプログラミングのHowtoを逆引き形式で掲載しています。作りたいモノを決めて学んでいくスタイル。プログラマではないので、コードの汚さはお許しを。参照していないものに関しては、コピペ改変まったく問いません

UnityのMecanim Locomotion Starter Kit+Character Controller+Box Colliderで衝突判定

Character Controllerは衝突判定を備えており、キャラクターのコントロールを簡単にするものです。
が、衝突判定との相性が良くないのか苦労されている方が多いようです。
ここでは下記の条件で衝突判定を行い、「衝突したら音が鳴る」「特定のエリアに入ったらシーン移動(ワープ)する」例を作ってみました。
Box Colliderの「Is Trigger」にチェックを入れるとキャラクターがオブジェクトをすり抜けるので、「この範囲に来たらワープする」などに使用できます。

今回はMecanim Locomotion Starter Kit+Character Controllerを使用しているため、障害物の前で止まる=障害物に接触しない=他の当たり判定が発動しないことになります。
(Character Controller自身で当たり判定のアクションを動作させることもできますが、あまり上手くいかなった)
なので、障害物より少し大きめの当たり判定エリアを作り、そのエリアに接したら(衝突したら)アクションが開始するようにします。

また障害物がキャラクターの身長より小さいと乗り越えて進んでしまうため、そこも注意が必要です。


●3Dキャラクター
・Mecanim Locomotion Starter Kitを使用
・Character Controllerを使用
・Rigidbodyを使用(ジャンプのアニメーションをさせたりしてたので)

最終的な状態:
f:id:prince9:20180729184243p:plain


●衝突するオブジェクト
・すり抜けをさせたくなかったので、衝突用のオブジェクトと衝突エリア用のオブジェクトをそれぞれ用意
・Box Colliderでキャラクターのすり抜けができなくなる(停止する)

最終的な状態:
f:id:prince9:20180729184451p:plain


●音が鳴る用の衝突エリア用のオブジェクト(いわゆる当たり判定エリア)
・Box Colliderの「Is Trigger」にチェックを入れる

最終的な状態:
f:id:prince9:20180729184358p:plain


●ワープ用の当たり判定エリア用のオブジェクト
・Box Colliderの「Is Trigger」にチェックを入れる

最終的な状態:
f:id:prince9:20180729184559p:plain



ではまず、「衝突したら音が鳴る」から。
すでに
・「Mecanim Locomotion Starter Kit」を使って矢印キーでキャラクターが操作できている
・Character Controllerを設定済み

な状態からスタートします(プログラミングの必要なし)。

■障害物を設置する
1.「GameObject」→「3D Object」→「Cube」を選択して立方体を出す
※キャラクターの身長より大きいサイズであること。でないと乗り越えてしまう
2.Hierarchy」→「Cube」をクリックし、「Inspector」の「Cube」を「Block」などにして名前を変える。必要であれば移動させておく
3.「Hierarchy」→「Block」をクリックし、「Inspector」→「Add Component」をクリックする


■Box Colliderを設定する
4.虫眼鏡アイコンのところに「Box Collider」と入力し、「Box Collider」をクリックする
5.衝突して止まるかの確認のため、Unityの再生ボタンを押して動作させる
※「Character Controller」を設定していないか、「Box Collider」の「Is Trigger」のチェックがONだとすり抜けてしまう


■当たり判定エリアを設定する
今回はCharacter Controllerを使用しているため、障害物の前で止まる=障害物に接触しない=他の当たり判定が発動しないことになります。
なので、障害物より少し大きめの当たり判定エリアを作り、そのエリアに接したら(衝突したら)アクションが開始するようにします。

6.「GameObject」→「3D Object」→「Cube」を選択して立方体を出す
7.「Hierarchy」→「Cube」をクリックし、「Inspector」の「Cube」を「JudgeArea」などにして名前を変える。1.で作った障害物と同じ位置に移動させる(Transformの数値を設定するなどで)
8.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Mesh Renderer」の右にある歯車のアイコンをクリックする
9.「Remove Component」を選択する。オブジェクトが非表示になり、枠線が表示される
10.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Transform」の「Scale」をXYZともに「1.5」程度に若干拡大する


■当たり判定エリア用のBox Colliderを設定する
11.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Add Component」をクリックする
12.虫眼鏡アイコンのところに「Box Collider」と入力し、「Box Collider」をクリックする
13.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Box Collider」の「Is Trigger」にチェックを入れる
※こうすることで「OnTriggerEnter」関数が呼び出され、「衝突したらアクションを起こす」という処理をさせることができる
※「Box Collider」の「Is Trigger」にチェックを入れると、そのオブジェクトをすり抜けることができる。そのためオブジェクトに衝突する前にキャラクターが止まらないので、衝突判定を設定することができる


■音を出す準備をする その1
14.「Hierarchy」→「JudgeArea」をクリックし、「Add Component」をクリックする
15.虫眼鏡アイコンのところに「AudioSource」と入力し、「AudioSource」をクリックする
16.「Asset」を右クリックし、「Import New Asset」をクリックして音源ファイルを選択する
17.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Audio Source」→「AudioClip」に音源ファイルをドラッグ&ドロップする


■衝突判定
18.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Add Component」をクリックする
19.「New Script」を選択し、名前を「AreaSctipt」として「Create and Add」を押す
20.「Asset」→「AreaSctipt」をダブルクリックして、下記のコードを書く

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class AreaSctipt : MonoBehaviour {

//音を出す準備
public AudioClip crashSound;

private AudioSource audioSource;

	void Start () {
//音を出す準備
audioSource = gameObject.GetComponent<AudioSource> ();
	}

//衝突したときの処理
void OnTriggerEnter(Collider col)
{

//実際の処理を書く(ここでは「crashSound」に設定した音源が鳴る)
audioSource.PlayOneShot (crashSound);
   }

}

■音を出す準備をする その2
21.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Area Script」の「Crash Sound」に「Assets」の中にある音源ファイルをドラッグ&ドロップする
22.「Hierarchy」→「JudgeArea」をクリックし、「Inspector」→「Audio Source」→「Play On Awake」のチェックを外す
23.Unityの再生ボタンを押して、ちゃんと衝突したときに音が鳴るか確認する


これでキーボードでキャラクターを動かして、かつ障害物に衝突すると音が鳴ります。鳴らない場合のいちばんの原因として、当たり判定のオブジェクトのサイズが小さすぎることがあります。Scaleの値を調整して、少し大きくしてあげましょう。


次は「この範囲に来たらワープ(シーン移動)する」です。
・「Mecanim Locomotion Starter Kit」を使って矢印キーでキャラクターが操作できている
・Character Controllerを設定済み

な状態からスタートします。
ワープした後、次のシーンでもキャラクターがいるようにしてあげます。
単純に同じシーンの他の位置へワープしたい場合は、キャラクターにスクリプトとタグ(これは後でやります)を設定し、下記のようにすればOKです。

void Update () {
//「WarpSctipt」というスクリプトに書いたフラグがOnのとき
if (WarpSctipt.flag == true) {
//このオブジェクトを原点に移動させる
this.gameObject.transform.position = new Vector3(0,0,0);
//「WarpSctipt」のフラグをOffにしておく(でないとワープした後動けない)
Warpctipt.flag = false;
}
}


■ワープエリアを設定する
ここでは壁にしました。

1.「GameObject」→「3D Object」→「Plane」を選択して平面を出す
2.「Hierarchy」→「Plane」をクリックし、「Inspector」の「Plane」を「NextStage」などにして名前を変える。必要であれば位置・大きさ・角度を調整する
※このとき壁の大きさはキャラクターの身長より高くする
3.「Hierarchy」→「NextStage」をクリックし、「Inspector」→「Mesh Renderer」の右にある歯車のアイコンをクリックする
4.「Remove Component」を選択する。オブジェクトが非表示になり、枠線が表示される


■ワープエリア用のBox Colliderを設定する
5.「Hierarchy」→「NextStage」をクリックし、「Inspector」→「Add Component」をクリックする
6.虫眼鏡アイコンのところに「Box Collider」と入力し、「Box Collider」をクリックする
7.「Hierarchy」→「NextStage」をクリックし、「Inspector」→「Box Collider」の「Is Trigger」にチェックを入れる
※ワープ用の壁はすり抜けてかまわないので、「Box Collider」の「Is Trigger」にチェックを入れる。すり抜けて欲しくない場合は「衝突したら音が鳴る」の1.-13.まで同じ


■キャラクターにタグをつける
オブジェクトが複数になってくると判別しにくくなるので、タグをつける。ここでは操作キャラクターに「Player」というタグをつける

8.「Hierarchy」→「3Dキャラクターのファイル名」をクリックし、「Inspector」→「Tag」の「Untagged」をクリックする
9.「Untagged」を「Player」に変える


■衝突(エリアに入ったか否か)判定
10.「Hierarchy」→「NextStage」をクリックし、「Inspector」→「Add Component」をクリックする
11.「New Script」を選択し、名前を「NextStageSctipt」として「Create and Add」を押す
12.「Asset」→「NextStageSctipt」をダブルクリックする
13.下記のコードを書く

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class NextStageSctipt : MonoBehaviour {
//フラグのOn/Offをbool(true/false)で管理する宣言
public static  bool flag;

	void Start () {
//最初のフラグはオフにしておく
flag = false;
	}

//キャラクターがエリアに入ったら
void OnTriggerEnter(Collider secondswarp)
{

//Playerというタグを持つオブジェクトがエリアに入ったら
if(secondswarp.tag=="Player")
    {

//フラグをOnにする
flag = true;
    }
}


■新しいシーン(次のステージ)をつくる
14.「Assets」→「Scenes」を右クリックし、「Create」→「Scene」を選択して新しいシーン(ステージ)を用意する
15.「New Scene」をクリックし、「2ndScene」に名前を変える
16.「Assets」→「Scenes」→「Sample Scene」をクリックし、「1ndScene」に名前を変える
17.「Assets」→「Scenes」→「2ndScene」のアイコン部分をダブルクリックし、新しいシーンの編集をする
18.「GameObject」→「3D Object」→「Plane」を選択して地面を出す
19.「Hierarchy」→「Plane」をクリックし、「Inspector」の「Plane」という名前を「2ndGround」に変える。必要があればマテリアルも設定する
20.新しいシーンにオブジェクトを配置する


■シーン移動のコードを書く
21.「Hierarchy」→「3Dキャラクターのファイル名」をクリックし、「Inspector」→「Add Component」をクリックする
11.「New Script」を選択し、名前を「WarpPlayer」として「Create and Add」を押す
12.「Asset」→「WarpPlayer」をダブルクリックする
13.下記のコードを書く

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

//ステージ移動できるようにする
using UnityEngine.SceneManagement;

public class WarpPlayer : MonoBehaviour {
	void Update () {

//「NextStageSctipt」で設定したフラグがOn(true)になったら
if (NextStageSctipt.flag == true) {

//「2ndScene」というシーンに移動
SceneManager.LoadScene ("2ndScene");

//「NextStageSctipt」で設定したフラグをOff(false)にしておく(これをしないとステージ移動後に動けなくなる)
NextStageSctipt.flag = false;
}
}

//次のシーンでもキャラクターが存在して動くための設定
void Awake () {
	DontDestroyOnLoad(this.gameObject);
}

}


■シーン移動の設定をする
このままではまだシーンの移動ができない。下記の設定も必要となる
14.「Assets」→「Scenes」→「1ndScene」のアイコン部分をダブルクリックして、「1ndScene」が表示された状態にする
15.Assets」→「Scenes」→「2ndScene」をクリックする
16.「File」メニュー→「Build Settings」を選択する
17.「Add Open Scenes」をクリックする
下記のように「2ndScene」が追加されていればOK。
f:id:prince9:20180729194113p:plain


■照明の設定をする
Unityではシーンの移動をすると全体が暗くなってしまう。その対処法として下記のようにする。
Unity2018版の方法です。

18.「Assets」→「Scenes」→「1ndScene」のアイコン部分をダブルクリックして、「1ndScene」が表示された状態にする
19.「Window」メニュー→「Lighting」→「Settings」を選択し、「Object Maps」タグをクリックする
20.「Auto Generate」のチェックを外す
21.「Generate Lighting」をクリックする
22.「Assets」→「Scenes」→「2ndScene」のアイコン部分をダブルクリックして、「2ndScene」が表示された状態にする
23.「Window」メニュー→「Lighting」→「Settings」を選択し、「Object Maps」タグをクリックする
24.「Auto Generate」のチェックを外す
25.「Generate Lighting」をクリックする

これで再生ボタンを押せば動きます。
f:id:prince9:20180729195213g:plain