Unity优化篇 | Unity脚本代码优化策略,快速获取 游戏对象 和 组件 的方法文末送书
Posted 呆呆敲代码的小Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity优化篇 | Unity脚本代码优化策略,快速获取 游戏对象 和 组件 的方法文末送书相关的知识,希望对你有一定的参考价值。
- 🎬 博客主页:https://xiaoy.blog.csdn.net
- 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉
- 🎄 学习专栏推荐:Unity系统学习专栏
- 🌲 游戏制作专栏推荐:游戏制作专栏
- 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📆 未来很长,值得我们全力奔赴更美好的生活✨
📢前言
- 本文是 Unity优化篇 系列的一篇文章,同时也包是含在 『Unity系统学习专栏⭐️』里的文章。
- 本专栏是我总结的Unity学习类的文章,适合Unity入门和进阶的小伙伴。
- 订阅该专栏之后
Unity基础知识学习
、Unity 进阶技巧
、Unity 优化 篇
几个专栏的文章都可以查看。 - 对Unity感兴趣的小伙伴千万不要错过哦,目前专栏正在优惠中,具体内容可以看该专栏的导航帖。
- 本篇文章就来讲一下 Unity中的脚本代码优化策略,一起来学习一下吧!
🎬Unity脚本代码优化策略
上一篇文章中介绍了 Unity中的优化概念
和 Unity自带的性能分析工具Profiler
以及 性能分析的方法
在看完这篇文章之后应该对Unity中的优化有了一个大概的观念。
那接下来就是来看优化中最常用的 脚本代码优化 了。
编写脚本会占据大量的开发时间,而且脚本编写是一个含义宽泛的术语。
所以本系列只限于Unity相关的脚本,包括MonoBehaviour
、GameObject
和 相关功能的问题。
大概内容如下所示:
获取游戏对象、访问组件、空引用快速检索、协程、GameObject 和 Transform的使用 、使用合适的数据结构、游戏对象间通信、数学计算、合理反序列化行为等。
下面就来挨着学习一下相关内容。
📒获取游戏对象的方法
在Unity中获取游戏对象是经常会用到的。
我们要 获取某些游戏对象 对其进行一些逻辑处理 或者 拿到该游戏对象身上的某些组件进行某些处理。
而且在Unity中获取游戏对象的方法有很多种,下面一起来看一下。
- GameObject.Find() 通过对象名称(Find方法)
- Transform.Find() 通过对象名称(Find方法)
- GameObject.FindWithTag 通过标签获取单个游戏对象(FindWithTag方法)
- GameObject.FindGameObjectWithTag() 通过标签获取单个游戏对象(FindGameObjectWithTag方法)
- Transform.FindObjectOfType() 通过类型获取单个游戏对象(FindObjectOfType方法)
- Transform.FindObjectsOfType() 通过类型获取多个游戏对象(FindObjectsOfType方法)
- transform.GetChild() 通过索引获取单个游戏对象
- 通过 Public 声明对象,从检查器面板上手动拖拽获取
Unity中查找获取游戏对象的方法应该都在这里了,下面简单来介绍下这几种方法。
🏳️🌈GameObject.Find()
GameObject.Find()
通过对象名称(Find方法)
该方法通过输入对象名称的方式获取对应的游戏对象
static GameObject Find (string name )
使用示例如下:
// 找对象
GameObject parent = GameObject.Find("GameObject/ObjectName");
特点:
- 全局查找参数名称游戏物体;
- 不对禁用(隐藏)物体进行查找;
- 若有同名物体时根据层级关系进行查找。
🏳️🌈Transform.Find()
Transform.Find()
通过对象名称(Find方法)
该方法也是通过输入对象名称的方式获取对应的游戏对象
与GameObject.Find()
使用方法一致,不过也是有区别的
具体请看这篇【100个 Unity小知识点】 | Unity两种获取游戏对象的方法,GameObject.Find 和 Transform.Find区别
public Transform Find(string name);
使用示例:
// 找对象
Transform parent = transform.Find("Root/ObjectName");
特点:
- 只能找其子物体,不能找其同级或更高层级物体
- 找子物体时不考虑是否被禁用(隐藏)
- 找多层子物体时需写全路径(否则即使存在也找不到)
🏳️🌈GameObject.FindWithTag()
GameObject.FindWithTag()
通过标签获取单个游戏对象(FindWithTag方法)
返回一个用tag做标识的活动的对象,如果没有找到则为null。
static GameObject FindWithTag (string tag)
使用示例:
GameObject p1= GameObject.FindWithTag("player1");
if (null != p1)
Debug.Log("p1!");
Tag标签
可以在面板上进行 添加和复制,先选中游戏对象然后进行操作。
特点:
- 查找不到禁用物体,使用时需确认要查找的物体是启用(显示)状态;
- 有多个有游戏物体使用同一标签时,尽量不使用
FindWithTag
此方式查找单一游戏体,因为查找顺序会受到层级影响; - 查找未定义标签会报错,使用时需确认查找的字符串是已定义的标签;
- 查找的标签是已定义但是未使用过,会找不到游戏物体,返回空值。
🏳️🌈GameObject.FindGameObjectWithTag()
FindGameObjectWithTag()
通过标签获取单个游戏对象(FindGameObjectWithTag方法)
FindGameObjectWithTag
和 上面的FindWithTag
用法一致,功能也是一样的
他俩的具体区别我暂时没有发现,如果知道的小伙伴欢迎评论区告诉我呀!
public static GameObject FindGameObjectWithTag(string tag);
🏳️🌈Transform.FindGameObjectsWithTag()
Transform.FindObjectsOfType()
通过类型获取多个游戏对象(FindObjectsOfType方法)
public static GameObject[] FindGameObjectsWithTag(string tag);
返回一个用tag做标识的活动的游戏物体的列表
上面说了一下Transform.FindObjectOfType()
方法,与这个 Transform.FindObjectsOfType()
的方法使用起来也是一样的。
只不过该方法可以根据 标签 查找当前场景中 所有这个标签的游戏物体
并返回所有物体的数组。
所以他们的区别就是一次性 获取单个符合要求的游戏对象 和 获取多个游戏对象。
要注意的是Transform.FindObjectsOfType()
返回的是一个游戏对象的数组,找不到则返回null
🏳️🌈GameObject.FindObjectOfType()
Transform.FindObjectOfType()
通过类型获取单个游戏对象(FindObjectOfType方法)
public static T FindObjectOfType<T>() where T : Object;
返回类型为type的活动的第一个游戏对象
使用示例:
Camera c1 = GameObject.FindObjectOfType<Camera>();
Debug.Log("游戏对象c1:" + c1);
特点:
- 查找不到禁用物体,使用时需确认要查找的物体是启用(显示)状态;
- 查找场景中不存在类型时会返回null,不会报错;
🏳️🌈GameObject.FindObjectsOfType()
Transform.FindObjectsOfType()
通过类型获取多个游戏对象(FindObjectsOfType方法)
public static T[] FindObjectsOfType<T>() where T : Object;
该方法和上面的方法使用方式一样,只不过返回的是一个该类型的数组
使用示例:
Camera[] c2 = Transform.FindObjectOfType<Camera>();
Debug.Log("游戏对象c2:" + c2);
🏳️🌈transform.GetChild()
transform.GetChild()
通过索引获取单个游戏对象
public Transform GetChild(int index);
使用实例:
//找一级子物体的第一个物体
Transform child1 = transform.GetChild(0);
使用方式:几个层级就几个GetChild(),参数就是当前层级的第几个物体(从0开始)
特点:
- 以自身为基础,查找子物体(注意索引从0开始,写多报错)
- 可以使用transform.parent.parent 的形式无限向上,然后再GetChild(),就达到了查找父层级或更高层级物体的目的
- 弊端是依赖游戏物体的层级关系,使用时需确保层级关系相对稳定。若不稳定会导致每次修改游戏体时还要修改代码,这就加大了工作量了。
🏳️🌈通过 Public 声明对象,从检查器面板上手动拖拽获取
在Unity中除了上面的几种通过代码获取游戏对象的方法之外。
还有一种很常用的方式来获取游戏对象或者组件,那就是使用Public修饰符来声明对象。
public GameObject _g1;
public Button _button1;
这种方式在我们日常开发的时候也可以使用,因为直观方便还不用多写代码就可以直接获取对象。
网上对比最多的就是 Public
和 Transform.Find
的方式哪种更消耗性能。
在我查阅了一些资料之后并没有看到有关于这块很详细的资料,简单测试发现这两种性能消耗的差异不大。
所以说还是要看平时个人的代码规范 和 项目要求 来选择使用哪种方式。
整理了以上几个获取对象的方法,各有特点。
但是我通常使用的就是Transform.Find()
,该方法可以获取到非激活状态的游戏对象,性能消耗也不高。
获取游戏对象部分 参考了 陈言必行
大佬 的这篇博客https://czhenya.blog.csdn.net/article/details/117530824
可以去这篇博客查看更详细的实例方法,获取游戏对象的方法这里就简单介绍到这,下面看一下获取组件的最佳方法。
📒获取组件的最佳方法
上面说完了获取游戏对象的几种方法,接下来再来讲一下获取组件的最快方法。
在Unity中获取组件的方法也有几种,下面一起来看一下。
获取组件的方法主要是使用 GetComponent()
方法,但是 GetComponent()
有一些变体,他们性能消耗有所不同。
- GetComponent(string)
- GetComponent()
- GetComponent(typeof(T))
public Component GetComponent(string type);
public T GetComponent<T>();
public Component GetComponent(Type type);
主要是通过这三个变体方法来获取组件
根据上百万次测试发现 GetComponent<T>()
和 GetComponent(typeof(T))
方法性能差异不大。
但是 GetComponent(string)
方法则比上面两种方法慢的多。
所以说正常情况下尽量不使用 GetComponent(string)
方法即可
大多数情况下还是使用 GetComponent<T>()
比较多,平时都在使用这个方法获取组件。
使用示例:
Demo1 _demo1;
_demo1 = transform.GetComponent<Demo1>();
_demo1 = (Demo1)transform.GetComponent("Demo1");
_demo1 = (Demo1)transform.GetComponent(typeof(Demo1));
📒移除空的回调定义
Unity中编写脚本的主要意义是从 MonoBehaviour
继承的类中编写回调函数,然后Unity会在必要时进行调用。
一般来说最常用的四个回调是 Awake()
、Start()
、Update()
、FixedUpdate()
我们在创建一个新脚本的时候默认会帮我们添加两个回调 Awake()
和 Update()
关于 Awake()
和 Update()
方法的意义就不多做讲解了,看优化篇的应该都知道是干嘛用的。
Awake()
主要是在程序运行的第一帧进行调用,而Update()
则是在每一帧都会进行调用。
MonoBehaviour
在场景中第一次实例化的时候,Unity会将任何定义好的回调添加到一个函数指针列表中,他会在关键时刻调用这个列表。
即使我们在Awake()
和 Update()
中并没有写任何的方法,Unity也会挂接到这些回调中。
核心Unity引擎可能没有意识到这些函数体是空的,由于引擎调用他们的开销就会浪费少量的CPU。
但是我们每当在Unity中创建一个MonoBehaviour
脚本的时候,都会添加这两个回调。
所以说一旦项目偏大,脚本偏多,功能比较复杂之后,因为这个原因造成的性能浪费是没有任何收益的。
所以未使用的回调一定要直接删除掉,防止不必要的浪费。
下面使用3000个组件进行的测试实例,都带有Update
的回调,左边是未激活组件的状态,右边则是激活组件之后的状态。
可以看出CPU使用情况的差异还是很大的,所以移除空的回调很有必要。
💬总结
- 本文对 获取 游戏对象 和 组件 的方法进行了一个较详细的说明
- 还包括 空的回调定义 造成的影响,当项目越大时浪费的性能则越多。
- 关于脚本代码优化策略的内容还有一些,等下一篇博客在接着进行学习介绍。
- 本篇文章就先讲到这里,后续的Unity脚本代码优化策略会继续更新。
🚀往期优质文章分享
- ❤️Unity零基础到入门 | 游戏引擎 Unity 从0到1的 系统学习 路线【全面总结-建议收藏】!
- 🧡花一天时间做一个高质量飞机大战游戏,过万字Unity完整教程!漂亮学妹看了直呼666!
- 💛通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难
- 💚重回童年的经典系列☀️|【贪吃蛇小游戏】近两万字完整制作过程+解析+源码 【建议收藏学习】
- 🤍重回童年的经典系列☀️| 【皇室战争 】 的 即时战斗类 复刻游戏Demo!两万多字游戏制作过程+解析!
- 💙重回童年的经典系列☀️| 【横版街机格斗游戏】类似“恐龙快打” 该如何制作? | 一起来学习 顺便送源码【建议收藏学习】
- 💜重回童年的经典系列☀️|【炸弹人小游戏】制作过程+解析 | 收藏起来跟曾经的小伙伴一起梦回童年!
🚀 优质专栏分享 🚀 |
- 🎄如果感觉文章看完了不过瘾,可以来我的其他 专栏 看一下哦~
- 🎄比如以下几个专栏:Unity基础知识学习专栏、Unity游戏制作专栏、Unity实战类项目 和 算法学习专栏
- 🎄可以学习更多的关于Unity引擎的相关内容哦!直接点击下面颜色字体就可以跳转啦!
【游戏开发爱好者社区】活动进行中,每周打卡送书籍等礼品,期待你的加入
🚀 社区活动,重磅来袭 🚀 |
【游戏开发爱好者社区】在本周重磅新推出【每日打卡】活动
🎁 新玩法,奖励升级!游戏开发爱好者社区:https://bbs.csdn.net/forums/unitygame
社区中心思想:今天你学到了什么?
在社区你可以做些什么: 每日强化知识点,白嫖书籍礼品!
一个人可以走的很快,一群人才能走的更远!🔥爆C站的游戏开发爱好者社区欢迎您的加入!
更多白嫖活动详情:https://bbs.csdn.net/forums/unitygame?typeId=19603
👑评论区抽奖送书
最后在评论区进行抽取三名幸运的小伙伴
送下面这本书籍
-
这次博主多方联系,最终在
清华出版社
搞到了一些unity 相关的书籍,在这里搞个小活动抽奖送给大家,对看书感兴趣的小伙伴可以参加一波呀,刚开始可能参与的不多,抽中概率很大哦! -
《C#实践入门(快捷学习C#编程和Unity游戏开发第4版.NET开发经典名著) 》
-
一本非常经典的C#编程名著,结合Unity开发使用效果卓佳!
-
尤其是想从事Unity开发刚入门的小伙伴,没必要去买专门的C#书籍,这本书就可以让你了解Unity用到的C#相关知识,对症下药可以极大地提高学习效率!
🎁抽奖规则
规则如下:
🚀 规则如下🚀 |
-
给本篇博客文章
点赞
收藏
评论
三连,然后在评论区评论里点赞数 排名前五的评论抽取三个
小伙伴!送一本Unity的书籍! -
总共
抽三本
,中的几率还是很大的哦~ 想看书的小伙伴参与起来! -
中奖信息
明天下午本篇文章评论区公布!记得留意呀! -
没抽到的,但是喜欢这本书的小伙伴也可以在网上自行购买哈,官方正品商店购买即可!
🚀 规则如上🚀 |
🎄推荐理由(⭐⭐⭐⭐⭐)
-
在如今的技术环境中学习编程无疑是一项艰巨的任务,尤其是当面对众多可选的编程语言时。幸运的是,《C#实践入门(快捷学习C#编程和Unity游戏开发第4版.NET开发经典名著) 》消除了充满不确定性的学习过程,为初学者指明了一条成为有竞争力的Unity程序员的捷径。
-
在本书中,你将首先学习编程的基本构成要素,涵盖从变量、方法、条件语句到类、面向对象编程在内的所有知识。打好基础后,你将开始探索Unity接口并创建C#脚本,进而将学到的知识转换为简单的游戏机制。
-
在整个学习过程中,你将掌握编程方面的最佳实践以及宏观的架构知识,例如游戏管理器与灵活的应用程序架构。等到本书结束时,你将对C#的一些中级主题了然于胸,例如泛型、委托、事件等,从而在自己的项目中加以灵活运用。
书本图片如下,喜欢的小伙伴参与起来!也可自行京东官网购买哦!
京东链接:https://item.jd.com/13263338.html
温馨提示: 点击下面卡片可以获取更多编程知识,包括各种语言学习资料,上千套PPT模板和各种游戏源码素材等等资料。更多内容可自行查看哦!
以上是关于Unity优化篇 | Unity脚本代码优化策略,快速获取 游戏对象 和 组件 的方法文末送书的主要内容,如果未能解决你的问题,请参考以下文章
Unity 优化篇 | 优化专栏《导航帖》,全面学习Unity优化技巧,让我们的Unity技术上升一个档次
Unity 优化篇 | 优化专栏《导航帖》,全面学习Unity优化技巧,让我们的Unity技术上升一个档次
Unity优化篇| Unity3D场景 常用优化策略,遮挡剔除层消隐距离技术 和 LOD多层次细节