Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public enum WarmUpStage

private bool panelOpenRequested;

private bool contentEditSignaled;
private string? contentEditSrc;

private WarmUpStage warmUpStage;
private string? warmUpSceneId;
private float warmUpElapsedSeconds;
Expand Down Expand Up @@ -280,6 +283,36 @@ public bool TryConsumePanelOpenRequest()
}
}

/// <summary>
/// Signals that the LSD preview server reported a content edit, so the scene's bundles are about
/// to be reconverted. <paramref name="changedSrc" /> names the edited model when the message
/// carried one (UpdateModel); null for whole-scene updates. Rapid successive edits keep the
/// latest name — one reconversion pass covers them all.
/// </summary>
public void OnContentEdit(string? changedSrc)
{
lock (gate)
{
contentEditSignaled = true;

// Protobuf strings default to "" — treat that as an unnamed (whole-scene) edit.
contentEditSrc = string.IsNullOrEmpty(changedSrc) ? null : changedSrc;
}
}

/// <summary>True once per <see cref="OnContentEdit" /> burst — consuming it resets the signal.</summary>
public bool TryConsumeContentEdit(out string? changedSrc)
{
lock (gate)
{
bool signaled = contentEditSignaled;
changedSrc = contentEditSrc;
contentEditSignaled = false;
contentEditSrc = null;
return signaled;
}
}

/// <summary>Adds an informational row to the panel without touching the counters.</summary>
public void OnMilestone(string message)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#nullable enable

namespace ECS.StreamableLoading.AssetBundles
{
/// <summary>
/// Hand-off of the abgen sidecar's already-fetched scene manifest to the scene loading lane.
/// Boot holds on the warm-up's manifest request and the reconversion watcher re-fetches it after
/// every content edit, so when the scene lane asks for the same URL the response is already in
/// hand — reusing it removes the server's content revalidation (seconds on a large scene) from
/// the scene-entry critical path. Single entry: local scene development serves exactly one scene.
/// </summary>
public static class AbgenManifestPrewarm
{
private static readonly object GATE = new ();

private static string? url;
private static string? json;

/// <summary>Stores the manifest response fetched from <paramref name="manifestUrl" />, replacing any previous entry.</summary>
public static void Set(string manifestUrl, string manifestJson)
{
lock (GATE)
{
url = manifestUrl;
json = manifestJson;
}
}

/// <summary>Drops the stored manifest. Called on a preview content edit, which may change the file census.</summary>
public static void Invalidate()
{
lock (GATE)
{
url = null;
json = null;
}
}

/// <summary>True when a manifest fetched from exactly <paramref name="manifestUrl" /> is held; the entry stays for scene reloads.</summary>
public static bool TryGet(string manifestUrl, out string manifestJson)
{
lock (GATE)
{
if (url == manifestUrl && json != null)
{
manifestJson = json;
return true;
}

manifestJson = string.Empty;
return false;
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,21 @@ private async UniTask<SceneAssetBundleManifest> LoadAssetBundleManifestAsync(str
.AppendPath(URLPath.FromString($"{hash}{PlatformUtils.GetCurrentPlatform()}.json"));

URLAddress url = urlBuilder.Build();
SceneAbDto sceneAbDto = await webRequestController.GetAsync(new CommonArguments(url, RetryPolicy.WithRetries(1)), ct, reportCategory)
.CreateFromJson<SceneAbDto>(WRJsonParser.Newtonsoft, WRThreadFlags.SwitchBackToMainThread);

// In local-ab the abgen sidecar already fetched this exact manifest — boot holds on the
// warm-up's request, and the reconversion watcher re-fetches after every content edit — so
// reuse the held response instead of paying the server's content revalidation a second time
// on the scene-entry critical path. Empty outside that flow.
SceneAbDto sceneAbDto;

if (AbgenManifestPrewarm.TryGet(url.Value, out string prewarmedJson))
{
sceneAbDto = JsonUtility.FromJson<SceneAbDto>(prewarmedJson);
ReportHub.Log(ReportCategory.ASSET_BUNDLES, $"manifest for {hash} served from the abgen warm-up hand-off (no re-fetch)");
}
else
sceneAbDto = await webRequestController.GetAsync(new CommonArguments(url, RetryPolicy.WithRetries(1)), ct, reportCategory)
.CreateFromJson<SceneAbDto>(WRJsonParser.Newtonsoft, WRThreadFlags.SwitchBackToMainThread);

CheckSceneAbDTO(sceneAbDto.Version, hash);

Expand Down
Loading
Loading