Skip to content

Commit

Permalink
Merge pull request #419 from anatawa12/exclude-from-trace-and-optimize
Browse files Browse the repository at this point in the history
Exclude from Trace and Optimize
  • Loading branch information
anatawa12 authored Sep 6, 2023
2 parents c82153d + c43de59 commit 838391e
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 25 deletions.
5 changes: 3 additions & 2 deletions .docs/content/docs/reference/trace-and-optimize/index.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ aliases:
また、以下の設定で自動設定を調節できます。
- `MMDワールドとの互換性`
MMDワールドで使われるBlendShapeを固定しないなど、MMDワールドとの互換性を考慮した軽量化を行います。
- `Advanced Animator Parserを使用する`
最適化内容を決めるために、AAOはAnimatorControllerを解析します。このオプションを有効にすると、AnimatorControllerのレイヤー構造とBlendTree構造を解析するAdvanced Animator Parserを解析に用います。このオプションを無効にすると、AnimationClipのみを解析するFallback Animator Parserを解析に用います。Fallback Animator Parserは旧式の処理であり、Direct BlendTreeを正しく解析しません。通常、このオプションを無効化する必要はありません。

他に、バグの回避などに使用するための高度な設定がありますが、それらは不安定であり、不用意に変更するべきではありません。
それらの機能については英語のTooltipやソースコード、または開発者の指示を参考にしてください。

![component.png](component.png)
10 changes: 3 additions & 7 deletions .docs/content/docs/reference/trace-and-optimize/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,8 @@ Currently the following optimizations are applied automatically.
Also, You can adjust optimization with the following settings
- `MMD World Compatibility`
Optimize with considering compatibility with MMD Worlds. e.g. Not freezing BlendShapes used by MMD Worlds.
- `Use Advanced Animator Parser`
To determine where AAO can optimize, AAO parses AnimatorControllers.
If this option is enabled, AAO will use Advanced Animator Parser
which parses layer structure of AnimatorController and BlendTree structure.
If this option is disabled, AAO will use Fallback Animator Parser which collects all AnimationClips and
parses AnimationClips. Fallback Animator Parser is an legacy process, so it will parse Direct BlendTree incorrectly.
Normally, you do not need to disable this option.

In addition, there is `Advanced Settings` which is for workaround bugs but it's unstable & not well-tested.
See tooltips or implementation for more details.

![component.png](component.png)
4 changes: 4 additions & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ The format is based on [Keep a Changelog].
- Pre-building validation for MergeBone `#417`
- There are some (rare) cases that are not supported by MergeBone. This adds warning for such case.
- Validation error for self recursive MergeSkinnedMesh `#418`
- Advanced Settings Section for Trace and Optimize `#419`
- Moved `Use Advanced Animator Parser` to there
- Added `Exclusions` for exclude some GameObjects from optimization
- Added `Use Legacy GC` to use legacy algotythm for Remove Unused Objects

### Changed
- Performance: Share MeshInfo2 between SkinnedMesh processing and MergeBone `#421`
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ The format is based on [Keep a Changelog].
- Pre-building validation for MergeBone `#417`
- There are some (rare) cases that are not supported by MergeBone. This adds warning for such case.
- Validation error for self recursive MergeSkinnedMesh `#418`
- Advanced Settings Section for Trace and Optimize `#419`
- Moved `Use Advanced Animator Parser` to there
- Added `Exclusions` for exclude some GameObjects from optimization

### Changed
- Improved 'Remove Unused Objects' `#401`
- Remove Unused Objects now removes unnecessary Components & Bones!
- You may use `Use Legacy GC` to use legacy algotythm for Remove Unused Objects in `Advanced Settings` (`#419`)
- Performance: Share MeshInfo2 between SkinnedMesh processing and MergeBone `#421`

### Deprecated
Expand Down
21 changes: 20 additions & 1 deletion Editor/AutomaticConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using CustomLocalization4EditorExtension;
using UnityEditor;
using UnityEngine;

Expand All @@ -10,13 +11,16 @@ internal class TraceAndOptimizeEditor : AvatarGlobalComponentEditorBase
private SerializedProperty _removeUnusedObjects;
private SerializedProperty _mmdWorldCompatibility;
private SerializedProperty _advancedAnimatorParser;
private SerializedProperty _advancedSettings;
private GUIContent _advancedSettingsLabel = new GUIContent();

private void OnEnable()
{
_freezeBlendShape = serializedObject.FindProperty(nameof(TraceAndOptimize.freezeBlendShape));
_removeUnusedObjects = serializedObject.FindProperty(nameof(TraceAndOptimize.removeUnusedObjects));
_mmdWorldCompatibility = serializedObject.FindProperty(nameof(TraceAndOptimize.mmdWorldCompatibility));
_advancedAnimatorParser = serializedObject.FindProperty(nameof(TraceAndOptimize.advancedAnimatorParser));
_advancedSettings = serializedObject.FindProperty(nameof(TraceAndOptimize.advancedSettings));
}

protected override void OnInspectorGUIInner()
Expand All @@ -26,11 +30,26 @@ protected override void OnInspectorGUIInner()

GUILayout.Label("General Settings", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_mmdWorldCompatibility);
EditorGUILayout.PropertyField(_advancedAnimatorParser);
GUILayout.Label("Features", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_freezeBlendShape);
EditorGUILayout.PropertyField(_removeUnusedObjects);

_advancedSettingsLabel.text = CL4EE.Tr("TraceAndOptimize:prop:advancedSettings");
if (EditorGUILayout.PropertyField(_advancedSettings, _advancedSettingsLabel, false))
{
EditorGUI.indentLevel++;
EditorGUILayout.HelpBox(CL4EE.Tr("TraceAndOptimize:warn:advancedSettings"), MessageType.Warning);
EditorGUILayout.PropertyField(_advancedAnimatorParser);
var iterator = _advancedSettings.Copy();
var enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
EditorGUILayout.PropertyField(iterator);
}
EditorGUI.indentLevel--;
}

serializedObject.ApplyModifiedProperties();
}
}
Expand Down
8 changes: 7 additions & 1 deletion Editor/Processors/TraceAndOptimize/AutoFreezeBlendShape.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
Expand All @@ -9,11 +10,14 @@ class AutoFreezeBlendShape
{
private readonly ImmutableModificationsContainer _modifications;
private readonly OptimizerSession _session;
private readonly HashSet<GameObject> _exclusions;

public AutoFreezeBlendShape(ImmutableModificationsContainer modifications, OptimizerSession session)
public AutoFreezeBlendShape(ImmutableModificationsContainer modifications, OptimizerSession session,
HashSet<GameObject> exclusions)
{
_modifications = modifications;
_session = session;
_exclusions = exclusions;
}

public void Process()
Expand All @@ -25,6 +29,7 @@ public void Process()

// skip SMR without mesh
if (!mesh) continue;
if (_exclusions.Contains(skinnedMeshRenderer.gameObject)) continue; // manual exclusiton

var modifies = _modifications.GetModifiedProperties(skinnedMeshRenderer);
var blendShapeValues = Enumerable.Range(0, mesh.blendShapeCount)
Expand Down Expand Up @@ -69,6 +74,7 @@ public void Process()
// second optimization: remove meaningless blendShapes
foreach (var skinnedMeshRenderer in _session.GetComponents<SkinnedMeshRenderer>())
{
if (_exclusions.Contains(skinnedMeshRenderer.gameObject)) continue; // manual exclusion
skinnedMeshRenderer.gameObject.GetOrAddComponent<FreezeBlendShape>();
skinnedMeshRenderer.gameObject.GetOrAddComponent<InternalAutoFreezeMeaninglessBlendShape>();
}
Expand Down
22 changes: 20 additions & 2 deletions Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,25 @@ class FindUnusedObjectsProcessor
{
private readonly ImmutableModificationsContainer _modifications;
private readonly OptimizerSession _session;
private readonly HashSet<GameObject> _exclusions;
private readonly bool _useLegacyGC;

public FindUnusedObjectsProcessor(ImmutableModificationsContainer modifications, OptimizerSession session)
public FindUnusedObjectsProcessor(ImmutableModificationsContainer modifications, OptimizerSession session,
bool useLegacyGC,
HashSet<GameObject> exclusions)
{
_modifications = modifications;
_session = session;
_useLegacyGC = useLegacyGC;
_exclusions = exclusions;
}

public void Process()
{
ProcessNew();
if (_useLegacyGC)
ProcessLegacy();
else
ProcessNew();
}

// Mark & Sweep Variables
Expand Down Expand Up @@ -80,6 +89,11 @@ private void ProcessNew()
if (collector.GetDependencies(component).EntrypointComponent)
MarkComponent(component, true);

// excluded GameObjects must be exists
foreach (var gameObject in _exclusions)
foreach (var component in gameObject.GetComponents<Component>())
MarkComponent(component, true);

while (_processPending.Count != 0)
{
var (component, canBeActive) = _processPending.Dequeue();
Expand Down Expand Up @@ -166,6 +180,10 @@ void AddGameObject(GameObject gameObject)
AddGameObject(transform.gameObject);
}

// entry points: active GameObjects
foreach (var gameObject in _exclusions)
AddGameObject(gameObject);

while (newReferenced.Count != 0)
{
var gameObject = newReferenced.Dequeue();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Anatawa12.AvatarOptimizer.Processors.TraceAndOptimizes;
using JetBrains.Annotations;
using UnityEngine;
Expand All @@ -8,24 +9,28 @@ internal class TraceAndOptimizeProcessor
{
private ImmutableModificationsContainer _modifications;
[CanBeNull] private TraceAndOptimize _config;
private HashSet<GameObject> _exclusions;

public void Process(OptimizerSession session)
{
_config = session.GetRootComponent<TraceAndOptimize>();
if (_config is null) return;
Object.DestroyImmediate(_config);
_exclusions = new HashSet<GameObject>(_config.advancedSettings.exclusions);

_modifications = new AnimatorParser(_config).GatherAnimationModifications(session);
if (_config.freezeBlendShape)
new AutoFreezeBlendShape(_modifications, session).Process();
new AutoFreezeBlendShape(_modifications, session, _exclusions).Process();
}

public void ProcessLater(OptimizerSession session)
{
if (_config is null) return;

if (_config.removeUnusedObjects)
new FindUnusedObjectsProcessor(_modifications, session).Process();
new FindUnusedObjectsProcessor(_modifications, session, _config.advancedSettings.useLegacyGc,
_exclusions).Process();

}
}
}
10 changes: 6 additions & 4 deletions Localization/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -369,11 +369,13 @@ msgstr "MMD World Compatibility"
msgid "TraceAndOptimize:tooltip:mmdWorldCompatibility"
msgstr "Enable MMD World Compatibility features such as keeping some BlendShapes"

msgid "TraceAndOptimize:prop:advancedAnimatorParser"
msgstr "Use Advanced Animator Parser"
msgid "TraceAndOptimize:prop:advancedSettings"
msgstr "Advanced Settings"

msgid "TraceAndOptimize:tooltip:advancedAnimatorParser"
msgstr "Advanced Animator Parser will parse your AnimatorController, including layer structure."
msgid "TraceAndOptimize:warn:advancedSettings"
msgstr "Advanced Settings is for workaround bugs in Avatar Optimizer.\n"
"Changing Advanced Settings will make your avatar non well-optimized.\n"
"In addition, Some modification of Advanced Settings may not well-tested or its behaviour is likely to be changed. Be careful!"

msgid "TraceAndOptimize:warn:unknown-type"
msgstr "Unknown Component Type '{0}' Found. This will reduce optimization performance and may break your Avatar."
Expand Down
10 changes: 6 additions & 4 deletions Localization/ja.po
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,13 @@ msgstr "MMDワールドとの互換性"
msgid "TraceAndOptimize:tooltip:mmdWorldCompatibility"
msgstr "MMD用BlendShapeを固定しないなどのMMDワールドとの互換性機能を有効化します"

msgid "TraceAndOptimize:prop:advancedAnimatorParser"
msgstr "Advanced Animator Parserを使用する"
msgid "TraceAndOptimize:prop:advancedSettings"
msgstr "高度な設定"

msgid "TraceAndOptimize:tooltip:advancedAnimatorParser"
msgstr "Advanced Animator ParserはAnimatorControllerを「レイヤー構造も含めて」解析します。"
msgid "TraceAndOptimize:warn:advancedSettings"
msgstr "高度な設定はAvatarOptimizerのバグを回避するための設定です。\n"
"高度な設定を変更すると、アバターが適切に最適化されなくなる可能性があります。\n"
"また、一部の高度な設定の変更は正しく機能しなかったり、その動作が変更される可能性があります。注意してください!"

msgid "TraceAndOptimize:warn:unknown-type"
msgstr "未知のコンポーネント'{0}'を検出しました! これにより最適化処理の品質が低下し、処理後のアバターが壊れる可能性があります。(元のアバターには影響しません)"
Expand Down
19 changes: 17 additions & 2 deletions Runtime/TraceAndOptimize.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using CustomLocalization4EditorExtension;
using UnityEngine;

Expand All @@ -21,9 +22,23 @@ internal class TraceAndOptimize : AvatarGlobalComponent
"TraceAndOptimize:tooltip:mmdWorldCompatibility")]
[ToggleLeft]
public bool mmdWorldCompatibility = true;
[CL4EELocalized("TraceAndOptimize:prop:advancedAnimatorParser",
"TraceAndOptimize:tooltip:advancedAnimatorParser")]

// for compatibility, this is not inside AdvancedSettings but this is part of Advanced Settings
[InspectorName("Use Advanced Animator Parser")]
[Tooltip("Advanced Animator Parser will parse your AnimatorController, including layer structure.")]
[ToggleLeft]
public bool advancedAnimatorParser = true;

public AdvancedSettings advancedSettings;

[Serializable]
public struct AdvancedSettings
{
[Tooltip("Exclude some GameObjects from Trace and Optimize")]
public GameObject[] exclusions;
[Tooltip("Use Legacy algorithm for Remove Unused Objects")]
[ToggleLeft]
public bool useLegacyGc;
}
}
}

0 comments on commit 838391e

Please sign in to comment.