Unity基础射线判定以及编辑自定义模型

Unity基础射线判定以及编辑自定义模型


代码很简单没有难度,自己看一下应该就能明白。

OK 老规矩,直接上代码:

Unity射线基础解析

		//	  射线图层遮罩:
        //    LayerMask参数基础设置
        //	  1 << 8 打开第8的层。
        //	  ~(1 << 8) 打开除了第8之外的层。
        //	  ~(1 << 0) 打开所有的层。
        //	  (1 << 10) | (1 << 8) 打开第10和第8的层。
        //	  也可以直接使用 LayerMask 结构体里的静态方法GetMask(),把LayerName传进去就自动转int类型图层掩码。
        //	  比位操作符更加简单和好理解。
        //	  LayerMask.NameToLayer("字符串");    对象中的内置层或用户层定义的层索引  返回 Int 类型
        //    LayerMask.LayerToName(10);    对象中的内置层或用户层定义的层索引  返回 String 类型
        //	  下面代码中都有应用根据个人需求来使用。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 射线基础解析
/// </summary>
public class Ray_ZH : MonoBehaviour
{
    private void Update()
    {
        RayCmaera();
    }
    /// <summary>
    /// Camera 射线 基本操作
    /// </summary>
    public void RayCmaera()
    {
        //点击鼠标左键
        if (Input.GetMouseButtonDown(0))
        {
            //屏幕坐标转换 世界空间位置
            Ray _RayCamera = Camera.main.ScreenPointToRay(Input.mousePosition);
            //射线结构体 对象 包含各种信息
            RaycastHit _CameraHit;
            //射线布尔 判断
            //参数 射线  返回结构体  最大距离  忽略层
            if (Physics.Raycast(_RayCamera, out _CameraHit,1000, ~LayerMask.GetMask("Target")))
            {
                print("鼠标点击的位置是: " + _CameraHit.point);
            }
        }        
    }

    /// <summary>
    /// 自定义射线
    /// </summary>
    /// <param 射线原点="_Starting"></param>
    /// <param 射线方向="_Direction"></param>
    public void RayCustom(Vector3 _Starting ,Vector3 _Direction)
    {
        //创建自定义射线
        Ray _RayCusetom = new Ray(_Starting, _Direction);
        //返回结构体
        RaycastHit _CusetomHit;
        //射线布尔 判断
        //参数 射线  返回结构体  最大距离  忽略层 查询报告触发次数
        if (Physics.Raycast(_RayCusetom,out _CusetomHit,1000, ~(1 << LayerMask.NameToLayer("Target")), QueryTriggerInteraction.Collide))
        {
            print("变换的世界空间位置: " + _CusetomHit.transform.position);
            
            print("在世界空间中射线击中对撞机的撞击点: " + _CusetomHit.point);
            
            print("被击中的三角形的重心坐标: " + _CusetomHit.barycentricCoordinate);
            
            print("被撞的碰撞体积: " + _CusetomHit.collider);
            
            print("从射线的原点到撞击点的距离: " + _CusetomHit.distance);
            
            print("在冲击点的uv光贴图坐标: " + _CusetomHit.lightmapCoord);
            
            print("射线照射表面的法线: " + _CusetomHit.normal);
            
            print("被撞击的碰撞器的刚体: " + _CusetomHit.rigidbody);

            print("在碰撞位置的uv纹理坐标: " + _CusetomHit.textureCoord);

            print("被击中的三角形的指数: " + _CusetomHit.triangleIndex);

            print("被击中物体: " + _CusetomHit.transform);
        }
    }
}

Unity UI射线检测

UI 射线和平常的基础射线检测还是有点区别的 剩下的自己悟吧

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// UI 射线检测
/// </summary>
public class WorldEay_ZH : MonoBehaviour
{
    [Header("目标世界位置")]
    public Transform _WorldTarget;

    [Header("UI  事件")]
    public EventSystem _EventSystem;

    [Header("World Canvas")]
    public GraphicRaycaster _WorldCanvas;

    [Header("Canvas")]
    public GraphicRaycaster _Canvas;

    //事件数据 
    private PointerEventData _PointerEventData;

    //屏幕坐标
    private Vector2 _CameraPos;


    void Start()
    {
        //初始值赋予
        _PointerEventData = new PointerEventData(_EventSystem);
    }
   
    void Update()
    {
        //自定义位置 UI 检测
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //世界转换 屏幕空间
            _CameraPos = Camera.main.WorldToScreenPoint(_WorldTarget.position);
            GraphicRaycaster(_CameraPos, _WorldCanvas, _EventSystem);
        }

        //鼠标检测
        if (Input.GetMouseButtonDown(1))
        {
            RaycastUI(_PointerEventData,_Canvas);
        }
    }

    /// <summary>
    /// 鼠标 UI 射线检测
    /// </summary>
    /// <param 事件数据="_PoEvDa"></param>
    /// <param 画布="_CanvasUI"></param>
    public void RaycastUI(PointerEventData _PoEvDa, GraphicRaycaster _CanvasUI)
    {
        //事件数据 检测位置 类似于射线起始位置
        _PoEvDa.position = Input.mousePosition;

        //数据列表捕获
        List<RaycastResult> _Results = new List<RaycastResult>();

        //画布响应
        _CanvasUI.Raycast(_PoEvDa, _Results);

        //数据输出
        foreach (RaycastResult _Eesult in _Results)
        {
            Debug.Log(_Eesult.gameObject.name);
        }
    }



    /// <summary>
    /// UI 射线检测
    /// </summary>
    /// <param 屏幕空间位置="_Pos"></param>
    /// <param 画布="_Canvas"></param>
    ///   <param 事件系统="_EventSystem"></param>
    private void GraphicRaycaster(Vector2 _Pos, GraphicRaycaster _Canvas, EventSystem _EventSystem)
    {
        //事件数据填充
        var _PointerEventData = new PointerEventData(_EventSystem);
        //触发位置赋值
        _PointerEventData.position = _Pos;
        //数据列表 重置
        List<RaycastResult> _ResultsList = new List<RaycastResult>();

        //射线检测
        _Canvas.Raycast(_PointerEventData, _ResultsList);

        //数据输出
        for (int i = 0; i < _ResultsList.Count; i++)
        {
            print(_ResultsList[i].gameObject.transform.name);
        }
    }
}

射线判定生成自定义模型

这个是配合射线的基础应用来实现多条射线在平面上展开,并可以调节射线相隔角度来获取
碰撞点数组进行模型生成。
这个如果看的比较难受的话可以先去看看这篇文章:
链接: Unity代码编写自定义模型 修改器(可扩展)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 射线判定生成自定义模型
/// </summary>
public class CustomMesh_ZH : MonoBehaviour
{
    //网格组件
    private MeshFilter _MeshFilter;
    //渲染组件
    private MeshRenderer _MeshRender;
    //碰撞组件
    private MeshCollider _MeshCollider;

    //顶点数据 数组
    private List<Vector3> _Verts;
    //渲染序列
    private List<int> _Indices;


    [Header("节点坐标物体")]
    public List<Transform> _Vertss;

    [Header("材质球")]
    public Material _Material;
    private Vector2[] _UV;

    [Header("射线碰撞数组")]
    public List<Vector3> _PointVector3;
    [Header("碰撞角度")]
    [Range(1, 180)]
    public int _Angle;

    [Header("半径")]
    public int _Radius;

    [Header("预制体生成存储数组")]
    public List<Transform> _TransformsPro;
    [Header("射线触碰位置生成预制体")]
    public Transform _Pro;


    public static CustomMesh_ZH _CustomMesh_ZH;

    private void Awake()
    {
        //单列
        _CustomMesh_ZH = this;

        transform.eulerAngles = Vector3.right * 180;
        Initialize();

    }


    /// <summary>
    /// 数据生成
    /// </summary>
    public void Generate()
    {
        //数据清除
        CleraMeshData();

        //数据填充

        if (_isBoom)
        {
            StartCoroutine(AddMeshDataOpen());
        }
        else
        {
            StartCoroutine(AddMeshData());
        }


        //数据传递给 Mesh 生成网格数据
        //构造Mesh对象  
        Mesh _Mesh = new Mesh();
        //顶点数据加载读取
        _Mesh.vertices = _Verts.ToArray();
        //渲染序列加载读取
        _Mesh.triangles = _Indices.ToArray();

        //UV数据加载读取
        _Mesh.uv = _UV;

        //从顶点重新计算网格的边界体积。
        _Mesh.RecalculateNormals();
        //从三角形和顶点重新计算网格的法线
        _Mesh.RecalculateBounds();


        //网格数据加载
        _MeshFilter.mesh = _Mesh;
        //碰撞体添加
        _MeshCollider.sharedMesh = _Mesh;
        //材质球赋予
        _MeshRender.material = _Material;

        transform.localPosition = Vector3.zero;
        transform.localScale = Vector3.one;
    }

    /// <summary>
    /// 数据清除
    /// </summary>
    private void CleraMeshData()
    {
        _Verts.Clear();
        _Indices.Clear();
    }

    /// <summary>
    /// 数据填充  闭环
    /// </summary>
    private IEnumerator AddMeshData()
    {
        //节点数据添加
        for (int i = 0; i < _Vertss.Count; i++)
        {
            _Verts.Add(_Vertss[i].position);
        }


        //整体数组 三角构成判断
        switch (_Verts.Count % 3)
        {
            //完美耦合状态
            case 0:
                //循环渲染 三角数列
                for (int i = 1; i < _Verts.Count + 1; i++)
                {
                    //三角面渲染
                    int _Index0 = 0;
                    int _Index1 = i;
                    int _Index2 = i + 1;

                    if (_Index2 >= _Verts.Count)
                    {
                        break;
                    }

                    //存储渲染序列
                    _Indices.Add(_Index0);
                    _Indices.Add(_Index1);
                    _Indices.Add(_Index2);
                    print(_Index0 + " " + _Index1 + " " + _Index2);
                }

                break;

            //余1状态
            case 1:

                //循环渲染 三角数列
                for (int i = 1; i < _Verts.Count; i++)
                {
                    //三角面渲染
                    int _Index0 = 0;
                    int _Index1 = i;
                    int _Index2 = i + 1;
                    //超出三角数列判定
                    if (_Index2 >= _Verts.Count)
                    {
                        break;
                    }

                    //余1状态 补充
                    if (i == _Verts.Count)
                    {
                        //三角面渲染
                        _Index0 = 0;
                        _Index1 = _Verts.Count - 1;
                        _Index2 = _Verts.Count;
                    }

                    //存储渲染序列
                    _Indices.Add(_Index0);
                    _Indices.Add(_Index1);
                    _Indices.Add(_Index2);
                    print(_Index0 + " " + _Index1 + " " + _Index2);
                }

                break;



            //余2状态
            case 2:

                //循环渲染 三角数列
                for (int i = 1; i < _Verts.Count; i++)
                {
                    //三角面渲染
                    int _Index0 = 0;
                    int _Index1 = i;
                    int _Index2 = i + 1;

                    //超出三角数列判定
                    if (_Index2 >= _Verts.Count)
                    {
                        break;
                    }


                    //余2状态 补充
                    if (i == _Verts.Count)
                    {
                        //三角面渲染
                        _Index0 = 0;
                        _Index1 = _Verts.Count;
                        _Index2 = _Verts.Count - 1;
                    }

                    //存储渲染序列
                    _Indices.Add(_Index0);
                    _Indices.Add(_Index1);
                    _Indices.Add(_Index2);
                    print(_Index0 + " " + _Index1 + " " + _Index2);
                }

                break;

            default:
                break;
        }

        #region 循环渲染 三角数列  推演

        // 基础三角数列  推演
        //_Indices.Add(0); _Indices.Add(1); _Indices.Add(2);
        //_Indices.Add(2); _Indices.Add(3); _Indices.Add(4);
        //_Indices.Add(4); _Indices.Add(5); _Indices.Add(6);
        //_Indices.Add(6); _Indices.Add(7); _Indices.Add(8);
        //_Indices.Add(8); _Indices.Add(0); _Indices.Add(2);
        //_Indices.Add(2); _Indices.Add(4); _Indices.Add(6);
        //_Indices.Add(6); _Indices.Add(8); _Indices.Add(2);



        //for (int i = 0; i < _Verts.Count; i++)
        //{
        //    三角面渲染
        //    int _Index0 = i + _Number;
        //    int _Index1 = i + _Number + 1;
        //    int _Index2 = i + _Number + 2;
        //    _Number++;

        //    if (_Index2 > _Verts.Count)
        //    {
        //        _Number = 0;
        //        _Reuse.Add(0);
        //        _TwoReuse.Add(_Reuse[0]);

        //        for (int j = 0; j < _Reuse.Count; j++)
        //        {
        //            print(_Reuse[j]);
        //        }
        //        break;
        //    }
        #endregion


        yield return new WaitForSeconds(0.1f);

    }

    /// <summary>
    /// 数据填充  开环
    /// </summary>
    /// <returns></returns>
    private IEnumerator AddMeshDataOpen()
    {
        //节点数据添加
        for (int i = 0; i < _Vertss.Count; i++)
        {
            _Verts.Add(_Vertss[i].position);
        }

        int _Number = 0;
        //整体数组 三角构成判断
        switch (_Verts.Count % 3)
        {
            //完美耦合状态
            case 0:
                //循环渲染 三角数列
                for (int i = 0; i < _Verts.Count; i++)
                {
                    //三角面渲染
                    int _Index0 = i + _Number;
                    int _Index1 = i + 1 + _Number;
                    int _Index2 = i + 2 + _Number;

                    if (_Index2 >= _Verts.Count)
                    {
                        break;
                    }

                    //存储渲染序列
                    _Indices.Add(_Index0);
                    _Indices.Add(_Index1);
                    _Indices.Add(_Index2);

                    _Number++;
                    print(_Index0 + " " + _Index1 + " " + _Index2);
                }

                break;

            //余1状态
            case 1:

                //循环渲染 三角数列
                for (int i = 0; i < _Verts.Count; i++)
                {
                    //三角面渲染
                    int _Index0 = i + _Number;
                    int _Index1 = i + 1 + _Number;
                    int _Index2 = i + 2 + _Number;

                    if (_Index2 >= _Verts.Count - 1)
                    {
                        break;
                    }

                    //存储渲染序列
                    _Indices.Add(_Index0);
                    _Indices.Add(_Index1);
                    _Indices.Add(_Index2);

                    _Number++;
                    print(_Index0 + " " + _Index1 + " " + _Index2);
                }

                break;



            //余2状态
            case 2:

                //循环渲染 三角数列
                for (int i = 0; i < _Verts.Count; i++)
                {
                    //三角面渲染
                    int _Index0 = i + _Number;
                    int _Index1 = i + 1 + _Number;
                    int _Index2 = i + 2 + _Number;

                    if (_Index2 >= _Verts.Count - 2)
                    {
                        break;
                    }

                    //存储渲染序列
                    _Indices.Add(_Index0);
                    _Indices.Add(_Index1);
                    _Indices.Add(_Index2);

                    _Number++;
                    print(_Index0 + " " + _Index1 + " " + _Index2);
                }

                break;

            default:
                break;
        }

        yield return new WaitForSeconds(0.1f);
    }

    /// <summary>
    /// 初始化
    /// </summary>
    private void Initialize()
    {
        _Verts = new List<Vector3>();
        _Indices = new List<int>();

        if (GetComponent<MeshFilter>() == null)
        {
            _MeshFilter = transform.gameObject.AddComponent<MeshFilter>();
        }
        else
        {
            _MeshFilter = GetComponent<MeshFilter>();
        }
        if (GetComponent<MeshRenderer>() == null)
        {
            _MeshRender = transform.gameObject.AddComponent<MeshRenderer>();
        }
        else
        {
            _MeshRender = GetComponent<MeshRenderer>();
        }
        if (GetComponent<MeshCollider>() == null)
        {
            _MeshCollider = transform.gameObject.AddComponent<MeshCollider>();
        }
        else
        {
            _MeshCollider = GetComponent<MeshCollider>();
        }
        //Generate();
    }

    bool _isBoom = false;
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _isBoom = !_isBoom;

        }

        if (Input.GetKeyDown(KeyCode.Q))
        {
            //碰撞数组
            _PointVector3 = new List<Vector3>();

            _Vertss.Clear();
            for (int i = 0; i < _TransformsPro.Count; i++)
            {
                Destroy(_TransformsPro[i].gameObject);
            }
            _TransformsPro.Clear();

            //角度数列
            int _AngleNumber = 0;

            for (int i = 0; i < 361; i++)
            {

                _AngleNumber += _Angle;

                if (_AngleNumber > 360)
                {
                    Generate();
                    return;
                }
                else
                {
                    RaycastHit _Hit;
                    if (Physics.Raycast(transform.position,
                        new Vector3(transform.position.x + _Radius * Mathf.Cos(_AngleNumber * Mathf.PI / 180), transform.position.y, transform.position.z + _Radius * Mathf.Sin(_AngleNumber * Mathf.PI / 180)), out _Hit))
                    {
                        if (_Hit.collider.gameObject.layer== LayerMask.NameToLayer("Valid"))
                        {
                            _PointVector3.Add(_Hit.point);

                            Transform _ProT = Instantiate(_Pro,_Hit.point,Quaternion.identity,transform);

                            _TransformsPro.Add(_ProT);
                            _Vertss.Add(_ProT);
                        }
                    }
                }
                //Debug.Log(_AngleNumber);
            }
        }

    }
    private void OnDrawGizmos()
    {
        //Gizmos.DrawWireSphere(transform.position, _Radius);
        //Gizmos.DrawLine(transform.position, new Vector3(_Radius * Mathf.Cos(_Angle), transform.position.y, _Radius * Mathf.Sin(_Angle)));
        //角度数列
        int _AngleNumber = 0;
        for (int i = 0; i < 361; i++)
        {
            _AngleNumber += _Angle;
            //_Angle = i;
            Gizmos.DrawLine(transform.position, new Vector3(transform.position.x + _Radius * Mathf.Cos(_AngleNumber * Mathf.PI / 180), transform.position.y, transform.position.z + _Radius * Mathf.Sin(_AngleNumber * Mathf.PI / 180)));

            if (_AngleNumber>360)
            {
                return;
            }
        }
    }
}
组件搭载:

在这里插入图片描述

运行情况(按Q执行):

在这里插入图片描述

最终效果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
暂时先这样吧,如果实在看不明白就留言,看到我会回复的。
路长远兮,与君共勉。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maddie_Mo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值