这文章本身就是国外人写的 Unity圣典的朋友翻译来的(特此注明)
首先,我们新建一个场景,新建一个Cube来充当射线发射源,将这个Cube起名为“Ray Emitter”。
因为射线是看不见的,所以我们还需要给这个添加一个LineRenderer组件来表示射线。点击Component->Miscellaneous->Line Renderer。
接下来我们创建一些大小不同的Cube来当做墙,把这些墙离你的 Ray Emitter 近一些,确保射线可以打到其中的一面墙上。然后旋转某些墙,使折射后的射线也能打到这些墙上。
然后,让我们书写如下代码,并把它贴到
Ray Emitter物体上。
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(LineRenderer))]
public class RaycastReflection : MonoBehaviour
{
//本物体的Transform
private Transform goTransform;
//添加的line renderer组件
private LineRenderer lineRenderer;
//一条射线
private Ray ray;
//一个RaycastHit类型的变量, 可以得到射线碰撞点的信息
private RaycastHit hit;
//折射的方向
private Vector3 inDirection;
//折射次数
public int nReflections = 2;
//line renderer组件上点的数量
private int nPoints;
void Awake()
{
//初始化组件
goTransform = this.GetComponent<Transform>();
lineRenderer = this.GetComponent<LineRenderer>();
}
void Update()
{
//在当前物体的正前方发射一条射线
ray = new Ray(goTransform.position, goTransform.forward);
//只有在编辑器的Scene窗口才会看到的射线,用于调试
Debug.DrawRay(goTransform.position, goTransform.forward * 100, Color.magenta);
//将lineRenderer的点数设置成和折射次数相等
nPoints = nReflections;
//使lineRenderer有nPoints个点
lineRenderer.SetVertexCount(nPoints);
//将lineRenderer的第一个点设置为当前物体的位置
lineRenderer.SetPosition(0, goTransform.position);
for (int i = 0; i <= nReflections; i++)
{
//当射线还没有折射的时候
if (i == 0)
{
//检查射线是否碰到了墙壁
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100))//发射一条100个单位长的射线
{
//折射方向就是当前碰撞点的反射角
inDirection = Vector3.Reflect(hit.point, hit.normal);
//新建一条射线, 用刚才的碰撞点当做新射线的初始点,用折射方向当做他的发射方向
ray = new Ray(hit.point, inDirection);
//调试用信息,绘制法线、射线
Debug.DrawRay(hit.point, hit.normal * 3, Color.blue);
Debug.DrawRay(hit.point, inDirection * 100, Color.magenta);
//打印被射线击中物体的名称
Debug.Log("Object name: " + hit.transform.name);
//如果折射次数为1
if (nReflections == 1)
{
//给lineRenderer上新加一个点
lineRenderer.SetVertexCount(++nPoints);
}
//将lineRenderer的下一个点的位置设置为击中点的位置
lineRenderer.SetPosition(i + 1, hit.point);
}
}
else // 如果射线已经折射过至少一次
{
//检查射线是否碰到了墙壁
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100))//发射一条100个单位长的射线
{
//折射方向就是当前碰撞点的反射角
inDirection = Vector3.Reflect(inDirection, hit.normal);
//新建一条射线, 用刚才的碰撞点当做新射线的初始点,用折射方向当做他的发射方向
ray = new Ray(hit.point, inDirection);
//调试用信息,绘制法线、射线
Debug.DrawRay(hit.point, hit.normal * 3, Color.blue);
Debug.DrawRay(hit.point, inDirection * 100, Color.magenta);
Debug.Log("Object name: " + hit.transform.name);
//给lineRenderer上新加一个点
lineRenderer.SetVertexCount(++nPoints);
//将lineRenderer的下一个点的位置设置为击中点的位置
lineRenderer.SetPosition(i + 1, hit.point);
}
}
}
}
}
效果图: