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);}
}

 

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MQ,RabbitMQ,SpringAMQP的原理与实操

MQ 同步通信 异步通信 事件驱动优势&#xff1a; 服务解耦 性能提升&#xff0c;吞吐量提高 服务没有强依赖&#xff0c;不担心级联失败问题 流量消峰 ​ 小结: 大多情况对时效性要求较高&#xff0c;所有大多数时间用同步。而如果不需要对方的结果&#xff0c;且吞吐…

性能实测:分布式存储 ZBS 与集中式存储 HDS 在 Oracle 数据库场景表现如何

作者&#xff1a;深耕行业的 SmartX 金融团队 金鑫 在金融客户的基础架构环境中&#xff0c;HDS 是一种被广泛使用的存储解决方案。作为集中式存储的代表之一&#xff0c;HDS 拥有高性能、高可用性和可扩展性的企业级存储特点&#xff0c;适用于实时数据处理、虚拟化和灾难备份…

Python 潮流周刊#38:Django + Next.js 构建全栈项目

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 你好&#xff0c;我是猫哥。这里每周分享优质的 Python、AI 及通用技术内容&#xff0c;大部分为英文。本周刊开源&#xff0c;欢迎投稿[1]。另有电报频道[2]作为副刊&#xff0c;补充发布更加丰富的资讯&#xff0c;…

开源软件全景解析:驱动技术创新与行业革新的力量

目录 什么是开源 开源的核心 开源软件的特点 为什么程序员应该拥抱开源 1.学习机会&#xff1a; 2.社区支持&#xff1a; 3.提高职业竞争力&#xff1a; 4.加速开发过程&#xff1a; 5.贡献和回馈&#xff1a; 开源软件的影响力 开源软件多元分析&#xff1a; 开源…

蓝桥杯刷题day06——平均

1、题目描述 有一个长度为n 的数组&#xff08;n 是 10 的倍数&#xff09;&#xff0c;每个数ai都是区间 [0,9] 中的整数。 小明发现数组里每种数出现的次数不太平均&#xff0c;而更改第i 个数的代价为bi&#xff0c; 他想更改若干个数的值使得这10 种数出现的次数相等&…

YOLOv8改进 | 检测头篇 | 重参数化检测头RepHead解决困难样本检测(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是RepHead,该检测头为我独家全网首发,该检测头由重参数化模块组成,加大对于特征学习的能力,却可以不增加GFLOPs(仅仅略微提升)从而不影响模型的推理速度和性能,保持较高的FPS能力,牺牲了少量GFLOPs的情况下确提高了模型的特征提…

LeetCode--代码详解 292.Nim游戏

292.Nim游戏 题目 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。你们轮流进行自己的回合&#xff0c; 你作为先手 。每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。拿掉最后一块石头的人就是获胜者。 假设你们每一步都是最优解。请编写…

(2)(2.13) Rockblock Satellite Modem

文章目录 前言 1 支持的MAVLink命令信息 2 设置 3 使用方法 4 数据成本 5 参数 前言 &#xff01;Note 该功能仅适用于 ArduPilot 4.4 或更高版本&#xff0c;并且要求飞行控制器支持 LUA 脚本(LUA Scripts)。 RockBLOCK 卫星调制解调器可实现与 ArduPilot 飞行器的全球…

SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式 基础(持续更新~)

具体操作&#xff1a; day2: 作用&#xff1a; 出现跨域问题 配相对应进行配置即可解决&#xff1a; IDEA连接的&#xff0c;在url最后加参数?useSSLfalse注意链接密码是123&#xff08;docker中mysql密码&#xff09; 注意&#xff0c;虚拟机中设置的密码和ip要和主机上…

专业排版设计软件:QuarkXPress 2024 for mac中文激活版

QuarkXPress 2024 for Mac是一款功能强大、易于使用、高质量输出的专业排版软件。无论您是出版业的专家还是初学者&#xff0c;都可以通过QuarkXPress 2024轻松创建出令人惊叹的出版物。 软件下载&#xff1a;QuarkXPress 2024 for mac中文激活版下载 QuarkXPress 2023 for Mac…

Unity3d Cinemachine篇(完)— TargetGroup

文章目录 前言使用TargetGroup追随多个模型1. 创建二个游戏物体2. 创建TargetGroup相机3. 设置相机4. 完成 前言 上一期我们简单的使用了ClearShot相机&#xff0c;这次我们来使用一下TargetGroup 使用TargetGroup追随多个模型 1. 创建二个游戏物体 2. 创建TargetGroup相机 3…

vue 下载二进制文件

文章目录 概要技术细节 概要 vue 下载后端返回的二进制文件流 技术细节 import axios from "axios"; const baseUrl process.env.VUE_APP_BASE_API; //downLoadPdf("/pdf/download?pdfName" res .pdf, res); export function downLoadPdf(str, fil…

react-virtualized实现行元素不等高的虚拟列表滚动

前言&#xff1a; 当一个页面中需要接受接口返回的全部数据进行页面渲染时间&#xff0c;如果数据量比较庞大&#xff0c;前端在渲染dom的过程中需要花费时间&#xff0c;造成页面经常出现卡顿现象。 需求&#xff1a;通过虚拟加载&#xff0c;优化页面渲染速度 优点&#xff1…

rust嵌入式开发之RTICvsEmbassy

RTIC和Embassy是目前rust嵌入式开发中比较热门的两个框架。本来呢&#xff0c;针对RTIC的移植已经完成了一小半&#xff0c;但在移植过程中感受到了RTIC的不足&#xff0c;正好跳出来全面考察下embassy&#xff0c;本文就是根据目前的尝试结果做个对比总结。 RTIC和Embassy是两…

Codeforces Round 651 (Div. 2)C. Number Game 博弈 奇偶数 偶数的表示

Submission #244500083 - Codeforces 题目&#xff1a; 思路&#xff1a; 此题要从奇偶性上入手。&#xff08;注意除的是奇因数&#xff0c;即一个奇数。我想成质数了&#xff09; 1.当A选手开局是1时&#xff0c;A败。 2.当A选手开局是2和奇数时&#xff0c;A必胜。&…

Golang context 万字解析实现原理

Golang&#xff1a;context基于go1.21版本 Context 是什么Context 的功能应用场景源码分析1.10 Context核心结构1.1Err错误2 .1 emptyCtx 3.1 Background() 和 TODO()4.1.1 cancelCtx4.1.2 Deadline 方法4.1.2 Done 方法4.1.2 Err 方法4.1.2 Value 方法 4.2 WithCancel() 和 Wi…

vue2 el-table新增行内删除行内(两种写法)里面第一个是树组件,第二个是数字组件,第一个数组件只能勾选最后一个节点

第一种 <template><div class"time_table"><div style"margin-bottom: 10px"><el-button click"addRowFn">新增</el-button></div><el-form ref"costForm" :model"formData">&l…

备战蓝桥杯---搜索(剪枝)

何为剪枝&#xff0c;就是减少搜索树的大小。 它有什么作用呢&#xff1f; 1.改变搜索顺序。 2.最优化剪枝。 3.可行性剪枝。 首先&#xff0c;单纯的广搜是无法实现的&#xff0c;因为它存在来回跳的情况来拖时间。 于是我们可以用DFS&#xff0c;那我们如何剪枝呢&#…

Http请求Cookie失效问题

Http请求Cookie失效问题记录 一、问题现象 在开发功能的过程中&#xff0c;业务依赖cookie进行取之&#xff0c;项目进行交互时会对前端http请求携带的cookies进行解析操作&#xff0c;但在自测调试对过程中出现账户的授权失效的报错问题。 二、问题排查 用arthas进行代码方…

React16源码: React中event事件监听绑定的源码实现

event事件监听 1 &#xff09;概述 在 react-dom 代码初始化的时候&#xff0c;去注入了平台相关的事件插件接下去在react的更新过程绑定了事件的操作&#xff0c;在执行到 completeWork 的时候对于 HostComponent 会一开始就先去执行了 finalizeInitialChildren 这个方法位置…