Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9683

【Unity】asmref(asmdefではない)を使うとinternalアクセスできて便利【Assembly Definition Reference Files】

$
0
0
はじめに Assembly Definition Files( *.asmdef )については解説を見かけるのですがAssembly Definition Reference Files( *.asmref )についての解説を見かけないのでメモがてら書き残します。 Assembly Definition Files 影響下にあるスクリプトを一つのDLLとしてコンパイルすることで全体のコンパイル時間を短縮してくれたりするやつです。 参考: Unity Assembly Definition 完全に理解した 【Unity】「AssemblyDefinitionを分けるとコンパイルが高速になる」ってホント?検証してみた! 【Unity】asmdefのVersion Definesを使って特定のPackageがインストールされていたら自動的に処理を変える Assembly Definition Reference Files Unity2019.2.0で追加された機能で、 Scripting: Added support for Assembly Definition Reference Files (asmref). These allow for adding additional source code directories to an existing Assembly Definition File (asmdef). DeepL翻訳: アセンブリ定義参照ファイル(asmref)のサポートを追加しました。これにより、既存のアセンブリ定義ファイル(asmdef)にソースコードのディレクトリを追加することができます。 とのことです。 機能としてはシンプルで、 自身の影響下にあるスクリプトを指定した *.asmdef と同じDLLファイルに含める 以下のスクリプトファイルに影響する( *.asmdef と同じ) *.asmref が存在するディレクトリ内 同ディレクトリ内に存在するディレクトリ、その子,孫,..(以下ループ)ディレクトリ 子ディレクトリを辿る途中で別の *.asmref (X)が存在したら、それ以下は(X)の影響下になる となっています。 作成方法は *.asmdef とほぼ同じで、   Projectウィンドウを右クリック → Create → Assembly Definition Reference で作成できます。 実際に *.asmref ファイルを作ってInspectorで確認するとこんな感じ。 ファイルの実態は短いテキストファイルで、開いて確認してみると Use GUIDがオンのとき: { "reference": "GUID:d00ea8eea3b8a4df79ba6bcba16173ef" } Use GUIDがオフのとき: { "reference": "AutoScreen" } といった感じになります。 用途 とりあえず思いついたやつを3つほどご紹介します。 *.asmdefによって強制されるスクリプトの配置を好きに変更できる *.asmdef を使用するとディレクトリ構造がある程度強制されますが、*.asmref を使うことで *.asmdef の配置場所とは関係なくスクリプトを配置できます。 ちなみに同一の *.asmdef を参照する *.asmref は複数追加できます。 アセットやPackage Managerから入れたパッケージに外から手を加える 例えば UniRx には Observable.Using() が実装されてないのですが、これを追加するためにリポジトリをForkして手を加えたり、 Assets/ 以下にソースコードをすべて配置してカスタマイズするのは面倒です。 *.asmref を使用すると UniRx をPackage Managerから追加しつつ、 Observable.Using() のような独自の処理を追加できます。 Package ManagerからUniRxを追加 適当なディレクトリ(例えば Assets/UniRxExtensions/ )(A)を作成 (A)に *.asmref ファイルを追加& Assembly Definition に UniRx.asmdef を指定 UniRxに追加したい処理を(A)に追加 以下のコードは UniRx で使える Observable.Using から引用 Observab.Using.cs using System; namespace UniRx { public static partial class Observable { // https://github.com/Reactive-Extensions/Rx.NET/blob/371c83c621562a2259580a03f0cb5bf8680ea720/Rx.NET/Source/System.Reactive.Linq/Reactive/Linq/QueryLanguage.Creation.cs#L417-L441 public static IObservable<TSource> Using<TSource, TResource>( Func<TResource> resourceFactory, Func<TResource, IObservable<TSource>> observableFactory) where TResource : IDisposable { return Observable.Create<TSource> (observer => { var source = default(IObservable<TSource>); var disposable = Disposable.Empty; try { var resource = resourceFactory(); if (resource != null) { disposable = resource; } source = observableFactory(resource); } catch (Exception exception) { return new CompositeDisposable(Throw<TSource>(exception).Subscribe(observer), disposable); } return new CompositeDisposable(source.Subscribe(observer), disposable); }); } } } *** 注意点 *** 処理を「足す」ことはできるが「引く/変更する」ことはできない Package Managerで入れたパッケージ内の *.asmdef の Assembly Definition References に何かを足す・上書きすることはできない 例えば こちら で紹介されてる Observable.FromUniTask() を *.asmref で足すのは無理 そもそも UniRx.asmdef には UniTask.asmdef への参照が含まれていない なので UniRx.dll から UniTask.dll を参照できない Unityの internal クラスにアクセスする (使用は自己責任でお願いします) 【Unity, C#】internalな型やメンバにアクセスするには、多分これが一番早いと思います こちらの記事では特殊な *.asmdef を追加する手法が紹介されてますが、同様のことは *.asmref でも可能です。 例えば UnityEditor.UI を指定した *.asmref を作成すると、その影響下にあるスクリプトはUnityの internal クラスにアクセスできます。 *.asmdef を使用する場合は同一名のものを複数追加するとコンフリクトが起きて以下のようなエラーになります。 Assembly with name 'Unity.InternalAPIEditorBridgeDev.001' already exists (Assets/Foo/NewAssembly.asmdef) が、*.asmref を使用する場合は上記のようなコンフリクトを気にする必要がありません。 ただし、配布するライブラリなどでこのテクニックを使用する場合は、 *.asmref に指定した *.asmdef がプロジェクトに確実に含まれている必要があります。不要なパッケージは削除されてる場合があるので注意が必要です。 ちなみに 同一のディレクトリに *.asmdef と *.asmref を両方配置すると以下のようなエラーになります。 Folder 'Assets/Foo/' contains multiple assembly definition files (Assets/Foo/NewAssemblyReference.asmref) Folder 'Assets/Foo/' contains multiple assembly definition files (Assets/Foo/NewAssembly.asmdef) 同一のディレクトリに *.asmref を複数配置した場合は、同じ *.asmdef を指定してある分にはエラーになりませんでした。エラーになるかと思った😇 さいごに *.asmref は *.asmdef のかゆいところに手が届く、そんな存在。ぜひ使ってみてください。

Viewing all articles
Browse latest Browse all 9683

Trending Articles