![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/45ad83c0-6d98-11ee-95eb-cdd3e747f724/image_09.png)
쿡앱스 기술지원팀에서 클라이언트 개발을 하고 있는 이진호입니다. 전 각 스튜디오가 사용하는 공통 모듈 개발과 기술 R&D를 통해 쿡앱스의 기술적 성장을 위한 업무를 주로 하고 있습니다. Unity Engine에서 Source Generators 기능을 이용하여 코드의 생산성과 유연함을 증대하는 방법을 아티클로 소개해 보고자 합니다.
Source Generators는 무엇인가요?
Source Generators란 컴파일 중 실행되는 기능으로, 컴파일 단계에서 코드를 분석하거나 추가 코드를 생성할 수 있는 기능입니다. 컴파일 과정 중 Source Generators는 컴파일 작업을 일시정지 후 코드와 메타 데이터를 분석하고, 이 과정에서 컴파일 중인 코드에 대한 syntax 및 semantic 모델과 함께 작동하는 코드를 작성할 수 있습니다.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/90ee11e0-6d95-11ee-998d-6fe91b211ce6/image_01.webp)
Source Generator 작동 과정 / 이미지 출처: Microsoft
Source Generators, 이럴 때 쓰면 좋아요!
Source Generators기능은 반복 작업을 자동화하거나 코드의 특정 조건을 기반으로 추가 코드를 생성하는 경우 매우 뛰어난 성능을 발휘합니다. 간단하게 코드를 기반으로 새로운 코드를 생성하는 매크로 정도로 이해하면 편합니다. Unity Engine에서 Source Generators 유용하게 사용되는 경우는 다음과 같습니다.
-
AOT(ahead-of-time) 문제 해결, Source Generators는 컴파일 단계에서 코드 파일을 생성하여 진행하기 때문에 iOS AOT 문제 해결 가능합니다.
-
동일한 코드를 반복해서 작성하는 경우 자동으로 코드를 생성하여 시간 절약이 가능하고 코드에서 복사 & 붙여 넣기 등의 실수 방지가 가능합니다.
-
API 변경 등 유지 보수에 유연하게 대처 가능합니다. Source Generators 부분만 변경하면 프로젝트의 모든 부분에 코드의 수정 없이 바로 적용이 가능하기 때문에 플랫폼 및 기능별로 유연하게 대처 가능합니다.
Unity Engine 의 Source Generators
Unity Engine에서는 이미 Source Generators 기능을 적극 사용하고 있습니다. 대표적으로 DOTS Entities 경우가 있습니다.
public partial struct MoveSystem : ISystem {
public void OnUpdate(ref SystemState state) {
// MoveData, MoveBuffData 처리
foreach (var data in SystemAPI.Query<MoveData, MoveBuffData>())
{
}
}
// .....
}
위의 예시에서 MoveSystem에서 MoveData, MoveBuffData 정보를 처리하고 있습니다. 코드 작성은 간단하지만 안 보이는 곳에서 Source Generators 기능을 이용하여 많은 작업을 진행하고 있습니다. 아래의 gif는 실제 코드가 생성된 부분을 보여주는 이미지입니다.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/55caf370-6d96-11ee-ab1a-b5ecd899549d/image_02.gif)
DOTS 내부에서 Source Generators 작동 모습
Source Generators 생성 방법
Visual Studio도 같은 방법으로 사용 가능합니다. JetBrains Rider 2023.2 기준의 예제로 설명하겠습니다.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/ac22d530-6d96-11ee-998d-6fe91b211ce6/image_03.webp)
① Rider에서 Class Library 프로젝트를 생성합니다.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/bb11c510-6d96-11ee-9fe5-65ce440a7506/image_04.webp)
② 프로젝트의 Target Framework설정을 .NET Standard 2.0 변경합니다.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/fd300a10-6d96-11ee-b65e-15e020ed36ef/image_05.webp)
③ Unity Engine에서 지원하는 NuGet 패키지 Microsoft.CodeAnalysis.CSharp 3.8를 설치합니다.
[Generator]
public class ExampleSourceGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var sourceBuilder = new StringBuilder(
@"
using System;
namespace SourceGenerated
{
public static class Example
{
public static string GetTestText()
{
return ""This is from source generator ");
sourceBuilder.Append(DateTime.Now.ToString());
sourceBuilder.Append(
@""";
}
}
}
");
string source = CSharpSyntaxTree.ParseText(sourceBuilder.ToString()).GetRoot().NormalizeWhitespace().ToFullString();
context.AddSource("ExampleSourceGenerator", source);
}
public void Initialize(GeneratorInitializationContext context) { }
}
④ 프로젝트에서 새 C# 파일을 만들고 다음 코드를 추가합니다.
⑤ 코드 추가 및 프로젝트 빌드 후 bin/debug or release/netstandard2.0/결과물.dll 파일을 유니티 Assets 하위에 복사합니다. 그다음 dll을 선택한 후 인스펙터에서 Include Platforms 이동하여 모든 플랫폼 비활성 합니다.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/2688e8a0-6d97-11ee-9fe5-65ce440a7506/image_06.gif)
⑥ ‘RoslynAnalyzer’ 이름으로 Asset Labels를 지정합니다.
public class SourceGeneratorTest : MonoBehaviour
{
private void Start()
{
// 생성된 코드 사용
string testText = SourceGenerated.Example.GetTestText();
Debug.Log(testText);
}
}
⑦ 이름 저장 후 위 코드를 생성해 주세요.
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/44adbc70-6d97-11ee-b0f4-955016f41463/image_07.gif)
자동 생성된 코드 모습
![](https://hr-fileupload.s3.ap-northeast-2.amazonaws.com/2023-10-18/626660f0-6d97-11ee-ab84-652ff4741bb0/image_08.gif)
⑧ Unity Engine에서 실행 시 아래와 같이 실행되는 것을 확인 가능합니다.
마치며
지금까지 Source Generator 기능을 Unity Engine에 적용하는 방법을 알아보았습니다. 그동안 코드 생산에서의 효율성을 높이지 못해 고민이셨거나 잦은 휴먼 오류를 개선하기 위한 방법을 찾던 분들에게 이 아티클이 큰 도움이 되길 바랍니다. 다음에는 이러한 Source Generator 기능을 게임에서 어떻게 응용하고 적용하는지 공유해 보도록 하겠습니다!