Skip to content

fix: YooAsset native builder support, bundle granularity, and dropdown stale values (#631, #632)#633

Merged
JasonXuDeveloper merged 8 commits intomasterfrom
fix/issues-631-632
Apr 23, 2026
Merged

fix: YooAsset native builder support, bundle granularity, and dropdown stale values (#631, #632)#633
JasonXuDeveloper merged 8 commits intomasterfrom
fix/issues-631-632

Conversation

@JasonXuDeveloper
Copy link
Copy Markdown
Owner

Summary

Addresses two reporter issues plus a related UX gap found during review.

Fixes #632 — YooAsset native builder + bundle granularity

  1. MissingMethodException when building with YooAsset's AssetBundleBuilder
    YooAsset's BuildPipelineViewerBase.CreateEncryptionServicesInstance() calls Activator.CreateInstance(type) with no arguments, but JEngine's {Aes,Xor,ChaCha20}EncryptionServices and {Aes,Xor,ChaCha20}Manifest{Process,Restore} only exposed config-taking constructors. Added parameterless default constructors that chain to the existing ones via *Config.Instance (the same singleton JEngine's internal BundleEncryptionConfig<…> already resolves). Existing internal instantiation — which passes the config via Activator.CreateInstance(type, new object[] { config }) — still matches the parameterized overload, so no behavior change for the JEngine panel path.

  2. JEngine output had fewer/larger bundles than YooAsset's native builder for identical collector configs
    Root cause: YooAsset's ScriptableBuildPipelineViewer.ExecuteBuild (and BuiltinBuildPipelineViewer) both set buildParameters.EnableSharePackRule = true, but JEngine's BuildManager.CreateBuildParameters() omitted it, falling back to the BuildParameters.cs default of false. With it disabled, YooAsset's TaskGetBuildMap step 7 skips shared-bundle extraction entirely, inlining shared assets into every referencing bundle — producing fewer/larger bundles and duplicated payload. Matches the reporter's screenshot. Fix: set EnableSharePackRule = true in BuildManager. Other build params (LZ4, HashName, StripUnityVersion, TrackSpriteAtlasDependencies) already match YooAsset UI defaults or are intentional JEngine overrides.

Fixes #631 — Dropdowns show stale values after YooAsset package rename

  • BootstrapEditorUI (inspector) and the Build Panel (SettingsUIBuilder + PanelUI) passed the serialized value as the PopupField default without checking it existed in the choices list. When a YooAsset package was renamed, Unity's PopupField silently fell back to index 0 without firing a change event — UI and serialized value desynced. Single-entry dropdowns exhibited the same class of issue.
  • Fix: prepend a "None" sentinel so every dropdown has ≥ 2 entries; when the stored value isn't in the current choices it displays as None; selecting None clears the stored value to empty. Applied uniformly to the 7 dropdowns in BootstrapEditorUI, the Package dropdown in SettingsUIBuilder, and the (previously missed) Package dropdown in PanelUI.

Related improvements (not reported, found during review)

  • DRY: Extracted WithNoneOption / ResolveDropdownValue / NormalizeDropdownSelection + NoneDropdownOption into JEngine.Core.Editor.EditorUtils. All three call sites now share the same implementation.
  • Auto-refresh on external change: The Bootstrap inspector polls a signature of external dropdown sources (packages, asmdefs, scenes, classes/methods, AOT files, dynamic keys) every 500ms and rebuilds when it changes, plus rebuilds on EditorApplication.focusChanged. The Build Panel (EditorWindow) rebuilds on OnFocus (skipped mid-build). A package rename in the AssetBundle Collector window now propagates without requiring the user to reselect the asset.

Chore

  • Rebuilt the main asset package and hot-update AOT assemblies with EnableSharePackRule = true so a fresh clone of this branch runs without a manual rebuild. Old monolithic bundles are removed; new share-pack-split bundles are committed.

PR strategy

Per discussion the PR should be merged via "Rebase and merge" so all six commits land on master individually with their own scopes, rather than squash-merged.

Test plan

  • In JEngine Bootstrap panel, pick AES → Open YooAsset's AssetBundleBuilder → select AesEncryptionServices (+ matching manifest services) → build succeeds (previously MissingMethodException). Repeat for XOR and ChaCha20.
  • Same collector config, build once via JEngine panel, once via YooAsset's builder — bundle counts/sizes now match within rounding.
  • Open Bootstrap inspector with packageName = "main". In AssetBundle Collector, rename the sole package to game. Dropdown updates to None within 500ms without reselecting the asset (polling). Selecting game persists.
  • Same rename scenario with Build Panel open: on focus return it rebuilds and shows None.
  • Start a build, switch focus away and back to the Build Panel mid-build — content is not rebuilt (build state preserved).
  • Undo/redo still rebuilds inspector content (existing behavior unchanged).
  • Fresh clone of this branch opens and plays without a manual "Build All".

JasonXuDeveloper and others added 6 commits April 23, 2026 19:30
Two fixes for issue #632:

1. Add parameterless default constructors to all build-time encryption
   and manifest services (Aes/Xor/ChaCha20 EncryptionServices,
   ManifestProcess, ManifestRestore). Each chains to the existing
   config-taking constructor using the *Config.Instance singleton,
   which is the same instance JEngine's internal BundleEncryptionConfig
   resolves to. YooAsset's AssetBundleBuilder calls
   Activator.CreateInstance(type) with no args, so the previous
   config-only constructors threw MissingMethodException when selected
   via the YooAsset panel.

2. Set EnableSharePackRule = true in BuildManager.CreateBuildParameters.
   YooAsset's own ScriptableBuildPipelineViewer and
   BuiltinBuildPipelineViewer both set this (YooAsset 2.3.18, line 116
   of each), but JEngine left it at the BuildParameters default of
   false. With it off, TaskGetBuildMap skips shared-bundle extraction,
   inlining shared assets into every referencing bundle - producing
   fewer, larger bundles than the YooAsset UI would for the same
   collector config.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
BootstrapEditorUI dropdowns (Package, Hot Code Assembly, Hot Scene,
Entry Class/Method, AOT DLL List, Dynamic Secret Key) passed the
serialized value as JDropdown's default without checking it existed
in the choices list. When a YooAsset package was renamed or a
collector had only one entry, Unity's PopupField silently fell back
to index 0 without firing a change event - so the UI displayed a
different value than what was serialized, and selecting the same
visible entry did not sync them.

Prepend a "None" sentinel to every dropdown and route through
ResolveCurrentOption / NormalizeSelection helpers. This guarantees
at least two entries per dropdown (sidestepping Unity PopupField
single-item quirks), shows "None" when the stored value is missing
from the current choices, and clears the stored value to empty when
the user selects "None".

Closes #631

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
SettingsUIBuilder.CreatePackageSettingsGroup had the same pattern as
the Bootstrap inspector fields: it passed settings.packageName as the
PopupField value without verifying it existed in the choices list,
so a renamed YooAsset package still showed the stale value.

Mirror the Bootstrap fix: prepend a "None" sentinel to the choices,
resolve the current value through a null/not-contained check, and
clear the stored value to empty when "None" is selected.

Part of #631

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
Extract WithNoneOption / ResolveDropdownValue / NormalizeDropdownSelection
plus the NoneDropdownOption constant into EditorUtils so the three
package-dropdown call sites (SettingsUIBuilder, BootstrapEditorUI,
PanelUI) no longer each reimplement the same sentinel / fallback /
clear-on-None logic.

Additionally override Panel.OnFocus to rebuild its content when the
window regains focus, so the Package dropdown reflects renames made
in the AssetBundle Collector window without having to close and
reopen the Panel. Skipped while a build is in progress to avoid
losing BuildManager state and the log view contents.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
…nges

BootstrapEditorUI now calls EditorUtils.WithNoneOption /
ResolveDropdownValue / NormalizeDropdownSelection instead of its own
local copies, and PanelUI's Package dropdown now uses the same
helpers (previously missed in the earlier #631 fix - it still showed
the stale package name after a rename).

Also add a 500ms polling check on the Bootstrap inspector that
compares a signature of the external data sources (packages, asmdefs,
scenes, classes, methods, AOT files, dynamic keys) and rebuilds the
inspector when they change. Combined with the existing undo/redo
handler and a new EditorApplication.focusChanged listener, this means
a package rename in the AssetBundle Collector propagates to the
Bootstrap inspector without the user having to reselect the asset.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
Rebuild hot update code and main asset package after the build
pipeline changes in this branch so a fresh clone runs without a
manual rebuild. Bundles are now split via EnableSharePackRule=true;
old monolithic bundles are removed.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 23, 2026

Unity Test Results

EditMode: All tests passed
PlayMode: All tests passed

Unity Version: 2022.3.55f1
Project Path: UnityProject

✅ All tests passed! The PR is ready for review.

View workflow run

Click here to view the full workflow run

OnDetachFromPanel no longer takes an Undo.UndoRedoCallback token -
after the focus-refresh refactor it unregisters from statically-known
handlers (OnUndoRedo, OnEditorFocusChanged) directly. Update the test
to call the method with just the event argument.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
@github-actions github-actions Bot added the tests label Apr 23, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 95.81152% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.99%. Comparing base (7193761) to head (a8b8094).
⚠️ Report is 13 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #633      +/-   ##
==========================================
+ Coverage   94.91%   94.99%   +0.07%     
==========================================
  Files          70       71       +1     
  Lines       10431    10583     +152     
==========================================
+ Hits         9901    10053     +152     
  Misses        530      530              
Flag Coverage Δ
ui 95.44% <95.81%> (+0.08%) ⬆️
util 93.19% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Adds EditorUtilsTests for the new WithNoneOption / ResolveDropdownValue
/ NormalizeDropdownSelection helpers, plus roundtrip tests mirroring
the rename-then-display-as-None flow.

Adds BootstrapEditorUI tests for the new refresh paths:
OnEditorFocusChanged (both hasFocus=true rebuild and hasFocus=false
early-return), ComputeExternalDataSignature (stability + formatting),
and CheckForExternalDataChanges (early-return on match, rebuild on
mismatch).

Adds Panel.OnFocus tests covering the null-root guard and the
IsBuilding guard that preserves BuildManager state + log view
contents during an in-progress build.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
@JasonXuDeveloper JasonXuDeveloper enabled auto-merge (rebase) April 23, 2026 10:28
@JasonXuDeveloper JasonXuDeveloper merged commit 96c010f into master Apr 23, 2026
20 checks passed
@JasonXuDeveloper JasonXuDeveloper deleted the fix/issues-631-632 branch April 23, 2026 10:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant