うどんゲームメモ

ゲームの技術メモをまったりと

IncrementalCompiler時代のUnityC#Tips(C#7.2)

この記事はUnityゆるふわサマーアドベントカレンダー 2018の6日目の記事になります
5日目の記事は@splas_boomelangさんのUnity用のパッケージ(アセット)を配布する時のお作法でした!

qiita.com

Unity2018.1以降からIncrementalCompilerがPreview版として公開されるようになりました
まだUnity開発界隈では6.0の機能を徐々に会社の実プロダクトレベルで実験的に活用し始めたぐらいのフェーズかなと思いますが(async/awaitがじわじわと広まりだしたぐらいかな?) 、IncrementalComplierを導入することでC#7.2までの機能を使用することができます
6.0のasync/awaitレベルのUnity開発に対する革新的な変更はないため、そんなにインパクトがあるわけではないのですがちょっとしたTipsとしてUnity開発に使えそうなものをちょこちょこっと紹介します


IncrementalCompiler

まずIncrementalCompilerについて軽くお話します
IncrementalCompilerとは2014年よりMicrosoftオープンソース化した次世代コンパイラ「Roslyn」をUnity内で用いることでコンパイル時間の削減とC#7.2までの機能の使用を可能にするものです
上述にもあったようにまだPreview版でバージョンも0.0.42-preview,16と試験段階かなと言わざるを得ない状態です、これにより今のところ運用を見送っているプロジェクト等もあるのではないでしょうか
自分が個人規模の開発で使用してみた感じは特に問題は起きていないため、使用を続けています、その内Unityのアップグレードに従って標準環境になっていくことは見えているので早いうちから慣れておくのは悪くない選択肢かなと

Unity Incremental C# Compiler - Unity Forum

Tips

それではIncrementalCompiler導入によって使用できるC#機能の紹介です

タプル

タプルとは簡潔に説明すると複数のオブジェクトを1つのオブジェクトとしてまとめたものです 元々.Net4で導入されていたもので、パッケージとして導入し使用することは出来たのですがC#7よりC#の正式な機能として導入されるようになりました
Tuple<T1, T2>みたいな感じでジェネリクス保有する型を定義して使用します
複数の値を戻り値として受け取れるため便利な機能の一つです、自分はよく使用しています
.NetのTupleだとアクセサが固定でitem1といった抽象名でしか扱えずコードが見づらくなりがちでしたが、C#では名前を定義して使うことができます

// タプルの定義
(int age, string name) tuple = (10, "udon");

// タプル値の参照
Debug.Log(tuple.age); //10
Debug.Log(tuple.name);

// タプルで返す
(bool success, int result) Sum(int x, int y)
{
    if(x > 100 || y > 100)
    {
        return (false, -1);
    }
    else
    {
        return (true, x + y);
    }
} 

またタプルで受け取った複数のオブジェクトに対してそれらを分解する機構も作られています
上記のSumのように定義したタプルを変数宣言することなく個々の戻り値を使えるわけですね、タプルを使用するケースではタプル自体に命名する意義がない場合が多いので嬉しい配慮です

(var success, var sum) = Sum(100, 100);
Debug.Log(success); //true
Debug.Log(sum); //200

出力変数宣言

出力引数を受け取る際、事前に変数を宣言し受け取り口を作ってからそれを指定する必要がありましたが、C#7からは式の中で受け取り口の変数宣言を行うことが出来るようになりました
これに関しては劇的に使用するわけではありませんが、スマートに書けるので身に着けときましょう

Dictionary<string, string> hogeDictionary;

hogeDictionary.TryGetValue("hoge", out var value);
Debug.Log(value);

async T

async/awaitは確かに強力なソリューションの一つですが、そのネックの一つとして返り値がTaskに縛られてしまうというものがありました
特にTaskとしての機能が要らないようなケースでもasyncさせるためにはTaskとして宣言する必要があり割とパフォーマンス的な観点で見るとおやっ?ってなったり、シンプルな値返還の形を作るだけでも若干await操作がめんどくさかったりしました
C#7.0からは任意の型に対してasync宣言が行え、それをawaitで待機できるようになりました
ここで具体的な説明をしてしまうとそれだけで一つの記事になっちゃうかもなので詳しくは下記のリンク先のtask-likeについての項目を読んでみてください

非同期メソッド - C# によるプログラミング入門 | ++C++; // 未確認飛行 C


ざっくり自分が使用したり、知識として抑えているものを紹介しました
この他にも様々な機能の追加がされているので、IncrementalCompilerを個人で試しに使ってみてください(特にUniRx6等はバリバリ使用しているので見てみるといいかも)