//tips
//攻撃スクリプトの内容確認
前回の続き、ターゲットをEthanにした攻撃スクリプトの内容を確認する。
ターゲットへのレイ照射時にパーティクルを発生させ、カウントダウンのタイマーの設定値まで照射し続けることで、攻撃成功。
Startメソッドではscoreを0に設定し、countDownタイマーに開始値を代入、hitEffectをoffにする。
Updateメソッドではカメラからレイを飛ばしてEthanと衝突したかを調べ、その際にタイマーの数値を参照する。
レイをタイマーが0になるまで、当て続けることができたら、攻撃成功で、消滅エフェクトを発生させ、新たなターゲットをリスポーンさせる。タイマーもリセットされる。
パーティクルシステムはこの時点では作られていないため、新たに作成する必要がある。メインメニューからgameobject/effects/partcle systemで追加する。
追加particleをGameControllerのインスペクターHitEffectにセット。standard assetsのprefabsにあるexplosionをKillEffectにセットする。
パーティクルは初期設定のままなので好みの形に変更していく。
Start size:0.15
Start lifetime:0.3
Max particle:50
Shape:sphere
Raise:0.01
Rayがうまく照射できていないようでエフェクトが発生しない。
一旦、cameraとrayの接続の問題、particleのエフェクト起動の問題の二つに分けて考えていくことにする。
まずは、Rayの照射を見直していく。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rayex : MonoBehaviour
{
void Update()
{
//カメラ上で画面をタップした場所の位置情報と方向をrayに格納
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
//Rayが当たったオブジェクトの名前と位置情報をログに表示する
Debug.Log(hit.collider.gameObject.name);
Debug.Log(hit.collider.gameObject.transform.position);
}
}
}
マウスの座標はInput.mousePositionで取得でき、Camera.ScreenPointToRayで、スクリーンの点に向けてカメラからレイを通す。
raycastの主な使用方法は2パターンあり、
Rayの発射位置と方向を指定するもの
//Physics.Raycast(発射位置、Rayの方向、衝突したオブジェクト情報、Rayの長さ)
Physics.Raycast(origin, direction, out hit, Mathf.Infinity);
と、
直接Rayクラスを持った変数を設定するもの
//メインカメラ上のマウスポインタのある位置からrayを飛ばす
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
Physics.Raycast(ray, out hit, Mathf.Infinity);
があり、今回は後者を採用している。
Physics.Raycastは下記の要素をとることができ、origin(rayの開始地点)とdirection(rayの向き)のみ必須の情報となっている。後者のCamera.main.ScreenPointToRayには向きの情報も含まれているので、追加で向きを指定する必要がなくなっている。
Physics.Raycast(Vector3 origin(rayの開始地点), Vector3 direction(rayの向き),RaycastHit hitInfo(当たったオブジェクトの情報を格納), float distance(rayの発射距離), int layerMask(レイヤマスクの設定));
他の要素を記入しなかった場合、distance(rayの発射距離)は永遠に続き、layerMask(レイヤマスクの設定)は初期設定のレイヤ、発射されたrayとコライダがぶつかったらtrue、それ以外はfalseが返される。
次に、このスクリプトのレイを可視化していく。Debug.DrawRayではシーンビューでしかみることができないので両画面表示して確認する。
レイの表示ができたので、Camera.main.ScreenPointToRayの手法を持ち込み一部スクリプトを改編し、実行したら無事に動作できた。
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;
void Start()
{
score = 0;
countDown = timeToselect;
hitEffectEmission = hitEffect.emission;
hitEffectEmission.enabled = false;
}
void Update()
{
//Transform camera = Camera.main.transform;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//Ray ray = new Ray(camera.position, camera.rotation * Vector3.forward);
float maxDistance = 10;
Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.green, 5, false);
RaycastHit hit;
if (Physics.Raycast(ray, out hit) && hit.collider.gameObject == target)
{
if (countDown > 0.0f)
{
countDown -= Time.deltaTime;
hitEffect.transform.position = hit.point;
hitEffectEmission.enabled = true;
Debug.Log(countDown);
}
else
{
Instantiate(killEffect, target.transform.position, target.transform.rotation);
score += 1;
countDown = timeToselect;
SetRandomPosition();
}
}
else
{
hitEffectEmission.enabled = false;
countDown = timeToselect;
}
}
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);
}
}
時々、爆発の負荷か、パーティクルとカウントダウンが止まってしまうのが残念。
爆発を生成するInstantiateは
Instantiate(original: Object, position: Vector3, rotation: Quaternion)
で表され、既存オブジェクトのクローンを下記引数を指定して生成できる。
第1引数(original):コピーしたい既存オブジェクト
第2引数(position):新規オブジェクトの位置
第3引数(rotation):新規オブジェクトの向き
Ethanへのレイ照射がなぜか認識されなくなる時があるので、アバターの問題なのかを確認するために、targetをcubeに変更すると、爆発エフェクト使用後のオブジェクトの残像が残り、ランダム移動後の実態は透明で表示されるというバグが発生した。
Particle周りは負荷がかかるので要注意。