こんにちは (‘ω’)ノかずまなぶ です。
わたしのVR空間にだんだんと人が集まってきました。紹介します。

アイドルのおっかけ

- 先日紹介しました、アイドルのおっかけです。ユニティちゃんはロコモーションなのでPCのキーボードで自由に動けるのですが、それをずっと追っかけていきます。
- おっかけはAIThirdPersonControllerプレハブでAICharacterControlスクリプトのTargetをWalkTargetに設定しています。
- walkTargetはEmptyの名前を変えただけのオブジェクトです。追跡対象であるユニティちゃんの子オブジェクトにいれています。
- 言い換えれば、おっかけはユニティちゃんではなく、ユニティちゃんの保有するWalkTargetオブジェクトに反応しているのです。
- 星白しずかのエナがいつもカビザシを見つめているような感じです。ランカ・リーのVウィルスだったり、バサラのアニマスピリチアだったりもします。解らなかったらスルーしてください。
石盤のおっかけ

- アイドルのおっかけを改良して、追跡対象をユニティーちゃんから、地面を這う石盤に変更した「石盤のおっかけ」です。
- ユニティちゃんのときは追跡対象のユニティちゃんの中にTargetを入れていましたので、今回は石盤(cylinderオブジェクト)にTargetを入れていると普通は思いますが、違います。
- AIThirdPersonControllerプレハブのAICharacterContorolスクリプトのTargetをWalkTarget_lookMoveToオブジェクトにし、LookMoveToスクリプトを適用しています。
- LookMoveToスクリプトでは、カメラ目線の始点座標とベクトルを調べ、そのベクトルの延長上に何かしらのオブジェクトがあり、それが地面(変数ground)だったら、その座標にWalkTarget_lookMoveToオブジェクトを移動させるのです。変数GroundにはInspectorパネルからGroundPlaneを適用します
- そして、目線によって任意に動かすことができるようになったWalkTarget_lookMoveToオブジェクトに対してはcylinderオブジェクトという実体を与えて(子にして)、目で見ることができるようにしました。
- ゲームを実行してみると、目線の先に常に石盤がいるかと思います。
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class LookMoveTo : MonoBehaviour | |
{ | |
public GameObject ground;//ゲームオブジェクト型の変数groundを定義 | |
// Use this for initialization | |
void Start() { } | |
// Update is called once per frame | |
void Update() | |
{ | |
Transform camera = Camera.main.transform;//アクティブなカメラの座標を得る。 | |
//MainCameraというタグを探しに行くのでInstectorでタグの設定をすること | |
Ray ray;//レイとして表現(始点とベクトル)。変数名ray と定義する | |
RaycastHit[] hits;//追加 | |
GameObject hitObject; | |
Debug.DrawRay(camera.position, camera.rotation * Vector3.forward * 100.0f);//レイが描かれるはずだが、見えない? | |
ray = new Ray(camera.position, camera.rotation * Vector3.forward);//カメラの座標, 3軸回転角度*単位ベクトル。見ている方向Rayを定義 | |
hits=Physics.RaycastAll(ray);//追加 | |
for (int i = 0; i < hits.Length; i++)//追加 | |
{ | |
RaycastHit hit = hits[i];//追加 | |
hitObject = hit.collider.gameObject; //hit.colider.gameObjectにそのオブジェクトが入る | |
if (hitObject == ground)//もし、顔をさげてRayが衝突したオブジェクトhitObjectがgroundだったら実行する。 | |
//途中にground以外のオブジェクトがあったら条件を満たさない。 | |
{ | |
Debug.Log("Hit(x,y,z): " + hit.point.ToString("F2"));//デバックログ。衝突した座標hit.pointをコンソールに表示 | |
//ToString:ベクトルを文字列として出力 | |
transform.position = hit.point;//衝突した座標を 移動目標の座標とする | |
} | |
} | |
} | |
} |
うろちょろゾンビ

- ランダムに出現する見えないターゲットに向かってひたすら歩き続けます。ターゲットは5秒間隔で移動します。
- AIThirdPersonControllerプレハブのAICharacter ControlのTargetにWalkTarget_Randomオブジェクトを適用する。
- WalkTarget_RandomオブジェクトはRandomPositionスクリプトを持ちます。
- RandomPositionスクリプトがWalkTarget_Randomオブジェクトの座標を移動させます。
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class RandomPosition : MonoBehaviour { | |
// Use this for initialization | |
void Start () { | |
StartCoroutine(RePositionWithDelay()); | |
} | |
IEnumerator RePositionWithDelay() | |
{ | |
while (true) | |
{ | |
SetRandomPosition(); | |
yield return new WaitForSeconds(5); | |
} | |
} | |
void SetRandomPosition() | |
{ | |
float x = Random.Range(-5.0f, 5.0f); | |
float z = Random.Range(-5.0f, 5.0f); | |
Debug.Log("X,Z: " + x.ToString("F2") + "," + x.ToString("F2")); | |
transform.position = new Vector3(x, 0.0f, z); | |
} | |
// Update is called once per frame | |
void Update () { | |
} | |
} |
バイツァーダストの被害者

- 目線を合わせると、赤いパーティクルが体を包み3秒後に爆死!します。
- 何回でもリスポーンしますので、タイミングよくバイツァーダスト!と叫びましょう。要練習です。
- AIThirdPersonControllerプレハブのThirdPersonCharacterスクリプトには何もいれません。こいつは特になにかの目標に向かって移動する知能は与えていません。爆死能力だけです。AudioSourceに爆発音だけ入れましたが、機能していません。(課題です)
- EmptyからGameControllerを作ります。killTargetスクリプトとAudioSource爆発音をコンポーネントとして追加しました。AIThirdPersonControllerプレハブの中にGameControllerを入れておきましょう。
- killTargetスクリプトにはTarget , Hit Effect , Kill Effect , Time To Select , Score、といったいろいろなものをセッティングできるようにしました。
- killTargetスクリプトでは、カメラ目線をレイとし、レイが変数targetに当たっていたら、当たっている座標にEffiectを出し、設定時間経過後にkillEffectを出し、そのあとに新しい座標にリスポーンします。

using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class killTarget : MonoBehaviour { | |
public GameObject target; | |
public ParticleSystem hitEffect; | |
public GameObject killEffect; | |
public float timeToSelect = 3.0f; | |
public int score; | |
private ParticleSystem.EmissionModule hitEffectEmission; | |
private float countDown; | |
// Use this for initialization | |
void Start () { | |
score = 0; | |
countDown = timeToSelect; | |
hitEffectEmission = hitEffect.emission; | |
hitEffectEmission.enabled = false; | |
} | |
// Update is called once per frame | |
void Update() { | |
Transform camera = Camera.main.transform; | |
Ray ray = new Ray(camera.position, camera.rotation * Vector3.forward); | |
RaycastHit hit; | |
if(Physics.Raycast(ray,out hit) && (hit.collider.gameObject == target)) | |
{ | |
if (countDown > 0.0){ | |
//レイがターゲットに当たった時の処理 | |
countDown -= Time.deltaTime; | |
hitEffect.transform.position = hit.point; | |
hitEffectEmission.enabled = true; | |
}else{ | |
//殺された時の処理 | |
GetComponent<AudioSource>().Play();//Playメソド | |
Instantiate(killEffect, target.transform.position, target.transform.rotation); | |
score += 1; | |
countDown = timeToSelect; | |
SetRandomPosition();//新規関数を作成(後述) | |
} | |
} | |
else { | |
//リセットする | |
countDown = timeToSelect; | |
hitEffectEmission.enabled = false; | |
} | |
} | |
void SetRandomPosition() | |
{ | |
float x = Random.Range(-5.0f, 5.0f); | |
float z = Random.Range(-5.0f, 5.0f); | |
target.transform.position = new Vector3(x, 0.0f, z); | |
} | |
} |