Skip to content

Commit b9e20ba

Browse files
committed
Reject empty replay files before WebGL loading churn
High-frequency replay switching included a zero-byte sample, which could still enter the browser-to-Unity load path and add avoidable request, parse, status, and GC churn during stress. The bridge now treats an explicitly reported zero-size file as an immediate player-facing failure while leaving normal URL callers without size metadata untouched. Constraint: Competition package stability favors a narrow Playback-side fix over a replay parser rewrite. Rejected: Revoke blob object URLs from Unity after terminal load | stress testing showed this can make high-frequency blob loads less stable. Rejected: Abort and dispose active UnityWebRequest from PreparePlaybackLoad | stress testing showed this can worsen WebGL hangs under rapid blob switching. Confidence: medium Scope-risk: narrow Directive: Do not add aggressive blob revocation or UnityWebRequest disposal on the C# side without rerunning high-frequency WebGL replay stress. Tested: dotnet format whitespace --folder interface/Unity/Unity-Playback/Assets/Scripts --verify-no-changes Tested: Unity batchmode WebGL Playback build via WebGLBuildScript.BuildWebGL Tested: Playback zip extracted and SHA256-compared against interface/Unity/Unity-WebGL/playback, 17/17 files matched Tested: Three headless Chrome WebGL stress rounds, 80 random rapid loads each across playback (2), playback (1), and playback.thuaipb, no JS exceptions or permanent hang Not-tested: Full lazy/streaming replay parser redesign for eliminating 3-5 second main-thread parse long tasks
1 parent 43bfa5b commit b9e20ba

6 files changed

Lines changed: 22 additions & 4 deletions

File tree

interface/Unity/Unity-Playback/Assets/Scripts/WebGL/WebGLFrameBridge.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ public void SetPlaybackFile(string payload)
7474
if (playbackController == null) { DispatchEvent("playback-error", "missing-playback-controller"); return; }
7575
uiController?.SetPlaybackPathDisplay(selection.name ?? selection.url);
7676
DispatchEvent("playback-loading", selection.name ?? selection.url);
77+
if (selection.size == 0)
78+
{
79+
string status = "状态:回放文件为空,请选择有效的 .thuaipb 文件";
80+
playbackController.RejectPlaybackLoad(selection.url, selection.name, status);
81+
DispatchEvent("playback-error", "file-empty");
82+
return;
83+
}
84+
7785
if (selection.size > PlaybackController.MaxRemotePlaybackBytes)
7886
{
7987
string status = $"状态:回放文件过大({selection.size} 字节)";
@@ -228,7 +236,17 @@ private static PlaybackSelection ParsePlaybackSelection(string payload)
228236
if (string.IsNullOrWhiteSpace(payload)) return null;
229237
string trimmed = payload.Trim();
230238
if (!trimmed.StartsWith("{", StringComparison.Ordinal)) return new PlaybackSelection { url = trimmed.Trim('"'), name = trimmed.Trim('"') };
231-
try { return JsonUtility.FromJson<PlaybackSelection>(trimmed); } catch { return new PlaybackSelection { url = trimmed }; }
239+
try
240+
{
241+
PlaybackSelection selection = JsonUtility.FromJson<PlaybackSelection>(trimmed);
242+
if (trimmed.IndexOf("\"size\"", StringComparison.OrdinalIgnoreCase) < 0)
243+
{
244+
selection.size = -1;
245+
}
246+
247+
return selection;
248+
}
249+
catch { return new PlaybackSelection { url = trimmed }; }
232250
}
233251

234252
private static PlaybackDataSelection ParsePlaybackDataSelection(string payload)
@@ -264,7 +282,7 @@ private static string NormalizeBase64Payload(string base64)
264282
.Replace("\t", string.Empty);
265283
}
266284

267-
[Serializable] private class PlaybackSelection { public string url; public string name; public long size; }
285+
[Serializable] private class PlaybackSelection { public string url; public string name; public long size = -1; }
268286
[Serializable] private class PlaybackDataSelection { public string data; public string name; }
269287
[Serializable]
270288
private class PlaybackStatus
106 Bytes
Binary file not shown.
104 Bytes
Binary file not shown.

interface/Unity/Unity-WebGL/playback/Build/playback.framework.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
359 Bytes
Binary file not shown.

interface/Unity/Unity-WebGL/playback/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
}
5858

5959
var thuai9Mode = 'playback';
60-
var thuai9BuildStamp = '639152606370429751';
60+
var thuai9BuildStamp = '639152674144621830';
6161
var thuai9Query = new URLSearchParams(window.location.search);
6262
function thuai9CacheBust(url) {
6363
return url + (url.indexOf('?') >= 0 ? '&' : '?') + 'v=' + encodeURIComponent(thuai9BuildStamp);

0 commit comments

Comments
 (0)