墙和物体都要加上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还有以下一些方向:
参考资料 https://docs.unity3d.com/ScriptReference/Vector3.html
back | Shorthand for writing Vector3(0, 0, -1). |
down | Shorthand for writing Vector3(0, -1, 0). |
forward | Shorthand for writing Vector3(0, 0, 1). |
left | Shorthand for writing Vector3(-1, 0, 0). |
negativeInfinity | Shorthand for writing Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity). |
one | Shorthand for writing Vector3(1, 1, 1). |
positiveInfinity | Shorthand for writing Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity). |
right | Shorthand for writing Vector3(1, 0, 0). |
up | Shorthand for writing Vector3(0, 1, 0). |
zero | Shorthand 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的使用
墙和物体都要加上collider(碰撞体),一般注意以下几点:墙加mesh collider,在Convex上打勾 物体加box collider 加刚体(rigidbody)的物体不要选Is Kenimatic基础最简单的Raycast方法void Update(){ RaycastHit hitInfo; Vector3 fwd = Camera.m...
昨天做室内模型的时候,遇到一个非常棘手的问题,那就是第一视角在室内运行的时候,会出现穿墙的效果。类似下图效果,在靠近墙壁的时候,出现了镜头看见了墙壁外的情况,很显然这是不符合逻辑的。我们要做的就是避免这一问题的发生。
我的代码很简单,就是官方的FPS控制器,拿过来就能用。
我一开始遇到这个问题,也是搜了很多的资源,网上的答案层出不穷,脚本也是千奇百怪,但是这些对我来说,意义都不大,都没...
//首先,不好意思,可能标题的描述并不是很清楚
//我们现在的场景是这样的,一个摄像机在高处,场景中间有一面高墙,墙的后面有一个球形物体
//高度够高的时候我们可以看到球形物体,当摄像机的y轴下降的时候,就只能看到墙,看不到球形物体
//而我们现在的需求是,当球形物体被墙挡住的时候,我们想让墙消失,y轴够高的时候,又让墙出现
//好了,接下来看我们的代码吧~
using Unit
这个问题,摄像机拍摄主角,当主角被墙遮蔽了视野,那么就用正上方的点和当前相机所在位置的店为起始点和终点,从二者之间再找出三个关键点进行射线检测,能看到主角的店即可作为摄像机的transform.position Vector3[] posArray;
Vector3 beginPos = player.transform.position + offset;
Vector3 endPo
1.重新进行Unity布局,右上角哪里重新进行Layout布局,一般可以恢复Scene视角相机的初始化
2.Scene视角顶部信息栏有一个摄像头图标,点开,就是可以进行Scene摄像机的控制,把Field of View调小就可以调整穿模现象了。
我学习Unity3D一小段时间了,第一个制作目标就是实现一个自由漫游的摄像机。
使用WSAD键控制摄像机的上下左右移动,使用鼠标右键控制摄像机的旋转。
这个功能比较简单,代码也一目了然,不做过多解释了,直接上代码。
//-----------------------------------------------------------------
//1,把本类作为一个组件,包含在 Gam