博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity3D 射线指定层获取GameObject 注意 LayerMask
阅读量:5312 次
发布时间:2019-06-14

本文共 2920 字,大约阅读时间需要 9 分钟。

这一篇是纯技术讨论,看过我前面文章的童鞋应该清楚,我的奔跑是靠鼠标响应的,鼠标点到哪就跑到哪,后来又有了界面,麻烦就来了,我的界面居然能点 穿。我不希望点界面的时候还能点到界面后面的地面上,角色傻不拉几的往那跑,那肿么办呢,总不能每次点击都要推断点击的物体名称吧。那界面多了会累死的, 好在我们有标签和层这两个神器,所以我这里介绍两种方案,都能达到效果。

方案一:利用标签(Tag)拦截射线消息。

每一个GameObject的Inspector面板最上方都有个Tag选项,也就是说我们能够给全部的物体加个标签,Unity3d已经默认有了几 个标签,这里我们能够自己定义个UI的标签。然后把全部UI都用这个标签。点击Tag右方的选项。选Add Tag。Size调成2。Element 0的值改成UI。

然后你全部不想被点穿的UI都选成这个标签。

除了设置标签,另一点非常重要,就是界面要加碰撞器Collider,有的UI默认就有碰撞器,比方NGUI的button,你能够看到有一个Box Collider。假设没有的你就要自己加了,Size那里要调成这个UI的尺寸:

这样UI才干接收射线碰撞。然后代码能够这样写:

[csharp] 
  1. Ray ray1 = nguiCamera.camera.ScreenPointToRay(Input.mousePosition);  
  2. RaycastHit hit1;  
  3. if (Physics.Raycast(ray1, out hit1)) {  
  4.     if (hit1.collider.gameObject.tag == "UI")  
  5.         return;  
  6. }  

上面的nguiCamera是获取的NGUI下的Camera。由于是这个Camera发出的射线与UI的碰撞,而不是Main Camera,这点要注意。其它的不解释了。非常easy,自己看。

方案二、利用层(Layer)拦截射线消息

每一个GameObject的Inspector面板最上方都也有个Layer选项,就在Tag旁边,unity3d已经有了几个层。我们新建个层。 也叫UI,点击Add Layer,能够看到从Layer0到Layer7都灰掉了,那是不能用的,从第八个起能够用。所以在第八个建个UI的层。

然后我们看一下Physics的Raycast的參数:

static function Raycast (ray : out hitInfo : distance : float = layerMask : int = kDefaultRaycastLayers) : bool

普通情况下我们仅仅用前两个參数,distance表示射线距离,默认是无限远,重点是最后一个參数layerMask,专门处理layer过滤的,是个整型,怎么用呢。是靠layer的二进制位来操作的。看以下代码就清楚了:

[csharp] 
  1. Ray ray1 = nguiCamera.camera.ScreenPointToRay(Input.mousePosition);  
  2. RaycastHit hit1;  
  3. LayerMask mask = 1 << LayerMask.NameToLayer("UI");  
  4. if (Physics.Raycast(ray1, out hit1, 600, mask.value)) {  
  5.     return;  
  6. }  

LayerMask的NameToLayer是通过层的名称返回该层的索引,这里是8,然后1<<8换算成LayerMask值,再用LayerMask的value就能够了。

注意也必须设置collider才干接收碰撞,这里才干推断到。

我这里提供了两个方案,假设有其它方案的欢迎留言,谢谢。
笔者补充内容
 假设是在代码中自己创建GameObject指定Layer的方法和获取Layer进行射线的注意地方。
例如以下创建一个GameObject:
          GameObject _newObj = new GameObject();
            _newObj.layer = LayerMask.NameToLayer("CommObj"); //指定Layer
            _newObj.name = "Terrain0_Grass";
            print(LayerMask.NameToLayer("CommObj"));
            BoxCollider _collider = _newObj.GetComponent();
            _collider = _collider == null ?

_newObj.AddComponent() : _collider;

            _collider.center = Vector3.zero;
            _collider.size = new Vector3(10f, CommonDef.Layer0_Terrain_Grass, 10f);
            MeshFilter _meshFilter = _newObj.GetComponent();
            _meshFilter = _meshFilter == null ?

_newObj.AddComponent() : _meshFilter;

            Mesh _mesh = ModelResManager.AddTerrainGrassMesh(10, 10);
            _meshFilter.mesh = _mesh;
            MeshRenderer _meshRender = _newObj.GetComponent();
            _meshRender = _meshRender == null ? _newObj.AddComponent() : _meshRender;
            //指向父子节点关系,仅仅需指定其位置组件父子关系;
            GameObject _subObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
            _subObj.transform.parent = _newObj.transform;
以上是创建一个GameObject。赋上Collider组件用于射线碰撞检測。下面是获取指定Layer射线的方法:
 
          LayerMask mask = 1 << LayerMask.NameToLayer("CommObj");
          Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
          RaycastHit _hitInfo;
          if (Physics.Raycast(ray, out _hitInfo, 1000f, mask.value))
          {
             m_currSelectObj = _hitInfo.collider.gameObject;
             m_mouseMovePos = _hitInfo.point;
         }
黑体字为获取指定Layer的mask值。用于射线检測。

转载于:https://www.cnblogs.com/llguanli/p/6950458.html

你可能感兴趣的文章
uWSGI参考资料
查看>>
应急信息报送和值班工作的培训学习
查看>>
索引优化:select语句建立理性索引
查看>>
《JAVA与模式》之简单工厂模式
查看>>
Fixed DC-DC Regulator Output Uses A Digitally Controlled Potentiometer
查看>>
CAN Timing Sample Point
查看>>
Android图像处理之Bitmap类
查看>>
[KOJ6024]合并果子·改(强化版)
查看>>
[BZOJ3238][Ahoi2013]差异
查看>>
[codevs2185]最长公共上升子序列
查看>>
Spring+Struts+Hibernate 简介(转)
查看>>
动词短语搭配 (转)
查看>>
认识Android Service
查看>>
关于最近用过的一些类
查看>>
用Android模拟器也可以开发和测试NFC应用
查看>>
OpenCV属性页配置问题~
查看>>
Fragment
查看>>
js的另一个机制: cookie
查看>>
【数字图像处理】直方图均衡化
查看>>
mysql之锁、存储引擎和用户账户管理
查看>>