12 第1页 | 共2 页下一页
返回列表 发新帖
查看: 15468|回复: 12
打印 上一主题 下一主题

[教程] Unity3d中的碰撞检测(三)

[复制链接]

21

主题

7

听众

651

积分

初级设计师

Rank: 3Rank: 3

纳金币
0
精华
3

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-11-3 22:25:15 |只看该作者 |倒序浏览
   这一篇我紧接着上一篇来讨论一个我们避不开的一个问题,那就是镜头穿墙问题。其实,这个镜头穿墙问题确实是一个很棘手的问题。因为到现在都不能说100%解决,不光中国,甚至是国外也是。你也许会发现在某些游戏中,镜头也会或多或少的穿透物体或者墙壁的情形。如果是第一人称视角的话,根本不会出现这宗问题,但是如果是第三人称视角的话,我们就必须寻求一个优化这个问题的方式,这就是我今天要介绍的:利用射线作为工具来优化有关镜头穿墙方面的问题,我先将我们遇到的一个镜头穿墙的现象截一张图:




在这张图中我们可以发现我们的镜头穿透了墙壁到了墙壁外面,但还是看到了墙壁内的画面。如果是在现实中的话,那就


这次我先用这个工程:官方的ShadowDemoProject中的Apartment Scene这个场景,我们可以清清楚楚的看到,如果不对摄像机做一番处理,那么随着人物角色的旋转,摄像机穿透物体简直可以说是毫无压力,如果在游戏里面发生这样的情况,就会让玩家怀疑游戏的真实度。这是确实是我们不想看到的。那么接下来我就要对摄像机的代码做一定的修改了。
        由于我个人以前用的是java,所以对C#的语法感觉似曾相识,因为java与C#确实是太相似了。这次我写了一个摄像机控制的C#脚本。然后加入了射线的碰撞检测,代码如下:


using UnityEngine;
using System.Collections;

public class GooberCamera : MonoBehaviour {

    public Transform target;
    public float distance = 4.0f;
    public float maxDis = 4.0f;

    public float smoothPosition = 5.0f;
    public float smoothDis = 5.0f;
    public float jd = 45f;
    public float padding = 0.3f;
    public Vector3 dir = new Vector3(0, 1, -1);

    private LayerMask mask;

void Start () {








        mask = 1<<( LayerMask.NameToLayer("MustRaycast"));//实例化mask到MustRaycast这个自定义的层级之上。






        transform.eulerAngles = new Vector3(jd,0,0);//让摄像机成45&deg;角对准视野。






        if(!target){






            return;






        }








}


void LateUpdate () {








        transform.eulerAngles = new Vector3(jd, 0, 0);//不断校正摄像机的旋转角度。






        RaycastHit hit;//用于射线的碰撞检测













        maxDis = Mathf.Lerp(maxDis, distance, Time.deltaTime * smoothDis);//不断让maxDis接近于distance,不然maxDis只会不断变小






        if (Physics.Raycast(target.position, dir, out hit, maxDis + padding, mask))//开始射线方式的碰撞检测






        {






            maxDis = hit.distance - padding;//使maxDis变小,这是为了将摄像头拉近到角色。






        }




















        transform.position = Vector3.Lerp(transform.position, target.position + transform.forward * (-maxDis), smoothPosition);







    }
}



我让摄像机与的视角保持在45度,并且运用到了LayerMask这个类。我将那个房间里面的不懂的物体(不包括那些刚体)标示为静态的,然后添加了一个层,取名为:MustRaycast(如果读者对这方面还不熟悉,可以参考我上一篇文章)。然后有选择的进行碰撞检测,如果不管碰到什么东西你都检测的话,会出现大量的问题,比如如果角色与摄像机从一开始两者连线之间就有障碍物,那么就会发生摄像机一开始就会迅速靠近角色。角色的话我用了官方CharacterAnimation这个工程里面的goober。下面我们运行一下:
这是开始时摄像机没有检测到碰撞时Scene视图下的情形:



这是开始时摄像机检测到碰撞时Scene视图下的情形:



此时Game视图下是这样的:






很明显,摄像头被角色遮挡了,所以视野一片黑暗。
        可是,这个代码也只是对镜头穿墙做了一定的处理,并没有完全解决问题,因此还是会有一定的穿墙情况发生。但是这个射线发射与LayerMask的应用确实给我们提供了一个很好的方式来解决特定事件。最后我还介绍一下有关LayerMask的实例化:
比如一个特定的layer,假设其名字为:layer1,则可以这样创建LayerMask类型变量:
LayerMask   layerMask = 1<<LayerMask.NameToLayer( "layer1" );

如果要是这个layerMask包含层layer2,那么可以用“|”,即逻辑“或”来做运算:

layerMask |=1<< LayerMask.NameToLayer( "layer2" )。

那么既然可以用或运算,那么就可以用非运算。比如,如果我们的layerMask是除layer1与layer2的其他层的集合,那么我们可以这样来做:


LayerMask   layerMask =1<< LayerMask.NameToLayer( "layer1" );//理解不了的可以看我的上一篇帖子。下一行代码也是一样的。
layerMask |=1<< LayerMask.NameToLayer( "layer2" );
layerMask = ~layerMask。//对layerMask取反,就是得到除layer1与layer2之外的其他层级的集合。



这样一来,我们就可以控制射线检测碰撞的范围了,这简直太棒了。

至此有关LayerMask配合射线碰撞的讲解也算是到了一定程度了。好了,今天放假,有点困了,晚安。

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏1 支持支持0 反对反对0
回复

使用道具 举报

955

主题

164

听众

7万

积分

版主

Rank: 7Rank: 7Rank: 7

纳金币
59338
精华
28

活跃会员 荣誉管理 突出贡献 优秀版主 论坛元老

沙发
发表于 2012-11-3 23:29:30 |只看该作者
感谢分享精彩的教程!
回复

使用道具 举报

.    

3797

主题

11

听众

5万

积分

首席设计师

Rank: 8Rank: 8

纳金币
32328
精华
41

活跃会员 优秀版主 荣誉管理 论坛元老

板凳
发表于 2012-11-8 21:15:41 |只看该作者
这是一个好帖子,大家快来围观!!
回复

使用道具 举报

2206

主题

2

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
32449
精华
23

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2012-11-9 14:01:08 |只看该作者
               
回复

使用道具 举报

1

主题

1

听众

81

积分

设计初学者

Rank: 1

纳金币
8
精华
0

活跃会员 灌水之王

5#
发表于 2013-5-28 17:30:17 |只看该作者
感谢楼主分享!!!!!!!
回复

使用道具 举报

19

主题

3

听众

1357

积分

助理设计师

Rank: 4

纳金币
636
精华
0

活跃会员

6#
发表于 2013-5-29 11:57:52 |只看该作者
谢谢分享了
回复

使用道具 举报

3

主题

2

听众

1154

积分

助理设计师

Rank: 4

纳金币
31
精华
0
7#
发表于 2013-12-26 15:42:31 |只看该作者

谢谢分享了
回复

使用道具 举报

0

主题

1

听众

592

积分

初级设计师

Rank: 3Rank: 3

纳金币
314
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

8#
发表于 2013-12-27 16:00:59 |只看该作者
支持下楼主
回复

使用道具 举报

0

主题

1

听众

592

积分

初级设计师

Rank: 3Rank: 3

纳金币
314
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

9#
发表于 2013-12-27 16:01:19 |只看该作者
但是代码间感觉空行有点大
回复

使用道具 举报

0

主题

1

听众

329

积分

设计实习生

Rank: 2

纳金币
2
精华
0

最佳新人

10#
发表于 2013-12-28 23:13:42 |只看该作者
恩恩,不错,学习了!
回复

使用道具 举报

12 第1页 | 共2 页下一页
返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-4-26 09:24 , Processed in 0.096142 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部