赞
踩
本文简要分析了Unity中各类 射线检测 的基本原理及用法,及不同检测手段的性能对比。内容包括:
博客园:Unity - Raycast
项目地址:Raycast - SouthBegonia
Ray ray = new Ray(transform.position,transform.forward)
:从物体中心创建一条指向前方的射线rayRay camerRay = Camera.main.ScreenPointToRay(Input.mousePosition)
:产生一条从摄像机产生、经过屏幕上光标的射线。当相机为perspective模式,射线在相机梯形视野内发散;若为orthoGraphic,则为垂直与相机面的直线段(见上图)Raycast(transform.position, Vector.forward, distance, LayerMask.GetMask("Enemy"))
: 从物体中心点起,朝向Vector3.forward方向发射一条射线,该射线长度为distance,射线可检测到的层为Enemy层,返回bool类型Raycast(transform.position, Vector.forward, distance, out RaycastHitInformation ,LayerMask.GetMask("Enemy"))
:从物体中心点起,朝向Vector3.forward方向发射一条射线,该射线长度为distance,将碰撞信息反馈到RaycastHitInformation上,射线可检测到的层为Enemy层,返回bool类型Raycast (MyRay, distance, LayerMash.GetMask("Enemy"))
:从已有的射线MyRay出发,长度延伸至distance,射线可检测到的层为Enemy层,返回bool类型Raycast (MyRay, out RaycastHitInformation, distance, LayerMask.GetMask("Enemy"))
RaycastHit[] hits = RaycastAll(Vector3.zero, Vector.forward, distance, LayerMask.GetMask("Enemy"))
RaycastHit[] hits = RaycastAll(MyRay, distance, LayerMash.GetMask("Enemy"))
Linecast(startPos, endPos, LayerMask.GetMask("Enemy"))
Linecast(startPos, endPos, out RaycastHit, LayerMask.GetMask("Enemy"))
BoxCast(originPos, halfExtents, direction, out RaycastHit, distance, LayerMask.GetMask("Enemy"))
:含义是在originPos点创建半径halfBoxLength的立方体(Vector3型,代表为正立方体在三个方向上的大小,一般用localScale/2);以朝向direction方向的平面为起始面(另一面舍弃),移动distance距离,期间经过的区域即为检测区域。(见下补充分析)SphereCast(originPos, radius, direction, out RaycastHit, distance, LayerMask.GetMask("Enemy"))
:含义是在originPos点创建半径为radius的球体;以朝向direction方向的球面为起始面(另一面舍弃),移动distance距离,期间半球面经过的区域即为检测区域。那么originPos到originPos+radius内的半球区域呢?答案是舍弃,用官方的话来说,是边界而不是包围体 。(立体结构:以左右球球心为轴线,建立半径为radius、高为distance的圆柱体,左球挖去右半体积,右球添加右半体积)SphereCast (Ray, radius, out RaycastHit, distance, LayerMask.GetMask("Enemy"))
Physics.CapsuleCast(pos1, pos2, radius, direction, out RaycastHit, maxDistance, LayerMask.GetMask("Anchor"))
:机理和SphereCast类似,在pos1、pos2两点创建半径为0.5f的球体,以此作为胶囊体模型两端;以朝向direction方向的半胶囊体面为起始面,移动maxDistance距离,期间该面经过的区域即为检测区域。(注:maxDistance和上面的distance必须非0否则无用)Physics.CapsuleCast(pos1, pos2, 0.5f, Vector3.forward, out RaycastHit, 0.1f, LayerMask.GetMask("Anchor"))
Collider[] hits = OverlapBox(Pos, halfExtents, Quaternion.identity, LayerMask.GetMask("Enemy"))
:以Pos点为中心创建三维半径halfExtents的正立方体,不对其进行旋转,检测层为EnemyCollider[] hits = Physics.OverlapSphere(Pos, radius, LayerMask.GetMask("Enemy"))
:以Pos为原点,创建半径为radius的球形,检测区域为整个球形包围体(实心),检测Enemy层上的物体,返回所有碰撞物体的collider而不是RaycastHit(注意:存在于球内部的物体也会被检测到)Collider[] hits = OverlapCapsule(pos1, pos2, radius, LayerMask.GetMask("Enemy"))
:在pos1、pos2两点创建半径为radius的球体,加上中间部分组成胶囊体,检测Enemy层CollAmount = Physics.OverlapBoxNonAlloc(Pos, halfExtents, colliders, Quaternion.identity, LayerMask.GetMask("Enemy"))
CollAmount = OverlapSphereNonAlloc(Pos, radius, colliders, LayerMask.GetMask("Enemy"))
CollAmount = OverlapCapsuleNonAlloc(pos1, pos2, radius, colliders, LayerMask.GetMask("Enemy"))
IsOverlapAnyCollider = Physics.CheckBox(transform.position, transform.localScale / 2, Quaternion.identity, LayerMask.GetMask("Enemy"))
:在物体中心创建检验盒,一定大小,不旋转,检测Enemy层,若有检测到碰撞则返回TrueIsOverlapAnyCollider = Physics.CheckSphere(transform.position, radius, LayerMask.GetMask("Enemy"))
IsOverlapAnyCollider = Physics.CheckCapsule(pos1, pos2,radius, LayerMask.GetMask("Enemy"))
IgnoreCollision (collider1, collider2, ignore)
DrawLine(startPos, endPos, color)
:绘制一条从startPos到endPos点、颜色为color的线段DrawRay(startPos, direction, color)
:绘制一条从startPos出发,指向direction的、颜色color的射线(默认长度为单位向量,再乘以倍率即可边长;在下一次绘制才会覆盖上一次的射线)Debug.DrawRay(startPos , direction, color, duration)
:同理绘制一定方向射线,但射线持续时间为duration :void OnDrawGizmos() { Gizmos.DrawCube(transform.position, transform.localScale );}
从上面对几种检测方法的分析及对比其返回值不难发现,不同方法产生GC情况相差甚远,因此在工程项目上应该慎重使用。此处引用网友 HONT的测试作为GC情况参考:
作者: SouthBegonia
出处:https://www.cnblogs.com/SouthBegonia/p/11732340.html
版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。