Cz_mirror Game開発備忘録

週末にUnity でゲーム開発をしています。ゲーム開発を通じて得た情報の備忘録として活用するブログになります。

【RAYSER開発】LineRendererとRayでレーザーを表現してみました。

 

LineRendererによるレーザーの表現

RAYSERでは自動追尾レーザーを実現するために、LineRendererを使って表現しています。

gyazo.com

LineRendererで線を描画する際に、プレイヤーとターゲットの位置を元に描画しました。

マテリアルを適用することでレーザーの表現が可能になります。レーザーの描画はこちらの記事を参考にさせていただきました。

aki-tk.hateblo.jp

 

Rayによる当たり判定

当たり判定ではRayを用いてみました。Rayでターゲットへの位置を取得する際に以下の情報を参考にしました。

プレイヤーのposition - ターゲットのpositionとすることでターゲットへのベクトルを求めることができるので、そこからheading.magnitudeで距離を取得、ベクトルと距離を元にプレイヤーとターゲットの正規化されたベクトルを得ることができます。

docs.unity3d.com

 

Debug.DrawLineによるRayの確認

Rayを視覚的に確認する際にDebug.DrawLineを使うことで

Gizmoを設定しておくことで、Debug.DrawLineで描画されたRayを確認することができました。注意点として、ray.direction * distanceだけではあくまでベクトルのみのため、ray.originを足して、線の開始の座標を足す必要があります。

var target = ray.origin + ray.direction * distance;
Debug.DrawLine (ray.origin, target, Color.red, 5, true);

qiita.com

LineRendererのフェードアウト

コルーチンを用いて、LineRenderer.SetColorsにアルファ値を調整することでレーザーをフェードアウトしてみました。

public IEnumerator FadeOut () {
float a = 1.0f;
while (a > 0)
{
Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, a);

// SetColors(StartColot, EndColor)
// 線の先頭と末尾で同じ色を使用しているので同じ値を指定している
// 先端から徐々にフェードアウトしたい、みたいなケースは個別に指定が必要
lineRenderer.SetColors(color, color);
yield return new WaitForSeconds(0.03f);
a -= 0.1f;
}
// α値が0になったら線の描画自体をやめる
lineRenderer.enabled = false;
yield break;
}

こちらのフェードアウトについて、青木ととさんのブログ記事を参考にさせていただきました。

lycoris102.hatenablog.com

ソースコード

LineRendererとRayを用いたレーザーを表現したソースになります。

using System.Collections;
using System.Collections.Generic;
using RAYSER.Scripts;
using UnityEngine;

public class Laser : MonoBehaviour
{
public GameObject target;
public float timer = 1.0f;
public GameObject muzzleFlash;

private LineRenderer lineRenderer;
private GameObject player;

private Vector3 firstPosition;
private Vector3 targetPosition;


public void LaserShot(GameObject shotOwner)
{
player = shotOwner;

var laserTarget = GameObject.Find("Player/LaserTarget");
target = laserTarget.GetComponent<LaserTarget>().target;

positionSetting();
drewLaserLine();
raySetting();

StartCoroutine("FadeOut");
Destroy (gameObject, timer);
}

/*
* レーザーの座標設定
*/
void positionSetting()
{
// Target Setting
firstPosition = player.transform.position;
targetPosition = new Vector3(firstPosition.x, firstPosition.y, firstPosition.z);
if (!target)
{
target = GameObject.Find("Player/NoTarget");
targetPosition = target.transform.position;
}
else
{
targetPosition = target.transform.position;
}
}

/*
* レーザー描画
*/
void drewLaserLine()
{
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.enabled = true;
lineRenderer.SetVertexCount(2);

// Draw Laser
lineRenderer.SetPosition(0, firstPosition);
lineRenderer.SetPosition(1, targetPosition);

// MuzzleFlash sample
GameObject _muzzleFlash = Instantiate(muzzleFlash) as GameObject;
_muzzleFlash.transform.position = firstPosition;
_muzzleFlash.transform.LookAt(target.transform);
}

/*
* Ray設定
*/
void raySetting()
{
// Ray Setting
var heading = targetPosition - firstPosition; // Rayの目標座標
var distance = heading.magnitude; // Rayの飛ばせる距離
var direction = heading / distance; // Rayのベクトル
Ray ray = new Ray(firstPosition, direction * distance);

foreach (RaycastHit hit in Physics.RaycastAll(ray))
{
var damagetarget = hit.transform.GetComponent<IDamagable>();
if (damagetarget != null)
{
float damage = 1.0f;
hit.transform.GetComponent<IDamagable>().AddDamage(damage);
}
}

// rayの方向ベクトルにhit迄の距離をかけ合わせて方向ベクトルを作り、発射地点の座標を足して初めてターゲットの座標が算出できる
var target = ray.origin + ray.direction * distance;
Debug.DrawLine (ray.origin, target, Color.red, 5, true);


}

/*
* レーザーフェードアウト処理
*/
public IEnumerator FadeOut () {
float a = 1.0f;
while (a > 0)
{
Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, a);

// SetColors(StartColot, EndColor)
// 線の先頭と末尾で同じ色を使用しているので同じ値を指定している
// 先端から徐々にフェードアウトしたい、みたいなケースは個別に指定が必要
lineRenderer.SetColors(color, color);
yield return new WaitForSeconds(0.03f);
a -= 0.1f;
}
// α値が0になったら線の描画自体をやめる
lineRenderer.enabled = false;
yield break;
}
}