Unity3D 自制摄像机不穿墙/不穿物体(射线cast方法)

墙和物体都要加上collider(碰撞体),一般注意以下几点:

  • 墙加mesh collider,在Convex上打勾
  • 物体加box collider
  • 加刚体(rigidbody)的物体不要选Is Kenimatic

基础 最简单的Raycast方法

void Update()
{RaycastHit hitInfo;Vector3 fwd = Camera.main.transform.TransformDirection(Vector3.forward);if (Physics.Raycast(Camera.main.transform.position, fwd, out hitInfo, 0.5f)){float dis = hitInfo.distance;Vector3 correction = Vector3.Normalize(Camera.main.transform.TransformDirection(Vector3.back)) * dis;Camera.main.transform.position += correction;}
}

 上面的代码,在撞墙时会有抖动的效果,如果要平滑后退,可以把

Vector3.Normalize(Camera.main.transform.TransformDirection(Vector3.back)) * dis;

改为:

Vector3.Normalize(Camera.main.transform.TransformDirection(Vector3.back)) * dis * Time.deltaTime;

但是,这样可能会出现“移动物体过快导致穿墙”的问题。

关于 TransformDirection 参考资料: Unity TransformPoint、InverseTransformPoint、TransformDirection 

Vector3 worldPosition = transform.TransformPoint ( Vector3 relativePosition ) 
        将相对 “当前游戏对象” 的坐标转化为基于世界坐标系的坐标
Vector3 relativePosition = transform.InverseTransformPoint ( Vector3 worldPosition ) 
        将世界坐标转化为相对 “当前游戏对象” 的基于世界坐标系的坐标
Vector3 worldDirection = Transform.TransformDirection ( Vector3 relativeDirection ) 
        将相对 “当前游戏对象” 的方向转化为基于世界坐标系的方向(不受父对象缩放的影响)

进阶1 四个方向Raycast

在上一种方法中,显然,只有一个方向(前方)能不穿墙,没有考虑如下情况:

  • 摄像机倒着走,从背后穿墙
  • 摄像机横着向左/右走,从左/右穿墙

这里用了一个比较蠢的方法,就是往前、后、左、右四个方向投射线,作四次检测。把这个检测过程封装成函数detect()。

Vector3.forward实际是一个固定值,unity 内置的vector3还有以下一些方向:

参考资料 Unity - Scripting API: Vector3

backShorthand for writing Vector3(0, 0, -1).
downShorthand for writing Vector3(0, -1, 0).
forwardShorthand for writing Vector3(0, 0, 1).
leftShorthand for writing Vector3(-1, 0, 0).
negativeInfinityShorthand for writing Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity).
oneShorthand for writing Vector3(1, 1, 1).
positiveInfinityShorthand for writing Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity).
rightShorthand for writing Vector3(1, 0, 0).
upShorthand for writing Vector3(0, 1, 0).
zeroShorthand for writing Vector3(0, 0, 0).
void detect(Vector3 dir, Vector3 inverse_dir)
{RaycastHit hitInfo;Vector3 _dir = Camera.main.transform.TransformDirection(dir);if (Physics.Raycast(Camera.main.transform.position, _dir, out hitInfo, 0.5f)){float dis = hitInfo.distance;Vector3 correction = Vector3.Normalize(Camera.main.transform.TransformDirection(inverse_dir)) * dis;Camera.main.transform.position += correction;}
}// Update is called once per frame
void Update()
{detect(Vector3.forward, Vector3.back);detect(Vector3.back, Vector3.forward);detect(Vector3.left, Vector3.right);detect(Vector3.right, Vector3.left);
}

进阶2 SphereCast

这里,射线只有一个像素点,尽管已经覆盖四个方向,但是可能还是会有疏漏的情况。可以用Physics.SphereCast()方法。

可参考下列指南:http://www.ceeger.com/Script/Physics/Physics.SphereCast.html

void detect(Vector3 dir, Vector3 inverse_dir)
{RaycastHit hitInfo;Vector3 _dir = Camera.main.transform.TransformDirection(dir);if (Physics.SphereCast(Camera.main.transform.position, 0.5f, _dir, out hitInfo, 0.5f)){float dis = hitInfo.distance;Vector3 correction = Vector3.Normalize(Camera.main.transform.TransformDirection(inverse_dir)) * dis;Camera.main.transform.position += correction;}
}// Update is called once per frame
void Update()
{detect(Vector3.forward, Vector3.back);detect(Vector3.back, Vector3.forward);detect(Vector3.left, Vector3.right);detect(Vector3.right, Vector3.left);
}

进阶3 层遮罩LayerMask

某些碰撞体(collider) 可能只被用作trigger,但是却受到了碰撞检测。

一个比较简单的方法:

把物体放置到 Ignore Raycast层

或者用LayerMask,以下为示例:

void detect(Vector3 dir, Vector3 inverse_dir)
{RaycastHit hitInfo;Vector3 _dir = Camera.main.transform.TransformDirection(dir);LayerMask _ignoreLayer = 1 << LayerMask.NameToLayer("mylayer");if (Physics.Raycast(Camera.main.transform.position, _dir, out hitInfo, 0.5f, _ignoreLayer)){float dis = hitInfo.distance;Vector3 correction = Vector3.Normalize(Camera.main.transform.TransformDirection(inverse_dir)) * dis;Camera.main.transform.position += correction;}
}

更详细资料可参考:U3D开发学习之路--RayCast中layerMask的使用


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部