視界に入ったキャラクターを感知する(障害物で隠れられる)
<動作概要>
一定のエリア内に入ったキャラクターを感知する。ShereColliderとRayCastを使う。ShereColliderで視界の範囲(現実的ではないが360°)を設定。障害物の感知はRayCastで実現する。
今回Cubeを敵と見立てた。球状の緑線が索敵範囲。Unityちゃんを見つけると近づいてくる。Unityちゃんの前に障害物がある場合見失うようにした。
<動作環境>
Unity 2019.3.9f1
<ソースコード>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Search : MonoBehaviour
{
//------------------------------public変数の宣言---------------------------------------
//移動速度
public float moveSpeed;
//------------------------------private変数の宣言--------------------------------------
CharacterController controller;
//追跡対象の方向
Vector3 targetDirection;
void Start()
{
//private変数の初期化
controller = GetComponent<CharacterController>();
targetDirection = Vector3.zero;
}
void Update()
{
}
void OnTriggerStay(Collider other)
{
if (other.gameObject.layer == LayerConst.PLAYER){
targetDirection = (other.transform.position - transform.position).normalized;
Debug.DrawRay(transform.position, targetDirection * 10.0f, Color.red);
RaycastHit hit;
Physics.Raycast(transform.position, targetDirection, out hit);
if(hit.transform.position == other.transform.position)
{
controller.Move(targetDirection * moveSpeed * Time.deltaTime);
}
}
}
void OnTriggerExit(Collider other)
{
targetDirection = Vector3.zero;
}
}
public static class LayerConst
{
public static int PLAYER = 8;
}
<ソースコード解説>
①Colliderのイベント関数”OnTriggerStay(Collider)”について
Colliderはオブジェクト同士の衝突を検知するのに利用するが、InspectorでColliderのIsTriggerにチェックを入れるとCollider同士の衝突が発生しなくなる(すり抜ける)。イベント関数OnTriggerStayはColliderが重なっている間実行される関数である。今回、敵の視界を表すSphereColliderのIsTriggerにチェックを入れた。

② “OnTriggerStay(Collider)” の引数でキャラとの接触を検知する。
イベント関数”OnTriggerStay(Collider)”の引数には、接触しているColliderの情報が自動的に格納される。
今回UnityちゃんのレイヤーをLayerConst.PLAYER に設定したので、もし接触したオブジェクトがUnityちゃんだったら以下のif文がtrueを返す。(レイヤーの設定に関しては別記事参照)
if (other.gameObject.layer == LayerConst.PLAYER)
③RayCastで視界を遮る障害物がないか確認する
RayCastはオブジェクトから光線を発する関数。光線がオブジェクトにあたれば、そこで光線は止まる。以下のようにすると、光線と衝突したオブジェクトの情報が引数hitに自動的に格納される。(hitの前のoutはC#特有の文法)
RaycastHit hit;
Physics.Raycast(transform.position, targetDirection, out hit);
この引数hitのpositionと②で検知したUnityちゃんのpositionが一致する場合、索敵成功となる。もしUnityちゃんの前に障害物があったら、引数hitには障害物の情報が格納されるので、索敵失敗となる。