自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(472)
  • 收藏
  • 关注

翻译 [C#] Foreach 循环还会产生垃圾吗?

虽然所有其他收集类型都没有改变它们产生的垃圾量,但至少它们使用的垃圾量都不比 Unity 5.2 中的垃圾量多。Dictionary、HashSet、LinkedList、Queue 和 Stack 现在在第一个循环上创建相同的 8 或 16 字节更少的垃圾,并在之后的任何循环上创建零垃圾。一年前,我写了一篇文章,标题为使用 Unity 5.2 进行 Foreach 循环创建垃圾,并使用各种集合测试了 foreach:列表、字典、数组等。所有代码和运行它的步骤仍然适用。

2024-04-23 15:58:00 31

翻译 [C#] C# String.Format() 和 StringBuilder

这很重要的原因是,在内部,String.Format() 实际上创建了一个 StringBuilder 并调用 StringBuilder.AppendFormat()!正如您所看到的,了解何时使用 String.Format 以及何时使用 StringBuilder.AppendFormat() 非常重要。而且,删除对 String.Format 的调用还可以提高性能。如果您试图避免通过使用 String.Format() 连接字符串来创建 StringBuilder,了解这一点也很重要。

2024-04-21 21:08:47 31

翻译 [C#] 何时在 .NET Core 中使用 String 与 StringBuilder

在 .NET Core 中处理字符串时,您会经常使用的两个流行类是 String 和 StringBuilder 类。在使用这两个类构建最小化分配且高性能的应用程序时,您应该了解最佳实践。本文讨论在 C# 中使用字符串时可以遵循的最佳实践。

2024-04-21 19:56:10 33

翻译 [C#] 从 Array 数据创建 ReadOnlySequence

在这篇文章中,我们进行了理论练习,并进一步了解了 ReadOnlySequence 类型。我保留对我的“SequenceReader 简介”博文中评论的最初回答。我认为我所展示的代码对于所提出的实际问题来说并不是一个明智的选择。然而,我喜欢这样的问题,因为它让我意识到,我实际上并没有考虑过 ReadOnlySequence 是如何创建的。通过小样本的调查,我更多地了解了这种类型的行为方式,我认为这是值得投入的时间。我希望您发现阅读这篇文章同样有用或至少有趣!

2024-04-21 15:38:20 35

翻译 [C#] SequenceReader 简介

可能值得首先解决这个问题,因为这是 .NET Core 中相当新的类型,并且您会遇到它的情况有限。不久前,添加了 Span 和 Memory 类型。它们都支持通过一致的 API 处理各种类型的连续内存区域。从那时起,许多新的构造都建立在这些类型提供的基础上。System.IO.Pipelines 就是一个这样的例子,它是一种用于处理 IO 的高性能 API。传统上,许多 IO 操作都使用流。流的一个问题是,它们让你负责管理缓冲区和在缓冲区之间复制数据。

2024-04-21 10:20:32 35

翻译 [C#] C# 索引和范围运算符解释

在这篇文章中,我们将最全面地揭开 C# 索引 ^ 和范围 … 运算符的神秘面纱。

2024-04-17 00:22:25 58

翻译 [Memory] 内存掌握:Unity 和 .NET 垃圾回收的比较

大家好,我叫 Dmitrii Ivashchenko,是 MY.GAMES 的软件工程师。在本文中,我们将讨论 Unity 和 .NET 中垃圾收集之间的差异。C# 编程语言的主要优点之一是自动内存管理。它消除了开发人员手动释放未使用对象的内存的需要,并显着缩短了开发时间。然而,这也可能导致大量与内存泄漏和意外应用程序崩溃相关的问题。

2024-04-16 13:53:50 38

翻译 [Testing] Unity性能测试

Unity 性能测试,单元测试,基准测试

2024-04-15 13:47:21 67

翻译 [C#] .NET 中的 Span、Memory、ReadOnlySequence

在 .NET 领域,一个关键方面是有效的数据操作。当涉及到内存管理时,这种能力更加重要。Span、Memory 和 ReadOnlySequence 结构提供了用于优化数据管理的高级工具。这些结构不仅提供了高度的控制性和灵活性,而且还大大提高了运营效率。

2024-04-15 08:08:26 107

翻译 [C#] 在 C# 中使用 Span<T> 和 Memory<T> 编写高性能代码

Span(之前称为 Slice)是 C# 7.2 和 .NET Core 2.1 中引入的一种值类型,开销几乎为零。Span 类型表示驻留在托管堆、栈甚至非托管内存中的连续内存块。如果创建基本类型的数组,它将在栈上分配,并且不需要垃圾回收来管理其生命周期。Span 能够指向分配在栈或堆上的一块内存。但是,由于 Span 被定义为引用结构,因此它应该仅驻留在堆栈上。值类型低或零开销高性能提供内存和类型安全ArraysStringsArraysPointers。

2024-04-14 01:15:43 47

翻译 [C#] 使用 Span<T> 结构编写高性能 C# 简介

今天我们来谈谈 Span,它已经被讨论了好几年了,因为它是随 C#7.2 引入的,并在 .NET Core 2.1 及更高版本的运行时中得到支持。在本文中,我们将通过一些示例来介绍如何使用 Span ,并讨论为什么在编写下一行代码时应该考虑使用它。

2024-04-10 23:37:58 119

翻译 [Unity] UniTask v2 — Unity 的零分配async / await,具有异步 LINQ [2]

我之前发布过UniTask,这是 Unity 的一个新的异步/等待库,现在我重写了所有代码并发布了新的UniTask。在 UniTask v2 中,由于对代码进行了彻底重写,几乎所有内容都是零分配的(技术细节将在后面介绍)。

2024-04-08 12:50:43 166

翻译 [Unity] UniTask 是 Unity 的一个新的 async / await 库[1]

我已经在 GitHub 上发布了新库。虽然这是一项更新,但可以说并不新鲜,因为它最初是作为 UniRx 的一项功能发布的,现在已成为一个独立的项目。在更新 UniRx 的同时,也对其进行了更新,现在它们已经相互独立,完全没有相互依存的关系。

2024-04-05 11:05:54 100

翻译 [Unity] 为什么空合并运算符 (??, ??=) 在 Unity 中是邪恶的?

我最近在 C# 中遇到了空合并运算符。如果您不熟悉它们,以下是它们的工作原理。??如果不为空,则返回左侧,否则返回右侧。如果 myList 为 null,此行会将 processList 设置为新列表。??= 只是??的赋值变体。仅当 myList 为空时,此行才会将其设置为新列表。

2024-04-02 22:21:38 49

翻译 [多线程] 不惜一切代价避免 GetAwaiter().GetResult()

当您需要等待Task时,您是否在同步方法中使用“.GetAwaiter().GetResult()”而不是“.Result”和“.Wait()”?你正在做比较正确的事,但前提是您无法改变该方法!

2024-04-01 22:35:01 127

翻译 [C#] 每个 C# 开发人员都应该知道的事情#1:hash codes (哈希码)

译者总结:HashCode是为了给这个对象一个独一无二的id。让对象在哈希表内均匀的分布,使查找时,速度更快作为一名 C# 开发人员,显然需要掌握很多技能才能发挥作用:语言语法、框架类、第三方库、数据库、正则表达式、HTTP 协议等。

2024-03-31 15:50:47 43

翻译 [多线程] 在异步编程中理解和使用ConfigureAwait

ConfigureAwait 是一种可用于任何 Task 或 Task 对象的方法,用于配置等待该任务时await 关键字的行为方式。它采用一个名为 continueOnCapturedContext 的布尔参数,该参数确定等待之后的延续是否应在与启动任务的上下文相同的上下文中运行。什么是上下文?上下文是一个抽象,表示与执行线程关联的某种状态或环境。例如,在 UI 应用程序中,上下文通常是 UI 线程及其关联的消息循环。在 ASP.NET 应用程序中,上下文是 HTTP 请求及其关联状态。

2024-03-30 22:29:41 32

翻译 [多线程] C#:为什么应该在库代码中使用ConfigureAwait(false)

Async/await 关键字提高了代码的可读性和程序员的工作效率,因为代码类似于同步代码,并且易于理解,这要归功于编译器处理了异步编程中最困难的部分。现在,我们将分析为什么 UI 应用程序中会发生死锁(而不是大多数控制台应用程序中),以及为什么ConfigureAwait(false) 可以解决这个问题。如果这是在控制台应用程序中执行,大多数时候我们的代码将按预期运行(不一定总是)。总之,在库代码中始终使用ConfigureAwait(false) 是一种很好的做法,可以防止出现不必要的问题。

2024-03-30 13:14:57 24

翻译 [Burst] 用 Burst 免费获得性能

因此,让我们编写一个简单的作业,并在使用和不使用 [BurstCompile] 属性的情况下测试其性能。我们将使用 NativeArray 类型来保存数组,并使用新发布的 Unity.Mathematics 包中的 float4 类型来保存向量。Burst 能够识别 float4 类型,并且当我们使用它时可以生成更优化的代码。Burst 编译的代码的运行时间比 IL2CPP 编译的代码少 35%。虽然 Burst 需要改变编程风格,主要是不使用class,但它为合规的代码提供了主要的性能优势。

2024-03-10 22:42:22 55

翻译 [C#] C# Tasks vs. Unity Jobs

两周前,我们针对 Unity 的新 C# 作业系统测试了 async 和 wait 关键字以及 C# Task 系统的性能。这测试了 Task 系统中异步和等待的常见组合,但没有直接针对 Unity 的 C# 作业系统测试任务系统。今天我们将对此进行测试,并在此过程中了解如何在没有 async 和 wait 关键字的情况下使用Task系统。

2024-03-10 21:55:57 68

翻译 [C#] Burst编译通用算法

许多算法被反复使用:搜索、排序、过滤等。C# 通过 LINQ 和 Array.Sort 等函数提供这些算法,但这些算法无法由 Burst 编译,因为不支持接口和委托。那么我们如何实现这些通用算法以避免一遍又一遍地重写它们呢?今天我们将探索一种解决这个问题的技术。请继续阅读以了解具体方法!

2024-03-10 21:30:29 47

翻译 [C#] LINQ 性能更新

为了与这些功能进行比较,测试包括完全“手动”版本和“正常”版本,该版本以更实用的方式使用相同的委托。现在,测试已更新为更加简单,并且更少依赖委托,以避免将测试框架的性能与正在测试的代码混淆。如果您想自己进行测试,只需将上述代码粘贴到 Unity 项目 “资产”(Assets)目录下的 TestScript.cs 文件中,并将其附加到新的空项目中的主摄像头游戏对象上即可。可用性完全是另一回事。今天,我们将使用 Unity 2018.1 和 IL2CPP 更新该文章的测试,看看 LINQ 最近的表现如何。

2024-02-25 20:51:46 64

翻译 [C#] LINQ 到底产生了多少垃圾?

考虑到这些信息,很容易建议不要逐帧使用 LINQ,因为在大多数游戏中,GC 分配即使不是完全禁止,通常也应该保持在最低限度。在最糟糕的情况下,OrderBy 的分配量高达 0.5 KB,而 ToDictionary 的情况也差不多糟糕,分配了 434 字节。其中 10 个函数分配了不止一次,而其余 7 个函数只分配了一次。对于今天的测试,我们将使用每种方法的一个重载,以保持事情简单明了。然后,只需在 CPU 使用情况剖析器的层次结构视图的 GC 分配列和内存剖析器的每帧 GC 分配中记录帧即可。

2024-02-25 20:38:14 74

翻译 [C#] LINQ 的CPU性能

如果您想自己尝试测试,只需将上述代码粘贴到 Unity 项目的 Assets 目录中的 TestScript.cs 文件中,并将其附加到新的空项目中的主相机游戏对象。这是可以预料的,因为他们通过了解问题的所有细节来“作弊”:元素类型、枚举类型以及每个元素要执行的函数。如果您发现带有 LINQ 查询的函数会减慢您的应用程序的速度,请考虑使用“手动”方法重写 LINQ 查询。我们将使用一个包含 1024 个元素的数组(全部为零),并在Where()中查找值1,并将Select中的每个元素加倍。

2024-02-25 19:17:18 87

翻译 [C#] 对象池产生的问题

很常见的是,有人问有关避免垃圾收集器的问题,但得到的答案却是“只需使用池”,就好像这立即完全解决了问题一样。虽然池通常会让垃圾收集器陷入困境,但它们也会带来一系列你必须处理的新问题。今天的文章将讨论其中的几个问题,以便您了解所涉及的权衡,并希望避免一些陷阱。

2024-02-25 19:08:02 41

翻译 [c#] Unity 如何禁用 GC

例如,如果我们在加载一个游戏关卡后开始使用 100 MB 的内存,并且我们知道在该关卡期间不会分配超过 100 MB 的内存,那么我们在任何可以使用的设备上都没有问题。但实际上,这些函数是 Unity 使用的现成 GC 的一部分,文件头中的最新日期是 2001 年,因此这种技术很可能会继续有效,直到 Unity 最终取代 GC。如果它不为零,则 GC 被禁用。对于游戏的帧速率关键部分禁用 GC 并在之后重新启用它(例如在加载屏幕上)可能是一个很大的好处,对于某些游戏来说是值得的,但应该非常小心地使用。

2024-02-17 22:20:06 114

翻译 [C#] 无装箱集合

在上周使用 List 等集合的技巧中,我们看到了结构类型有时是如何装箱的,从而导致 GC 分配。本周我们将了解如何避免装箱,并学习 .NET 集合类型用来实现这一点的一些巧妙技巧。

2024-02-17 22:00:21 57

翻译 [C#] 5 种常见的集合误用

List 和 Dictionary 等集合类型是 C# 中的基本工具。可悲的是,我不断在一个又一个的代码库中看到它们同样的滥用情况。今天我们将看看最重要的 5 个问题,并学习如何轻松避免它们!

2024-02-17 20:52:12 59

翻译 [Shader] Unity Shader 内在函数

在我们开发函数的过程中,我们会遇到一些导致数字小于“0”或大于“1”的操作,例如,在计算网格法线与光照方向的点积时,我们可以得到一个范围 -1.0f 和 1.0f 之间。为了深入理解这个概念,我们将执行以下操作:我们将创建一个新的着色器类型“Unlit Shader”,我们将其称为 USB_function_CEIL,并且我们将首先在纹理 _MainTex 中声明新的 UV 坐标 片段着色器阶段。我们将开始添加一个名为“Size”的属性,稍后我们将使用它来增加或减少圆的大小。因此,它等于“零”。

2024-02-17 20:01:21 112

翻译 [Shader] Unity CG/HLSL [2]

根据其术语,材质是表面渲染方式的定义,包括对纹理、平铺、偏移、颜色等的引用。材质的选项取决于所使用的着色器。我们如何将上述定义转化为实际水平?让我们将材质视为“着色器的容器”,这意味着我们拥有执行表面计算(着色器)的程序和能够读取这些计算的容器(材质)。单独的材料无法执行任何操作。如果它没有着色器,它将不知道应该如何渲染它,同样,如果不通过材质,着色器就无法应用于对象,因此,这个比喻之间材质和着色器是一个"预览的图形数学计算"。

2024-02-14 15:57:44 60

翻译 [Shader] Unity Cg / HLSL [1]

在我们的着色器中,我们至少可以找到三个默认编译指示。这些是处理器指令,包含在 Cg 或 HLSL 中。它们的功能是帮助我们的着色器和某些原本无法识别的函数。#pragma vertex vert 允许名为 vert 的顶点着色器阶段作为顶点着色器编译到 GPU。这是至关重要的,因为如果没有这行代码,GPU 将无法将“vert”函数识别为顶点着色器阶段,因此,我们将无法使用对象中的信息,也无法将信息传递到片段着色器阶段 投影到屏幕上。

2024-02-14 13:25:29 49

翻译 [Shader] Unity CGPROGRAM / ENDCG

我们上面回顾的所有部分都是用 ShaderLab 声明性语言编写的,我们在图形编程语言中的真正挑战从 CGPROGRAM 或 HLSLPROGRAM 声明开始。默认情况下,我们可以看到Unity在我们的程序中包含了CG这个词。对此,官方文档(2021.2版本)中表示:Unity最初使用Cg语言,因此有一些单词和.cginc扩展名,但该软件不再使用这种语言,但是,这些单词仍然包含在内,出于兼容性原因,代码仍在编译中。

2024-02-14 10:27:10 72

翻译 [Shader] Unity SubShader.

着色器的第二个组件是 SubShader。每个shader都由至少一个SubShader组成,以保证程序的完美加载。当有多个 SubShader 时,Unity 会对每个 SubShader 进行处理,并根据硬件特性从列表中的第一个到最后一个选择最合适的。为了理解这一点,我们假设着色器将在支持 Metal graph API (iOS) 的硬件上运行。为此,Unity 将运行第一个支持metal graph的 SubShader 并运行它。

2024-02-13 22:15:50 64

翻译 [Shader] Unity shader Inspector 属性绘制器。

在shader_feature中添加的变体是“常量”,因此它们以大写字母书写,这意味着,例如,如果我们的属性被称为_Change,那么在着色器变体中它应该被添加为“_CHANGE”。在前面的示例中,我们在括号中添加 KeywordEnum 绘制器,然后列出其状态,其中第一个对应于默认状态 (StateOff)。正如我们所看到的,我们将 Toggle 添加到括号中,然后声明属性,然后声明显示名称,后跟 Float 数据类型,最后将属性初始化为“Off”,因为我们在其默认值中添加了零。

2024-02-12 22:00:27 38

翻译 [Shader] 什么是着色器?

在开始定义代码之前,我们必须考虑到 Unity 中存在三种与着色器开发相关的编程语言,它们是 HLSL(高级着色器语言 - Microsoft)、Cg(C for Graphics - NVIDIA),它们仍然可以编译到着色器中,但在当前版本的软件和 ShaderLab(声明性语言 - Unity)中不再使用。我们将开始在内置 RP 中使用 Cg 和 ShaderLab 语言进行冒险,然后在Universal RP 中引入 HLSL。Cg 是一种高级编程语言,旨在在大多数 GPU 上进行编译。

2024-02-12 21:06:29 606

翻译 [Shader] Unity 渲染管线架构

一般来说,在 High Definition RP 和 Universal RP 中,着色器都是在 Shader Graph 中创建的,Shader Graph 是一个包,其中包含一个接口,允许我们通过节点创建着色器,该节点有积极的一面和消极的一面。这个过程可以看作是场景中的对象和屏幕上的像素之间的同步步骤。同样,定向光会影响场景中找到的所有球体,因此,它将为每个球体生成额外的绘制调用,这主要是因为着色器中已包含第二个pass来计算阴影投影,因此, 四个球体加上单向光将总共生成八次绘制调用。

2024-02-12 20:30:40 175

翻译 [Unity Sentis]使用 Unity 和 Hugging Face 创建引人入胜的 AI 驱动游戏

Say Something 是一款休闲游戏,玩家需要根据人工智能的要求输入一些有意义/好听/有趣的内容。目标是获得最高分。是一个平台,用户可以上传或下载超过 35 种不同任务的预训练 AI 模型,从 Llama v2 的文本生成、Whisper 的语音到文本、Coqui 的文本到语音(AI 语音)到 3D生成。对于这些模型中的大多数,Hugging Face 都提供了一个名为推理 API 的免费 API,让你可以通过简单的 API 调用来使用它们。

2024-02-11 16:32:15 204

翻译 [Unity Sentis] 使用 Hugging Face Transformers 和 Unity Sentis 创建 AI 机器人 NPC

句子相似性是一项任务,它能够在给定源句和句子的情况下,计算出句子与源句的相似程度。例如,如果我们的源句(播放器顺序)是 “嘿,给我拿红盒子”,那么它就非常接近 "拿红盒子 "这个句子。句子相似性模型将输入文本 "Hello "转换为捕捉语义信息的向量(嵌入)。我们称这一步为嵌入。然后,我们使用余弦相似度来计算它们的接近(相似)程度。细节我就不多说了,但由于我们的句子相似性模型会产生向量。

2024-02-08 19:56:40 315

翻译 [Shader] 我对着色器的看法:几何着色器

在进入代码之前,让我们先来了解一下什么是几何着色器。为了帮助我说明几何着色器的作用,下面是一个简化的实时渲染管道视图:这篇文章介绍的是 Vulkan 中的流水线,但其概念与其他流水线非常相似。黄色方框是流水线的实际阶段,我们可以用着色器进行编程/覆盖。值得注意的是,"Tessellation "阶段实际上分为 “Hull Shader 阶段”、"Tessellator 阶段 "和 “Domain Shader 阶段”。

2024-02-05 20:58:02 72

翻译 [Unity Sentis] Sentis 中的 Tensor 基本原理

在 Sentis 中,您可以在称为张量的多维数组中输入和输出数据。Sentis 中的张量的工作方式与 TensorFlow、PyTorch 和其他机器学习框架中的张量类似。Sentis 中的张量最多可以有 8 个维度。如果张量的维度为零,则该张量包含单个值,称为标量。

2024-02-03 18:51:52 82

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除