Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: improvements on editor public api #1143

Merged
merged 12 commits into from
Aug 26, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,78 @@ title: コンポーネントにAvatar Optimizerとの互換性をもたせる

Avatar Optimizerが処理する時点でアバターにコンポーネントが存在している場合、そのコンポーネントはAvatar Optimizerと互換性が無い可能性があります。

Avatar Optimizerはコンポーネント等に対するガベージコレクションシステムを実装しているため、最適化時にアバターに存在するすべてのコンポーネントのことを知る必要があります
Avatar Optimizerはビルド処理の最後の方で動作するように設計されているため、Avatar Optimizerにとって未知のコンポーネントについてはサポートしていません

未知のコンポーネントによる問題を避けるため、Avatar Optimizerは未知のコンポーネントが以下のようなものであると仮定します。(この仮定は将来的に変更される可能性があります。)
- 副作用のあるコンポーネントである。
例えば、Avatar Optimizerはコンポーネント等に対するガベージコレクションシステムを実装しています。
使用されているコンポーネントを保持し、未使用のコンポーネントを適切に削除するためには、
最適化時にアバターに存在するすべてのコンポーネントのことを知っておく必要があります。

未知のコンポーネントによる問題を避けるため、Avatar Optimizerは未知のコンポーネントが以下のようなものであると仮定します。
- コンポーネントが有効かつアクティブになる可能性がある場合は保持される必要がある。
- これは、未知のコンポーネントを実行時(VRChat上など)に動作するコンポーネントであると仮定しているためです。
anatawa12 marked this conversation as resolved.
Show resolved Hide resolved
- コンポーネントが参照している全てのコンポーネントに依存している。

この仮定は正しくない可能性があるため、Avatar Optimizerは未知のコンポーネントを見つけた場合に以下のような警告を生成します。
(上記の仮定は将来的に変更される可能性があります。)

しかしながら、これらの仮定は正しくない可能性があるため、Avatar Optimizerは以下のような警告を生成します。

![unknown-component-warning](unknown-component-warning.png)

## どのように互換性を改善するか {#improve-compatibility}

Avatar Optimizerが処理する前にコンポーネントを削除出来る場合は、そのようにしてください。
削除出来ない場合はAvatar Optimizerにコンポーネントを登録してください。
以下の対応のいずれかを行うことで、互換性を改善することができます。

1. Avatar Optimizerが処理する前にコンポーネントを削除する

コンポーネントが実行時では動作しないものである場合、(すなわち、ビルド時や編集モードでのみ動作するコンポーネントである場合、)
Avatar Optimizerより前にアバターを処理し、コンポーネントを削除することが殆どの場合で最善です。

詳細は[下のセクション](#remove-component)を参照してください。

Avatar Optimizerは、Trace and Optimizeの前に処理を行う殆どのAvatar Optimizerコンポーネントにおいて、内部的にこの方法を使用しています。

Avatar Optimizer v1.7.0以降では、ビルド時やランタイムで処理を行わないコンポーネント向けに[Asset Description]が追加されています。
ビルド時に処理を行わないようなツールであれば、こちらを利用して登録することもできます。
2. APIを使用してAvatar Optimizerにコンポーネントを登録する

ビルド時に何らかの処理を行うツールやコンポーネントの場合は、Asset Descriptionで登録するのは非推奨です。
これは、Asset Descriptionによる登録では、ビルド時の処理順が意図しないものになってしまった場合などにAvatar Optimizerがコンポーネントを削除してしまうことにより、ツールが正しく動作出来なくなる可能性があるためです。
実行時に動作するコンポーネントや、Avatar Optimizerより後にアバターを処理するために残しておく必要があるコンポーネントの場合、
そのコンポーネントの情報をAvatar Optimizerに登録することができます。

詳細は[下のセクション](#register-component)を参照してください。

Avatar Optimizerは、Trace and Optimizeの後に処理を行う一部のコンポーネントや、Unity純正のコンポーネント、VRCSDKのコンポーネントなどを保持するために、内部的にこの方法を使用しています。

[Asset Description]: ../asset-description
3. Asset Descriptionを使用して、削除しても問題のないコンポーネントとしてAvatar Optimizerに登録する

Avatar Optimizer v1.7.0以降では、実行時やビルド時で処理を行わないコンポーネント向けに[Asset Description]が追加されています。
ツールが実行時やビルド時に何も行わない場合は、「Avatar Optimizerが処理する前にコンポーネントを削除する」代わりにこの方法を使用してコンポーネントを登録することができます。

詳細は[Asset Description]を参照してください。
anatawa12 marked this conversation as resolved.
Show resolved Hide resolved

なお、ツールが実行時やビルド時に何らかの処理を行う場合は、そのコンポーネントをAsset Descriptionで登録することは非推奨です。
実行時やビルド時に何らかの処理を行うコンポーネントをAsset Descriptionで登録してしまうと、
実行順に予期しない変更があったり、指定が正しくなかったりした場合に、コンポーネントがAvatar Optimizerに意図せず削除されてツールが正常に動作できなくなる可能性があります。

Avatar Optimizerは、編集モードでのみ動作するよく知られているツールとの互換性を保つために、内部的にこの方法を使用しています。

### コンポーネントを削除する {#remove-component}

コンポーネントを削除する方法はいくつかあります。

ツールがNDMF[^NDMF]を使用した非破壊ツールの場合は、NDMFのOptimizing phaseより前、
またはOptimizing phaseの中で([`BeforePlugin`][ndmf-BeforePlugin]を用いて)`com.anatawa12.avatar-optimizer` plugin
ビルド時において、Avatar Optimizerより前にアバターを処理し、コンポーネントを削除するための方法はいくつかあります。削除には[`DestroyImmediate`]を用います。

ツールがNDMF[^NDMF]を使用した非破壊ツールの場合は、NDMFのOptimizing phaseより前のPhaseか、
Optimizing phaseの中で([`BeforePlugin`][ndmf-BeforePlugin]を用いて)`com.anatawa12.avatar-optimizer` plugin
より前にコンポーネントを削除することを推奨します。
Optimizing phaseの中でコンポーネントを削除する場合は、デフォルトのコールバック順序が`com.anatawa12.avatar-optimizer` pluginより前であっても、
[`BeforePlugin`][ndmf-BeforePlugin]を指定しておくことを強く推奨します。

ツールがNDMF[^NDMF]を使用していない非破壊ツールの場合は、NDMFのOptimizing phaseより前にコンポーネントを削除することを推奨します。
この場合、現在のNDMFはVRCSDKの`RemoveAvatarEditorOnly`の直前であるorder `-1025`でOptimizing phaseを実行するので、
それより小さい`callbackOrder`を指定した`IVRCSDKPreprocessAvatarCallback`でコンポーネントを削除してください。
`-1025`より小さい`callbackOrder`を指定した`IVRCSDKPreprocessAvatarCallback`でコンポーネントを削除してください。

ツールのコンポーネントにデータを保持する役割しかなく、ビルド時には意味を持っていない場合、
anatawa12 marked this conversation as resolved.
Show resolved Hide resolved
上記のように`IVRCSDKPreprocessAvatarCallback`でコンポーネントを削除するか、
[Asset Description]を使用し、削除しても問題のないコンポーネントとして登録することができます。

ツールのコンポーネントがデータを保持する役割しかなく、ビルド時には意味を持っていない場合、
`IVRCSDKPreprocessAvatarCallback`を用いてAvatar Optimizerが処理する前にコンポーネントを削除することを推奨します。
`IVRCSDKPreprocessAvatarCallback`の順序については上記を参照してください。
[DestroyImmediate]: https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html

### コンポーネントを登録する {#register-component}

Expand Down Expand Up @@ -92,7 +126,7 @@ internal class YourComponentInformation : ComponentInformation<YourComponent>

`CollectMutations`では、コンポーネントの処理によって変更される可能性があるプロパティを登録します。\
`CollectDependency`では、ビルド時や実行時でのコンポーネントの依存関係を登録します。\
詳しくはxmldocやメソッド名を参照してください
詳しくはそれぞれのメソッドのxmldocを参照してください

[fediverse]: https://misskey.niri.la/@anatawa12
[ndmf-BeforePlugin]: https://ndmf.nadena.dev/api/nadena.dev.ndmf.fluent.Sequence.html#nadena_dev_ndmf_fluent_Sequence_BeforePlugin_System_String_System_String_System_Int32_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,57 +16,96 @@ If you have some question, please feel free to ask [`@[email protected]`
If your components are on the avatar and still exist when Avatar Optimizer processes it,
your components can be incompatible with Avatar Optimizer.

Since Avatar Optimizer has Garbage Collection system for Components and others, Avatar Optimizer has to
know about all existing components in the Avatar at the optimization.
Avatar Optimizer is designed to process at the last of the build process,
components unknown to Avatar Optimizer is not supported.

For example, Avatar Optimizer has Garbage Collection system for Components and others.
To correctly remove unused components, and correctly keep used components,
Avatar Optimizer has to know about all existing components in the Avatar at the optimization.

To avoid problem with unknown components, Avatar Optimizer currently assumes unknown components
- have some side-effects.
- have to be kept if the component can be enabled and active at runtime.
- This is because Avatar Optimizer assumes unknown components are runtime components.
- will have dependency relationship to all components referenced in the component.
(They can be changed in the future.)

However, the assumption can be incorrect, so Avatar Optimizer will generate the following warning.
(Those assumptions above can be changed in the future.)

However, those assumptions can be incorrect, so Avatar Optimizer will generate a warning like below.

![unknown-component-warning](unknown-component-warning.png)

## How to improve the compatibility? {#improve-compatibility}

Please remove your components before Avatar Optimizer processes as much as possible.
If you cannot remove some components, please register them to Avatar Optimizer.
To improve the compatibility, you may implement one of the following methods.

1. Remove your components before Avatar Optimizer processes as much as possible.

If your component is not working at runtime, (in other words, it's a build-time or edit mode only component),
it's mostly better for your tool to process avatar before Avatar Optimizer processes,
and remove your components before Avatar Optimizer processes.

Please refer [section below](#remove-component) for more details.

Avatar Optimizer internally uses this method for most Avatar Optimizer components,
that will be processed before Trace and Optimize.

2. Register your components to Avatar Optimizer with API

Since Avatar Optimizer v1.7.0, [Asset Description] is added for components that doesn't process on build or at runtime.
If your tool process nothing at build time, you can use this to register your components.
If your component is working at runtime, or your tool actually wants to keep your components for processing avatar after Avatar Optimizer processes,
you can register your components to Avatar Optimizer to tell about your components.

If your tool process something at build time, registering with Asset Description is not recommended.
This prevents Avatar Optimizer from accidentally removing components and causing your tool to not work properly when the processes execution order is unexpected/incorrect.
Please refer [section below](#register-component) for more details.

Avatar Optimizer internally uses this method to keep some components that are processed after Trace and Optimize,
and components from Unity, VRCSDK, and other avatar platform components.

3. Register your components as no problems to remove with Asset Description.

Since Avatar Optimizer v1.7.0, you can use [Asset Description] to register components only for holding data
for edit-mode tools, that doesn't affects on build or at runtime.
If your tool process nothing at build time or runtime, you can use this to register your components instead of
removing your components before Avatar Optimizer processes.

Please refer [Asset Description] for more details.
anatawa12 marked this conversation as resolved.
Show resolved Hide resolved

If your tool process something at build time or runtime, registering with Asset Description is not recommended.
If you use Asset Description for components that process something at build time or runtime, it may cause unexpectedly
removing your components and your tool not working properly when the execution order is incorrect or unexpectedly changed.

Avatar Optimizer internally uses this method to keep compatibility with well-known edit-mode tools.

[Asset Description]: ../asset-description

### Removing your components {#remove-component}

You can remove your components with several ways.
There are several ways to process and remove your components from avatar before Avatar Optimizer processes on build. You can use [`DestroyImmediate`][DestroyImmediate] method for removing your components.

If your tool is a non-destructive tool based on NDMF[^NDMF], removing your components before the Optimizing phase
or before `com.anatawa12.avatar-optimizer` plugin (with [`BeforePlugin`][ndmf-BeforePlugin])
in the Optimizing phase is recommended.
If your tool is a non-destructive tool based on NDMF[^NDMF], you can remove your components before the phases
prior to the Optimizing phase of NDMF or before `com.anatawa12.avatar-optimizer` plugin
(with [`BeforePlugin`][ndmf-BeforePlugin]) in the Optimizing phase.
If your tool removes your components in Optimizing phase, it's highly recommended to specify [`BeforePlugin`][ndmf-BeforePlugin]
even if your default callback order is before `com.anatawa12.avatar-optimizer` plugin.

If your tool is a non-destructive tool not based on NDMF[^NDMF], removing your components before
the NDMF's Optimizing phase is recommended.
In this case, current NDMF executes Optimizing phase in order `-1025`, which is JUST before VRCSDK's `RemoveAvatarEditorOnly`
callback, so your tool should remove components with `IVRCSDKPreprocessAvatarCallback` with smaller `callbackOrder`.
callback, so your tool should remove components with `IVRCSDKPreprocessAvatarCallback` with `callbackOrder` smaller than `-1025`.
anatawa12 marked this conversation as resolved.
Show resolved Hide resolved

If your components is only for holding data for your edit-mode tool and doesn't affects on build or at runtime,
you can remove your components in `IVRCSDKPreprocessAvatarCallback` as described above, or
you can simply use [Asset Description] to register your components as safe-to-remove components
anatawa12 marked this conversation as resolved.
Show resolved Hide resolved

If your components holds some information for your tool and has no meaning on the build time,
removing your components before Avatar Optimizer processes with `IVRCSDKPreprocessAvatarCallback` is recommended.
See above for the ordering of `IVRCSDKPreprocessAvatarCallback`.
[DestroyImmediate]: https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Object.DestroyImmediate.html

### Registering your components {#register-component}

If your tool wants to keep your component after Avatar Optimizer processes,
If you want to keep your component after Avatar Optimizer processes,
you can register your components to Avatar Optimizer to tell about your components.

First, to call APIs of Avatar Optimizer, please make an assembly definition file[^asmdef] if your tool doesn't have.

Next, add `com.anatawa12.avatar-optimizer.api.editor` to assembly references in asmdef file.\
If your tool doesn't want to depends on Avatar Optimizer, please use [Version Defines].
If your tool doesn't want to depend on Avatar Optimizer, please use [Version Defines].
Because Avatar Optimizer didn't have public API prior to 1.6.0 and will break in 2.0.0,
it's recommended to add version range like `[1.6,2.0)`
(or stricter like `[1.7,2.0)` when you need new APIs that can be available in the future).
Expand Down Expand Up @@ -96,8 +135,8 @@ internal class YourComponentInformation : ComponentInformation<YourComponent>
```

In `CollectMutations`, you should register any mutation your component may do.\
In `CollectDependency`, you should register build-time or run-time dependencies of your component.\
Please refer xmldoc and method name for more datails.
In `CollectDependency`, you should register build-time or run-time dependencies and related information of your component.\
Please read xmldoc of each methods for more details.

[fediverse]: https://misskey.niri.la/@anatawa12
[ndmf-BeforePlugin]: https://ndmf.nadena.dev/api/nadena.dev.ndmf.fluent.Sequence.html#nadena_dev_ndmf_fluent_Sequence_BeforePlugin_System_String_System_String_System_Int32_
Expand Down
Loading
Loading