网易首页 > 网易号 > 正文 申请入驻

Unity 中文课堂 | DOTS课程系列:C# Job System精要

0
分享至

C# Job System 是 Unity 从 2018 开始提供给用户的一个非常强大的功能,它允许用户以一种低成本的方式书写高效的多线程代码。

Unity 中文课堂的官方免费课程《DOTS 课程系列 | C# Job System 精要》将从以下方面讲解 C# Job System,点击阅读原文,即可解锁完整教程。

什么是 C# Job System?

IJobFor

Thread Local

Pointers & InterLocked

Batches & False sharing

Custom batch & Kick jobs

SoA vs AoS

什么是C# Job System?

C# Job System 是 Unity 从 2018 开始提供给用户的一个非常强大的功能,它允许用户以一种低成本的方式书写高效的多线程代码。我们先通过一个 Demo 来一步一步揭开 C# Job System 的面纱:

首先我们先来定义一个 Job


public struct AddJob : IJobpublic float a;public float b;public NativeArray result;
public void Execute()result[0] = a + b;

我们最先能观察到的就是 AddJob 实现了 IJob 接口,IJob可以让我们调度(Schedule)一个在单一工作(worker)线程里执行的任务。其次我们可以看到 AddJob 是一个 struct。

我们再来看一下 AddJob 里的变量部分:


public float a;public float b;public NativeArray result;

Job 中的变量我们仅可以使用blittable types或者 Unity 为我们提供的NativeContainer容器,比如引擎内置的 NativeArray 或者 com.unity.collections package 中提供的容器类。

blittable types:

https://en.wikipedia.org/wiki/Blittable_types

NativeContainer:

https://docs.unity3d.com/Manual/JobSystemNativeContainer.html

注:为什么只能使用 blittable types?这是因为 C# Job System 使用了 Unity 内部的 native job system,C# Job System 会与 native job system 共享工作线程。为了达到这个目的,C# 中的 Job 数据需要被拷贝到 native 层来运行计算代码,blittable types 在这个拷贝过程中不需要做数据转换,因此 blittable types 在这里是必须的。不仅如此 blittable types 还有着其他的好处,我们会在后面的例子中看到。

让我们来总结一下声明一个 Job 的要点

创建一个实现了 IJob 接口的 struct。

在 struct 中声明 blittable types 或者 NativeContainer 的变量。

在 Execute() 方法中实现 Job 的逻辑。

好,通过上面几步我们就成功创建了我们的 AddJob 。接下来我们来看一下如何调度(Schedule)一个 Job 以及如何获得 Job 执行后的结果:


var job = new AddJoba = 1,b = 2,result = result
var handle = job.Schedule();handle.Complete();Debug.Log($"result = {result[0]}");

调度(Schedule)一个 Job是比较简单的,只需要调用 Schedule() 方法就可以了。这里比较有意思的是 Complete() 方法,在我们需要读取执行结果之前需要调用 Complete() 方法。但是 Complete() 不一定在 Schedule() 之后立即调用,也不一定在当前帧必须调用,也就是说一个 Job 本身不受 Update() 限制可以跨帧运行。当一个 Job 需要跨帧运行的时候,我们需要使用 IsCompleted 属性来判断 Job 是否执行完毕。


private void Update()if (handle.IsCompleted)handle.Complete();Debug.Log($"result = {result[0]}");

注:即使 IsCompleted 返回 true,也必须要调用 Complete() 方法。具体可以参考 C# Job System tips and troubleshooting。

C# Job System tips and troubleshooting:

https://docs.unity3d.com/Manual/JobSystemTroubleshooting.html

这样我们就实现了了一个最简单的 Job,这里我给出完整的 Demo 代码,方便大家进一步理解上面介绍的内容:


public class AddJobBehaviour : MonoBehaviourpublic bool longRunningJob;private JobHandle handle;private NativeArray result;
public struct AddJob : IJobpublic float a;public float b;public NativeArray result;
public void Execute()result[0] = a + b;
private void Start()result = new NativeArray(1, Allocator.Persistent);
var job = new AddJoba = 1,b = 2,result = result
handle = job.Schedule();
if (!longRunningJob)handle.Complete();Debug.Log($"result = {result[0]}");
private void Update()if (handle.IsCompleted)handle.Complete();Debug.Log($"result = {result[0]}");
private void OnDestroy()if (result.IsCreated)result.Dispose();

在上面的完整 Demo 代码中,有一点是之前没有提到的,就是下面这两句:


result = new NativeArray(1, Allocator.Persistent);
result.Dispose();

这里大家可以很明显的注意到,NativeContainer 是需要显式管理内存的。关于这方面的内容我会在后面的 NativeContainer 章节继续跟大家聊。

好,到这里大家应该对 C# Job System 有了一个初步的了解。让我们来做一个小测验,看我们是否真的理解了上面的内容。

下面的代码,输出结果会是什么?


public class MyCounterJobBehaviour : MonoBehaviourpublic struct CounterJob : IJobpublic NativeArray numbers;public int result;
public void Execute()for (int i = 0; i < numbers.Length; i++)result += numbers[i];
// Start is called before the first frame updatevoid Start()var numCount = 10;NativeArray numbers = new NativeArray(numCount, Allocator.TempJob);
for (int i = 0; i < numCount; i++)numbers[i] = i + 1;
var jobData = new CounterJobnumbers = numbers,result = 0
var handle = jobData.Schedule();handle.Complete();Debug.Log($"result = {jobData.result}");numbers.Dispose();

答案是result = 0

这个结果跟你想的一样么?

让我们来思考一下为什么是这个结果。我们再来看回顾一下 Job 的特点

需要声明成 struct

struct 中的数据必须是 blittable 的或者是 NativeContainer

要实现 IJob 接口

这些限制条件其实都是为了一个目的,就是要把 C# 中的 Job 数据复制到 native 层,最终由 native job system 去执行 job 中的逻辑。想到这其实我们的答案也就显而易见了,Execute() 方法中修改的其实只是我们 CounterJob 的一个副本,并不是原始的 CounterJob。因此当我们需要从 Job 中获得计算结果的时候,我们需要使用 NativeContainer,否则会得到不正确的结果。下面是正确的写法:


using Unity.Collections;using Unity.Jobs;using UnityEngine;
public class CounterJobBehaviour : MonoBehaviourpublic struct CounterJob : IJobpublic NativeArray numbers;public NativeArray result;
public void Execute()var tmp = 0;for (int i = 0; i < numbers.Length; i++)tmp += numbers[i];
result[0] = tmp;
void Start()var numCount = 10;NativeArray numbers = new NativeArray(numCount, Allocator.TempJob);var result = new NativeArray(1, Allocator.TempJob);
for (int i = 0; i < numCount; i++)numbers[i] = i + 1;
var jobData = new CounterJobnumbers = numbers,result = result
var handle = jobData.Schedule();handle.Complete();
Debug.Log($"result = {result[0]}");
result.Dispose();numbers.Dispose();

到这里我们就已经把 C# Job System 以及 IJob 大概了解了一下,相信大家应该已经注意到了,IJob 只能跑在单一工作(Worker)线程上,如果想要利用全部的工作(Worker)线程就需要用到我们下一节要介绍的另外一个接口了,那就是 IJobFor。

好,以上就是本节所有的内容了,下一节我们讲继续讨论 Job 的另一种形式:IJobFor。

感谢大家的耐心阅读

Unity 官方微信

第一时间了解Unity引擎动向,学习最新开发技巧

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
解放军登场后,外交部也跟进表态,中方通知日本:血债必须偿还

解放军登场后,外交部也跟进表态,中方通知日本:血债必须偿还

世间一分钟
2026-01-18 23:20:00
功夫影星梁小龙去世,享年77岁;周星驰曾3次邀请梁小龙演“火云邪神”

功夫影星梁小龙去世,享年77岁;周星驰曾3次邀请梁小龙演“火云邪神”

扬子晚报
2026-01-18 17:40:54
婚外情最残忍真相:穷人连出轨都透着穷酸气

婚外情最残忍真相:穷人连出轨都透着穷酸气

衍月
2025-12-07 22:51:30
陈幸同正式公开恋情!

陈幸同正式公开恋情!

乒乓乐园
2026-01-19 00:07:09
不出所料!委代总统通告了全球:邀美国共治,我们都被耍了?

不出所料!委代总统通告了全球:邀美国共治,我们都被耍了?

蓝色海边
2026-01-18 20:11:58
谢贤前女友大曝恋爱私隐!三年不碰她,却每天给她做“四哥菜芯”

谢贤前女友大曝恋爱私隐!三年不碰她,却每天给她做“四哥菜芯”

阿纂看事
2026-01-09 10:19:00
国乒2026年第一个冠军出炉!WTT多哈挑战赛:周启豪4-2战胜温瑞博

国乒2026年第一个冠军出炉!WTT多哈挑战赛:周启豪4-2战胜温瑞博

齐帅
2026-01-19 00:19:02
最帅星二代!黄磊8岁儿子近照,单眼皮高鼻梁拉小提琴,疑准备出道

最帅星二代!黄磊8岁儿子近照,单眼皮高鼻梁拉小提琴,疑准备出道

八星人
2026-01-16 15:46:25
贾国龙发怒后西贝员工仍被网友调侃:微波炉加热师是挺难找工作

贾国龙发怒后西贝员工仍被网友调侃:微波炉加热师是挺难找工作

映射生活的身影
2026-01-17 23:09:13
央行降息为何无法救市?A股牛市遭遇调整,沪指四连跌原因分析

央行降息为何无法救市?A股牛市遭遇调整,沪指四连跌原因分析

有料财经
2026-01-18 22:12:30
姜群道长:属虎人2026年运势及运程详解,2026年属虎人全年运程!

姜群道长:属虎人2026年运势及运程详解,2026年属虎人全年运程!

玄炀观
2026-01-18 15:50:23
巩俐21岁时写的字,颠覆了我的想象!

巩俐21岁时写的字,颠覆了我的想象!

石场阿鑫
2026-01-16 13:41:02
斯诺克比赛结果:囧哥5-3战胜老张,争夺大师赛首冠

斯诺克比赛结果:囧哥5-3战胜老张,争夺大师赛首冠

小鞄搞笑解说
2026-01-19 00:52:34
越南U23主帅:全队都很想念越南粉的味道;希望球队能战胜中国

越南U23主帅:全队都很想念越南粉的味道;希望球队能战胜中国

懂球帝
2026-01-18 23:30:07
李艾一家游哈尔滨,买19元棉衣和29元雪地靴,花346元旅行后扔掉

李艾一家游哈尔滨,买19元棉衣和29元雪地靴,花346元旅行后扔掉

阿纂看事
2026-01-15 10:29:10
拥有500万粉丝的日本网红大秀傲人身材,粉丝狂喜

拥有500万粉丝的日本网红大秀傲人身材,粉丝狂喜

随波荡漾的漂流瓶
2026-01-16 18:01:18
闫学晶简历

闫学晶简历

情感大头说说
2026-01-18 07:19:41
陪玩陪睡已过时!拳头塞嘴、集体开嫖、戚薇遭殃,阴暗面彻底曝光

陪玩陪睡已过时!拳头塞嘴、集体开嫖、戚薇遭殃,阴暗面彻底曝光

涵豆说娱
2025-11-20 16:35:46
北京市中小学,放寒假通知!

北京市中小学,放寒假通知!

美丽大北京
2026-01-18 09:10:40
雨夹雪+冻雨!下周二起,广州暴降至7℃!

雨夹雪+冻雨!下周二起,广州暴降至7℃!

羊城攻略
2026-01-18 23:28:50
2026-01-19 02:00:49
Unity incentive-icons
Unity
Unity中国官方帐户
2422文章数 6729关注度
往期回顾 全部

科技要闻

AI大事!马斯克:索赔9300亿元

头条要闻

特朗普建"联合国"自任主席 邀60国加入仅1国接受

头条要闻

特朗普建"联合国"自任主席 邀60国加入仅1国接受

体育要闻

21年后,中国男足重返亚洲四强

娱乐要闻

香港武打演员梁小龙去世:享年77

财经要闻

BBA,势败如山倒

汽车要闻

又一次闷声干大事,奇瑞进入2.0 AI+时代

态度原创

健康
教育
亲子
游戏
时尚

血常规3项异常,是身体警报!

教育要闻

孩子成绩好不好,先看父母稳不稳

亲子要闻

文咏珊带助理游曼谷,生娃3个多月瘦出“排骨胸”,不像母乳喂养

《GTA6》两大主角开场任务泄露 60%的建筑可进去

美拉德过时了?今年冬天最火的4个颜色竟然是它们

无障碍浏览 进入关怀版