转自Unity圣典:Unity中让射线发生折射的方法

这文章本身就是国外人写的 Unity圣典的朋友翻译来的(特此注明)

首先,我们新建一个场景,新建一个Cube来充当射线发射源,将这个Cube起名为“Ray Emitter”。




  因为射线是看不见的,所以我们还需要给这个添加一个LineRenderer组件来表示射线。点击Component->Miscellaneous->Line Renderer。 

 
   然后我们给LineRenderer组件赋上一个材质,并设置它的 StartWidth EndWidth 两个属性为0.1,并确定它的 Use World Space 属性是勾上的。 
    接下来我们创建一些大小不同的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);
     
                }
     
            }
     
        }
     
    }
     
}

效果图:

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值