概要
反射するレーザーを作れる関数を作りました。
実装は、Ray を打って RayCastHit から次の Ray の座標と方向を決める処理を繰り返す方法を取っています。
太いレーザーを作れるように SphereCast 版の関数も用意しています。
2D版の関数も用意しています。
使い方
LineRenderer で使用する際は useWorldSpace を有効にしてください。
LineRenderer で使う場合のサンプルコード(抜粋).cs
void Update()
{
var poses = PhysicsUtil.RefrectionLinePoses(transform.position, transform.forward, 50f, 1).ToArray();
lineRenderer.positionCount = poses.Length;
lineRenderer.SetPositions(poses);
}
コード
下記コードの関数をお手持ちの Utility クラスに追加してご利用ください。
PhysicsUtil.cs
using System.Collections.Generic;
using UnityEngine;
namespace Utility
{
public class PhysicsUtil
{
public static List<Vector3> RefrectionLinePoses(Vector3 position, Vector3 direction, float length, LayerMask layerMask)
{
var points = new List<Vector3>() { position };
while (Physics.Raycast(position, direction, out var hit, length, layerMask))
{
position = hit.point;
points.Add(position);
length -= hit.distance;
direction = Vector3.Reflect(direction, hit.normal);
}
points.Add(position + direction * length);
return points;
}
public static List<Vector3> RefrectionLinePoses(Vector3 position, float radius, Vector3 direction, float length, LayerMask layerMask)
{
var points = new List<Vector3>() { position };
while (Physics.SphereCast(position, radius, direction, out var hit, length, layerMask))
{
position = hit.point + hit.normal * radius;
points.Add(position);
length -= hit.distance;
direction = Vector3.Reflect(direction, hit.normal);
}
points.Add(position + direction * length);
return points;
}
}
}
Physics2DUtil.cs
using System.Collections.Generic;
using UnityEngine;
namespace Utility
{
public class Physics2DUtil
{
public static List<Vector2> RefrectionLinePoses(Vector2 position, Vector2 direction, float length, LayerMask layerMask)
{
var points = new List<Vector2>() { position };
var hit = Physics2D.Raycast(position, direction, length, layerMask);
while (hit)
{
position = hit.point;
points.Add(position);
length -= hit.distance;
direction = Vector2.Reflect(direction, hit.normal);
hit = Physics2D.Raycast(position, direction, length, layerMask);
}
points.Add(position + direction * length);
return points;
}
public static List<Vector2> RefrectionLinePoses(Vector2 position, float radius, Vector2 direction, float length, LayerMask layerMask)
{
var points = new List<Vector2>() { position };
var hit = Physics2D.CircleCast(position, radius, direction, length, layerMask);
while (hit)
{
position = hit.point + hit.normal * radius;
points.Add(position);
length -= hit.distance;
direction = Vector2.Reflect(direction, hit.normal);
hit = Physics2D.CircleCast(position, radius, direction, length, layerMask);
}
points.Add(position + direction * length);
return points;
}
}
}