151 Views
March 28, 25
スライド概要
2025/03/06に開催されたイベント、「ぷちTechCon for Unity」 で発表したスライドです。
イベント概要:https://dena.connpass.com/event/339748/
Unity2021.2から利用可能になった「Source Generator」ですが、Unityでの採用事例が徐々に増えています。「Source Generator」はコンパイル時に追加のC#コードを生成することができるRoslynの機能で、ボイラープレートコードの排除など、さまざまな利用方法が考案されています。今回の発表では、「Source Generator」の概要とお手軽な利用事例を紹介します。
DeNA が社会の技術向上に貢献するため、業務で得た知見を積極的に外部に発信する、DeNA 公式のアカウントです。DeNA エンジニアの登壇資料をお届けします。
インクリメンタルソースジェネレータ の概要とお手軽活用術紹介 佐藤 勇人 株式会社ディー・エヌ・エー © DeNA Co., Ltd. 1
インクリメンタルソースジェネレータの 概要とお手軽活用術紹介 佐藤 勇人 株式会社ディー・エヌ・エー © DeNA Co., Ltd. 2
自己紹介 佐藤 勇人 ゲームサービス事業本部 横断組織所属 ・今回の勉強会を主催する技術コミュニティを運営 ・よくブログを執筆 ・最近MacのデフォルトシェルをPowerShellに変更 ・CI/CDもPowerShellで大体作成 © DeNA Co., Ltd. 3
0 SourceGeneratorを利用した OSS紹介 - RapidEnum ● 高速+ゼロアロケーションで動作する 列挙型ユーティリティ ● Unityで利用可 .NET標準APIより 約1000万倍早い © DeNA Co., Ltd. https://github.com/hanachiru/RapidEnum 4
目次 1 Source Generatorとは 2 メリット/デメリット 3 お手軽な利用例 4 まとめ © DeNA Co., Ltd. 5
1. Source Generatorとは © DeNA Co., Ltd. 6
1 Unityにおけるコンパイルの流れ .NET Compiler Platform 通称 : Roslyn C# Mono JIT 中間言語 IL 機械語 IL2CPP C++ Compiler C++ LLVM Burst Compiler LLVM-IR AOT © DeNA Co., Ltd. 7
1 Unityにおけるコンパイルの流れ .NET Compiler Platform 通称 : Roslyn C# Mono JIT 中間言語 IL 機械語 IL2CPP 今回紹介するSourceGeneratorは Roslynの機能 C++ Compiler C++ LLVM Burst Compiler LLVM-IR AOT © DeNA Co., Ltd. 8
SourceGeneratorとは 1 ● コンパイル時に追加のC#コードを差し込むことができるRoslynの機能 コンパイル開始 SourceGeneratorの ステップ開始 ソースコードの 解析 生成コードを 入力に加える コンパイル再開 ソースコードの 生成 https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/ © DeNA Co., Ltd. 9
1
SourceGeneratorとは
[Generator]
public class SamplePropertyGenerator : ISourceGenerator
{
private const string AttributeText = @"
using System;
namespace Sample
{
sealed class SampleAttribute : Attribute
{
public SampleAttribute()
{
}
}
}
";
public void Execute(GeneratorExecutionContext context)
{
context.AddSource(
hintName : "Sample.Generated.cs",
sourceText: SourceText.From(AttributeText, Encoding.UTF8));
}
public void Initialize(GeneratorInitializationContext context) { }
© DeNA} Co., Ltd.
using System;
namespace Sample
{
sealed class SampleAttribute : Attribute
{
public SampleAttribute()
{
}
}
}
Sample.Generated.cs
myGeneratedFile.cs
10
Incremental Source Generator(ISG)とは? 1 ● コンパイル時に変更された部分のみコード生成できるSourceGenerator ○ 必要な部分だけ生成できるので効率的 [EnumExtensions] enum MyEnum { First, Second } ①実行・キャッシュ ForAttributeWithMetadataName() enumの 詳細情報 [EnumExtensions] enum MyEnum { First, Second } public class X{} Select() RegisterSourceOutput() ②コード生成 © DeNA Co., Ltd. ④実行・出力チェック ForAttributeWithMetadataName() ⑤スキップ enumの 詳細情報 Select() 情報を加工 (例. 名前) public class GeneratedClass{} ③コンパイル再実行 情報を加工 (例. 名前) public class GeneratedClass{} RegisterSourceOutput() ⑥前回生成したものを利用 11
Unity特有の制約 1 ● Microsoft.CodeAnalysis.CSharp.dll (≒Roslyn)のバージョンが大切 ○ v3.*はSourceGeneratorが利用可 ○ v4.*はIncremental SourceGeneratorが利用可 ● SourceGenerator は Unity2021.2 から利用可(なはず) ● Incremental SourceGenerator は Unity2022.2, Unity2023.1から利用可(なはず) ● 公言はされていないがUnityが利用するRoslynのバージョンは着々と上がっている 公式ドキュメント : https://docs.unity3d.com/2022.3/Documentation/Manual/roslyn-analyzers.html © DeNA Co., Ltd. 12
2. メリット / デメリット © DeNA Co., Ltd. 13
2 メリット / デメリット メリット ● 手動で生成していた作業を自動化することができる ● T4のように独自記法を使わずにC#の構文のまま生成処理を記述できる ● 生成結果をすぐにIDEでも確認できるのでイテレーションが早い デメリット ● 生成コードを編集できない ● 既存コードの書き換えはできないが、C#12では処理の一部差し替え可能 ● 生成コードの確認がしづらい ● コンパイル時に実行するためビルド時間が伸びる ● コンテキストがやや深いのでメンテコストが高め © DeNA Co., Ltd. 14
3. お手軽な利用例 © DeNA Co., Ltd. 15
3
お手軽な活用例 : T4からISGへの置き換え
●
T4 : テキスト(.cs)を簡易な文法で生成するテンプレートエンジン
○
t4コマンドを実行するとファイルを生成
<#
var types = new[] { "int", "float", "bool" };
foreach(var type in types)
{
#>
public static bool TryParse(this string s, out <#= type #> x) => <#= type #>.TryParse(s, out x);
<#
}
#>
$ t4 Hoge.tt -o Hoge.g.cs
public static bool TryParse(this string s, out int x) => int.TryParse(s, out x);
public static bool TryParse(this string s, out float x) => float.TryParse(s, out x);
public static bool TryParse(this string s, out bool x) => bool.TryParse(s, out x);
© DeNA Co., Ltd.
16
3 お手軽な活用例 : T4からISGへの置き換え ● T4のつらいポイント ○ ○ よく分からない差分が出がち ■ t4のバージョンによって差分が違ったりする ■ VisualStudio か Riderでも違ったり 場合によっては更新し忘れをしないように仕組みを整える必要あり ■ © DeNA Co., Ltd. csprojで設定 か CIで自動実行 で対応することが多い ○ 独自記法を覚えないといけない ○ 生成コードでコンフリクトが起きる可能性あり https://ufcpp.net/blog/2022/12/no-more-t4/ 17
3 お手軽な活用例 : T4からのISGへの置き換え ● ISGへの置き換え方法 1. Unityとは別にISG用の.NETプロジェクトを作成 2. 属性などの情報を読み取ってコードを生成する処理を記述 3. dllを生成してUnityへインポート 4. dllに「Roslyn Analyzer」というLabelをつければ完成 Asset Labelsに RoslynAnalyzer付与 © DeNA Co., Ltd. 18
3 お手軽な活用例 : T4からのISGへの置き換え ● 置き換えメリット ● ○ バージョン等による生成内容の変化がない ○ コンパイル時に生成されるので忘れることがない ○ C#で書けるので独自記法を覚える必要がない ○ GitHubに生成コードがあがらないのでコンフリクトが起きない 所感その他 ○ © DeNA Co., Ltd. T4からの移植は比較的簡単でコスパが良い! ■ 既にT4でどのように生成するのかが書かれている ■ Copilotも味方してくれる ○ T4のデザイン時テンプレートは大抵置き換え可能 ○ 生成したコードを編集したいみたいなケースは T4 を検討したい 19
4. まとめ © DeNA Co., Ltd. 20
4 まとめ ● SourceGeneratorはコンパイル時に追加のC#コードを差し込むことができる機能 ● Incremental SourceGeneratorは差分のみ生成するSourceGenerator ● T4からISGの移植はコスパが良く効率化できる ● 自動化・効率化を行って開発を楽しよう! © DeNA Co., Ltd. 21
© DeNA Co., Ltd. 22