zoukankan      html  css  js  c++  java
  • Unity

    本文简述了LayerMask的定义,后通过项目实战充分解析 LayerMask中的GetMask、LayerToName、NameToLayer 等函数的使用方法及其注意事项。
    项目地址:3D坦克大战 - SouthBegonia

    LayerMask 定义

    用来表示32个Layer层级的位掩码,类型为Int32,。前面8个是引擎使用的,后面24个供开发人员使用的。通过LayerMask我们可以实现诸多类似 层判定、层限制、层检测 的方法。的我们可以在Edit->Project Setting->Tags and Layers->Layers 中看到这32层(见下图)

    LayerMask 方法

    GetMask

    函数原型:public static int GetMask(params string[] layerNames)

    功能:传入一个图层名称列表,返回这个图层列表的等效图层蒙版。此处大家再回看上面的函数原型可能会产生疑问:何为等效图层蒙版,为何它的类型为int?它的用处是什么?

    解析:我们先Debug看看上图中第1层和第5层看看:

    //Way1:GetMask方法
    Debug.Log(LayerMask.GetMask("Default");	       -->1
    Debug.Log(LayerMask.GetMask("Default", "UI"));	-->33
    

    一个非常奇怪的数据,但是我们转换成二进制呢?

    1 --> ‭0001‬
    33 --> ‭0010 0001‬
    

    不难发现,这是Int32的位掩码,即LayerMask,第1、5位数为1表示开启了这两个层。因此可以说:等效图层蒙版 == 启用/关闭某几层的LayerMask位掩码, 1表示开启,0表示关闭。此外我们还可以使用位运算实现等效图层蒙版:

    //Way2:位操作方法
    LayerMask layer1 = (1 << 0);
    LayerMask layer2 = (1 << 0) | (1 << 5);
    Debug.Log(layer1.value);	  -->1
    Debug.Log(layer2.value);	  -->33
    
    //等效于:
    LayerMask layer3 = LayerMask.GetMask("Default","UI");
    Debug.Log(layer3.value);	  -->33
    
    //其他位操作方法:
    LayerMask layer4 = (0 << 5);  	 //关闭索引为5的层
    LayerMask layer5 =  ~(1 << 5);     //打开除了索引为5的层之外的层
    

    那么怎么落实到项目中呢?在此提供一个项目示例(地址在文章首):我们在开发坦克大战游戏,有红蓝绿三方阵营,我们想让各自阵营的炮弹不伤害到友军,这时我们就需要用到LayerMask:

    //设置LayerMask的类:
    public class LayerManager : MonoBehaviour
    {
        public static int blueLayer = 10;
        public static int greenLayer = 11;
        public static int redLayer = 12;
    
    	//传入玩家所在Team的结构体变量,返回敌人所在的图层蒙版
        static public LayerMask GetEnemyLayer(Team team)
        {
            LayerMask mask = 0;
            switch (team)
            {
                case Team.Blue:
                    mask = (1 << redLayer) | (1 << greenLayer);     //开启redLayer层和greenLayer层
                    break;
                case Team.Green:
                    mask = (1 << redLayer) | (1 << blueLayer);
                    break;
                case Team.Red:
                    mask = (1 << blueLayer) | (1 << greenLayer);
                    break;
            }
            return mask;
        }
    }
    
    //炮弹脚本的碰撞检测片段:
    public void OnCollisionEnter(Collision collision)
    {
    	//射线检测球形范围内enemyLayers层敌人的collider
    	Collider[] cols = Physics.OverlapSphere(transform.position, explotionRadius, enemyLayers);
    
    	//炮弹仅对敌人阵营(敌人所在图层)造成伤害
    }
    
    //机理概述:
    //1. 通过传入坦克自身所在阵营信息如蓝方阵营到GetEnemyLayer(),得到敌人红绿阵营的 layermask 并设置为 enemyLayers
    //2. 我们在发射出的炮弹的脚本中就通过该 enemyLayers 限制了仅能检测到敌方layer层的碰撞体
    //3. 实现炮弹对敌伤害而友军安全
    

    LayerToName / NameToLayer

    函数原型:public static string LayerToName(int layer)public static int NameToLayer(string layerName)

    功能:将索引值k转换为第k层的名称、将第k层的名称转换为k索引值

    示例:

    Debug.Log(LayerMask.NameToLayer("Blue"));	-->10
    Debug.Log(LayerMask.LayerToName(10));	    -->Blue
    
    //检测物体是否在某Layer
    if (gameObject.layer == LayerMask.NameToLayer("Default"))
    	Debug.Log("Yes!");
    

    总述

    LayerMask是Unity中 操控Layer层的类,我们在使用时需要注意数据类型转换,其用法常体现在物理检测、射线检测

    关于射线检测可移步博主拙作:Unity射线检测 - SouthBegonia

    参考

  • 相关阅读:
    HashMap扩容后是否需要rehash?
    为什么我们在定义HashMap的时候,就指定它的初始化大小呢
    HashMap是如何进行扩容的?
    【华为云技术分享】如何使用pyCharm与ModelArts公有云服务联动开发,快速且充分地利用云端GPU计算资源
    数据库“意外失联”?华为云DRS异地多活灾备为您支招
    【华为云技术分享】为什么说物联网平台是城市数字化的必备底座
    【华为云技术分享】HBase与AI/用户画像/推荐系统的结合:CloudTable标签索引特性介绍
    【华为云技术分享】云小课 | WAF反爬虫“三板斧”:轻松应对网站恶意爬虫
    【华为云技术分享】云小课 | 迁移第三方云厂商数据至OBS,两种方式任你选
    【华为云技术分享】网络场景AI模型训练效率实践
  • 原文地址:https://www.cnblogs.com/SouthBegonia/p/11861083.html
Copyright © 2011-2022 走看看