当前位置: 首页 > news >正文

Unity 开发注意事项

1. 空Unity消息

        Unity消息被运行时事件调用,即使消息体为空也会被调用。因此,删除空消息避免不必要的处理。

例如:

using UnityEngine;class Camera : MonoBehaviour
{private void FixedUpdate(){}private void Foo(){}
}

应该删除未使用的 FixedUpdate 方法。

2. 标签比较效率低下

       使用“==”进行标签比较效率要比使用内置的“CompareTag ”方法比较的效率低,所以尽量使用“CompareTag ”进行标签比较。

例如:

using UnityEngine;public class Camera : MonoBehaviour
{private void Update(){Debug.Log(tag == ""tag1"");}
}改为:using UnityEngine;public class Camera : MonoBehaviour
{private void Update(){Debug.Log(CompareTag(""tag1""));}
}

3. 非通用GetComponent的用法

        为了类型安全,首选使用GetComponent、TryGetComponent、GetComponents、GetComponentInChildren、GetComponentsInChildren、GetComponentInParent和GetComponentsInParent的泛型形式。

例如:

using UnityEngine;class Camera : MonoBehaviour
{private Rigidbody rb;private void Start(){rb = GetComponent(typeof(Rigidbody)) as Rigidbody;}
}改为:using UnityEngine;class Camera : MonoBehaviour
{private Rigidbody rb;private void Start(){rb = GetComponent<Rigidbody>();}
}

4. Time.fixedDeltaTime 和 Update 一起使用时

        Update 是依赖于帧率的,在Update中 应该用 Time.deltaTime 而不是用 Time.fixedDeltaTime。

         同理,FixedUpdate 不依赖帧率,在 FixedUpdate 中 应该用Time.fixedDeltaTime而不是 Time.deltaTime。

5. Unity对象上的空合并

        Unity 重写了Unity对象的null比较运算符,因此,不要对Unity对象使用null合并运算符(??),同理,也不要对Unity 对象使用null传递运算符(?.),is not null 也是不允许的,

他们是不兼容的。

例如:

例1:
using UnityEngine;class Camera : MonoBehaviour
{public Transform a;public Transform b;public Transform NC(){return a ?? b;}
}改为:using UnityEngine;class Camera : MonoBehaviour
{public Transform a;public Transform b;public Transform NC(){return a != null ? a : b;}
}例2:using UnityEngine;class Camera : MonoBehaviour
{public Transform NP(){return transform?.transform;}
}改为:using UnityEngine;class Camera : MonoBehaviour
{public Transform NP(){return transform != null ? transform : null;}
}例3:using UnityEngine;class Camera : MonoBehaviour
{public Transform a = null;public void Update(){if (a is not null) { }}
}改为:using UnityEngine;class Camera : MonoBehaviour
{public Transform a = null;public void Update(){if (a != null) { }}
}

6. 缺少InitializeOnLoad的静态构造函数

        在类上使用 InitializeOnLoad 属性标记的时候,应该提供静态的构造函数,它将在编辑器启动的时候调用。

using UnityEngine;
using UnityEditor;[InitializeOnLoad]
class Camera : MonoBehaviour
{
}改为:using UnityEngine;
using UnityEditor;[InitializeOnLoad]
class Camera : MonoBehaviour
{static Camera(){}
}

7. 组件实例创建

        组件实例创建时应该使用 AddComponent() 方法将组件添加到一个物体上,而不是使用 new 来创建实例。

using UnityEngine;class Foo : MonoBehaviour { }class Camera : MonoBehaviour
{public void Update() {Foo foo = new Foo();}
}改为:using UnityEngine;class Foo : MonoBehaviour { }class Camera : MonoBehaviour
{public void Update() {Foo foo = gameObject.AddComponent<Foo>();}
}

8. ScriptableObject 实例的创建

        使用  CreateInstance()  方法创建 ScriptableObject 的实例,而不是使用new。

using UnityEngine;class Foo : ScriptableObject { }class Camera : MonoBehaviour
{public void Update() {Foo foo = new Foo();}
}改为:using UnityEngine;class Foo : ScriptableObject { }class Camera : MonoBehaviour
{public void Update() {Foo foo = ScriptableObject.CreateInstance<Foo>();}
}

9. SerializeField 属性无效或冗余

        SerializeField 属性对于公共字段是多余的,对于属性或静态/只读字段无效。与 SerializeReference 不同,编译器允许您在属性上使用 SerializeField 属性,即使该属性无效且无法在 Unity 编辑器中运行。

using System.Collections;
using UnityEngine;public class SerializedAttributes : MonoBehaviour
{[SerializeField] // correct usageprivate string privateField;[SerializeField] // redundant usagepublic string publicField;[SerializeField] // invalid usageprivate string PrivateProperty { get; set; }[SerializeField] // invalid usagestatic string staticField;[SerializeField] // invalid usagereadonly field readonlyField;
}改为:using System.Collections;
using UnityEngine;public class SerializedAttributes : MonoBehaviour
{[SerializeField] // correct usageprivate string privateField;public string publicField;private string PrivateProperty { get; set; }static string staticField;readonly field readonlyField;
}

10. InitializeOnLoadMethod、RuntimeInitializeOnLoadMethod 或 DidReloadScripts 属性的方法签名不正确

InitializeOnLoadMethod、RuntimeInitializeOnLoadMethod 或 DidReloadScripts 修饰的方法或者属性必须是无参的,否则,Unity 不会调用它或抛出 NullReferenceException。

using UnityEditor;class Loader
{[InitializeOnLoadMethod]private void OnLoad(int foo, string bar) {}
}改为:using UnityEditor;class Loader
{[InitializeOnLoadMethod]private static void OnLoad() {}
}

11.  获取方法名称的不安全方式

        使用InvokeInvokeRepeatingCancelInvokeStartCoroutineStopCoroutine第一个参数是字符串文字不是类型安全的。相反,建议使用nameof运算符或直接调用协程。这样做的另一个好处是该方法能够使用重命名重构,而无需记住更新字符串文字。

using UnityEngine;
using System.Collections;class Camera : MonoBehaviour
{void Start(){Invoke("InvokeMe", 10.0f)StartCoroutine("MyCoroutine");}private void InvokeMe(){// ...}private IEnumerator MyCoroutine(){// ...}
}改为:using UnityEngine;
using System.Collections;class Camera : MonoBehaviour
{void Start(){Invoke(nameof(InvokeMe), 10.0f)StartCoroutine(MyCoroutine());}private void InvokeMe(){// ...}private IEnumerator MyCoroutine(){// ...}
}

12. SetPixels 调用很慢

Unity 对 RGBA 颜色使用两种不同的表示形式:

  • Color:每个颜色分量都是一个浮点值,范围从 0 到 1。(这种格式在所有显卡和着色器内部使用)。
  • Color32:每个颜色分量都是一个字节值,范围从 0 到 255。(32 位 RGBA)。

Color32速度更快,内存使用量减少 4 倍。ColorColor32可以隐式地相互转换。

SetPixels相比,SetPixels32速度更快并且使用更少的内存。

using UnityEngine;public class ExampleClass : MonoBehaviour
{void Start(){Renderer rend = GetComponent<Renderer>();Texture2D texture = Instantiate(rend.material.mainTexture) as Texture2D;rend.material.mainTexture = texture;// ...Color[] colors = new Color[3];colors[0] = Color.red;colors[1] = Color.green;colors[2] = Color.blue;texture.SetPixels(colors);// ...}
}

        上例中,如果 32 位 RGBA 与您的场景兼容,请改用SetPixels32

13. 在关键信息中,System.Reflection 特性的性能

        不要在关键消息如 UpdateFixedUpdateLateUpdate, or OnGUI中使用System.Reflection,System.Reflection会很慢可能导致滞后。

        如果一定要使用 System.Reflection,可以在Start()或者 Awake()中缓存一个变量,然后在关键信息中使用缓存的变量。

14. 对 GameObject.gameObject 进行不必要的间接调用

        Unity GameObject有一个gameObject的属性,它会返回 ​​​​​​​thisGameObject.gameObject.gameObject这样类似的调用是多余的,并且会影响性​​能。

15. 设置位置和旋转效率低下

        出于性能原因考虑,Transform/TransformAccess应该尽可能少的访问,如果需要依次设置Postion和Rotation,可以使用 SetPositionAndRotation() 方法代替。同样依次设置localPosition和localRotation,也可以用SetLocalPositionAndRotation()方法代替。

        相反,如果依次获取position和Rotation,也可以用GetPositionAndRotation()方法代替。Local 同理。

using UnityEngine;class Camera : MonoBehaviour
{void Update(){transform.position = new Vector3(0.0f, 1.0f, 0.0f);transform.rotation = transform.rotation;}
}改为:using UnityEngine;class Camera : MonoBehaviour
{void Update(){transform.SetPositionAndRotation(new Vector3(0.0f, 1.0f, 0.0f), transform.rotation);}
}

16. 标量计算优先于矢量计算

        在紧密循环或性能关键部分中工作时,请记住标量数学比向量数学更快。因此,只要交换或关联算术允许,就尝试最小化各个数学运算的成本。您可以在这里查看Unity 网站上的相关文档。

using UnityEngine;class Camera : MonoBehaviour
{public void Compute(){Vector3 x;float a, b;Vector3 slow = a * x * b;}
}改为:using UnityEngine;class Camera : MonoBehaviour
{public void Compute(){Vector3 x;float a, b;Vector3 fast = a * b * x;}
}

17.  GetComponent  总是分配

  Component.TryGetComponent或者GameObject.TryGetComponent将尝试检索给定类型的组件。与 GetComponent相比,最大的区别是,当请求的组件不存在时,此方法不会分配。也就是说,如果确定类型存在可以使用GetComponent 获取组件,如果可能获取不到类型,尽量使用TryGetComponent来获取组件。

using UnityEngine;class Camera : MonoBehaviour
{public void Update() {var rb = gameObject.GetComponent<Rigidbody>();if (rb != null) {Debug.Log(rb.name);}}
}改为:using UnityEngine;class Camera : MonoBehaviour
{public void Update() {if (gameObject.TryGetComponent<Rigidbody>(out var rb)) {Debug.Log(rb.name);}}
}

18.  使用非分配物理 API

        引入了物理查询 API 的非分配版本。您可以将RaycastAll调用替换为RaycastNonAlloc,将SphereCastAll调用替换为SphereCastNonAlloc,等等。您可以重复使用预先分配的数组来存储结果,而不是为每个调用分配一个新数组。这将提高性能,特别是对于频繁的调用。

using UnityEngine;class Camera : MonoBehaviour
{void Update() {var result = Physics.RaycastAll(Vector3.zero, Vector3.zero);// ...result = Physics.RaycastAll(Vector3.zero, Vector3.zero);}
}

 

        

相关文章:

Unity 开发注意事项

1. 空Unity消息 Unity消息被运行时事件调用&#xff0c;即使消息体为空也会被调用。因此&#xff0c;删除空消息避免不必要的处理。 例如&#xff1a; using UnityEngine;class Camera : MonoBehaviour {private void FixedUpdate(){}private void Foo(){} } 应该删除未使用…...

[Unity Sentis] Unity Sentis 详细步骤工作流程

文章目录 1. 导入模型文件支持的模型创建运行时模型导入错误 2. 为模型创建输入将数组转换为张量创建多个输入进行操作 3. 创建一个引擎来运行模型创建一个Worker后端类型 4. 运行模型5. 获取模型的输出获取张量输出多个输出打印输出 1. 导入模型文件 要导入 ONNX 模型文件&am…...

力扣144 二叉树的前序遍历 Java版本

文章目录 题目描述递归方法代码 非递归方法代码 题目描述 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xf…...

《Vue3 基础知识》 使用 GoGoCod 升级到Vue3+ElementPlus 适配处理

此篇为 《Vue2ElementUI 自动转 Vue3ElementPlus&#xff08;GoGoCode&#xff09;》 的扩展&#xff01; Vue3 适配 Vue3 不兼容适配 Vue 3 迁移指南 在此&#xff0c;本章只讲述项目或组件库中遇到的问题&#xff1b; Vue3 移除 o n &#xff0c; on&#xff0c; on&#…...

c#string方法对比

字符串的截取匹配操作在开发中非常常见&#xff0c;比如下面这个示例&#xff1a;我要匹配查找出来字符串数组中以“abc”开头的字符串并打印&#xff0c;我下面分别用了两种方式实现&#xff0c;代码如下&#xff1a; using System; namespace ConsoleApp23{ class Progra…...

Electron实战(一):环境搭建/Hello World/打包exe

文章目录 Electron安装Node.jsNodeJs推荐配置开始Electron项目创建index.js文件创建src目录运行打包生成exe生成安装包踩坑 下一篇Electron实战(二)&#xff1a;将Node.js和UI能力&#xff08;app/BrowserWindow/dialog)等注入html Electron Electron是一个使用JavaScript, HT…...

【C++】运算符重载详解

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 1. 为什么需要运算符重载 2. 运算符重载概念 3. 运算符重载示例 3.1 运算符重载 3.2 >或<运算符 4. 运算符重…...

评论区功能的简单实现思路

评论区功能是社交类项目中的核心组成部分&#xff0c;它涉及到前端的交云和后端的数据处理。基于你的技术栈&#xff08;前端 Vue3&#xff0c;后端 Java&#xff09;&#xff0c;下面是一个具体的实现思路和数据库设计建议&#xff0c;并探索一下知乎的评论系统。 数据库设计…...

Java自救手册

目录 访问地址 访问地址&#xff0c;发现不通&#xff0c;无法访问&#xff1a; 网络不通一般有两种情况&#xff1a; Maven 拿Maven 拿到Maven以后 Maven单独的报红 Git git注意&#xff1a; 目录 访问地址 访问地址&#xff0c;发现不通&#xff0c;无法访问&…...

ASM-HEMT参数提取和模型验证测试

参数提取程序 直流I-V参数提取 DC模型参数提取流程对于ASM-GaN-HEMT模型可以总结在下图中。 以下步骤描述了该流程&#xff1a; 在模型中设置物理参数&#xff0c;如L&#xff08;沟道长度&#xff09;、W&#xff08;沟道宽度&#xff09;、NF&#xff08;栅指数&#xf…...

浅压缩、深压缩、双引擎、计算机屏幕编码……何去何从?

专业视听领域尤其显示控制和坐席控制领域&#xff0c;最近几年最激动人心的技术&#xff0c;莫过于分布式了。 分布式从推出之日就备受关注&#xff1a;担心稳定性的&#xff0c;质疑同步性能的&#xff0c;怀疑画面质量的…… 诚然&#xff0c;我们在此前见多了带着马赛克的…...

2020年通信工程师初级专业实务真题

文章目录 一、第1章 现代通信网概述&#xff1a;信令网、同步网、管理网。第10章 通信业务&#xff1a;通信产业链&#xff0c;通信终端的分类&#xff0c;通信业务的定义及分类二、第3章 接入网&#xff1a;无线接入网的优点&#xff0c;接入网的接口&#xff08;UNI&#xff…...

Linux常见面试题汇总

Linux上如何查询某个端口是否被占用&#xff1f; 在Linux上&#xff0c;你可以使用以下几种方法来查询某个端口是否被占用&#xff1a; 使用netstat命令&#xff1a; netstat -tuln | grep <端口号>这个命令会列出当前正在运行的所有TCP和UDP端口&#xff0c;并过滤出指…...

C语言小游戏:贪吃蛇(游戏开发的环境和功能介绍)

❀❀❀ 文章由不准备秃的大伟原创 ❀❀❀ ♪♪♪ 若有转载&#xff0c;请联系博主哦~ ♪♪♪ ❤❤❤ 致力学好编程的宝藏博主&#xff0c;代码兴国&#xff01;❤❤❤ 生命不停&#xff0c;学习不止。铁汁们&#xff0c;我是大伟&#xff0c;欢迎来到大伟的游戏时间&#xff0c…...

ElementUI Form:InputNumber 计数器

ElementUI安装与使用指南 InputNumber 计数器 点击下载learnelementuispringboot项目源码 效果图 el-radio.vue &#xff08;InputNumber 计数器&#xff09;页面效果图 项目里el-input-number.vue代码 <script> export default {name: el_input_number,data() {re…...

apk反编译修改教程系列---修改apk的默认颜色 布局颜色 手机电脑同步演示【十】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…...

响应式开发如何设置断点,小屏幕界面该如何显示(有动图)

Hi&#xff0c;我是贝格前端工场&#xff0c;本期分享响应式开发&#xff0c;如何设置屏幕断点&#xff0c;pc页面布局到了移动端之后该如何布局的问题&#xff0c;微软也提供了设置屏幕断点的动图演示&#xff0c;非常直观。 一、什么是响应式开发&#xff0c;为何要设置屏幕断…...

Java基础 集合(二)List详解

目录 简介 数组与集合的区别如下&#xff1a; 介绍 AbstractList 和 AbstractSequentialList Vector 替代方案 Stack ArrayList LinkedList 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界…...

UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十七&#xff09;&#xff08;第51~54集&#xff09; 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…...

GaussDB新体验,新零售选品升级注入新思路【华为云GaussDB:与数据库同行的日子】

选品思维&#xff1a;低频VS高频 一个的商超&#xff0c;假设有50个左右的品类&#xff0c;每个品类下有2到10个不等的商品。然而如此庞大的商品&#xff0c;并非所有都是高频消费品。 结合自身日常的消费习惯&#xff0c;对于高频和低频的区分并不难。一般大型家电、高端礼盒…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...