app.hypergames.hypersdk 1.8.13 → 1.8.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/Editor/Scripts/Build/HyperBuildPipeline.cs +840 -0
- package/Editor/Scripts/Build/HyperBuildPipeline.cs.meta +2 -0
- package/Editor/Scripts/Tools/HyperBuildAssistant.cs +42 -509
- package/Runtime/Internal/ScriptableObjects/HyperGameContentConfig.cs +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
#if UNITY_EDITOR
|
|
2
|
+
using System;
|
|
3
|
+
using System.IO;
|
|
4
|
+
using UnityEditor;
|
|
5
|
+
using UnityEditor.Build;
|
|
6
|
+
using UnityEditor.Build.Reporting;
|
|
7
|
+
using UnityEditor.SceneManagement;
|
|
8
|
+
using UnityEngine;
|
|
9
|
+
using UnityEngine.SceneManagement;
|
|
10
|
+
using Hyper.Internal;
|
|
11
|
+
|
|
12
|
+
namespace Hyper.Editor
|
|
13
|
+
{
|
|
14
|
+
internal enum HyperBuildProfile
|
|
15
|
+
{
|
|
16
|
+
Development,
|
|
17
|
+
Release
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
internal sealed class HyperBuildRequest
|
|
21
|
+
{
|
|
22
|
+
public HyperBuildProfile Profile { get; set; }
|
|
23
|
+
public string OutputPath { get; set; } = "";
|
|
24
|
+
public bool CleanOutputFolder { get; set; } = true;
|
|
25
|
+
public bool OpenOutputFolder { get; set; } = false;
|
|
26
|
+
public bool IsCliBuild { get; set; } = false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
internal sealed class HyperBuildResult
|
|
30
|
+
{
|
|
31
|
+
public bool Succeeded { get; set; }
|
|
32
|
+
public BuildResult BuildResult { get; set; } = BuildResult.Unknown;
|
|
33
|
+
public string OutputPath { get; set; } = "";
|
|
34
|
+
public string Message { get; set; } = "";
|
|
35
|
+
public long TotalSizeBytes { get; set; }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
internal static class HyperBuildPipeline
|
|
39
|
+
{
|
|
40
|
+
internal static HyperGameContentConfig _gameContentConfig;
|
|
41
|
+
internal static HyperSDKSettings _sdkSettings;
|
|
42
|
+
private const string ReleaseDefine = "HYPER_RELEASE_BUILD";
|
|
43
|
+
private const string DevelopmentDefine = "HYPER_DEVELOPMENT_BUILD";
|
|
44
|
+
|
|
45
|
+
private struct BuildSettingsSnapshot
|
|
46
|
+
{
|
|
47
|
+
public bool HasCodeOptimization;
|
|
48
|
+
public object CodeOptimizationValue;
|
|
49
|
+
|
|
50
|
+
public bool HasDebugSymbolMode;
|
|
51
|
+
public object DebugSymbolModeValue;
|
|
52
|
+
|
|
53
|
+
public bool HasExceptionSupport;
|
|
54
|
+
public WebGLExceptionSupport ExceptionSupportValue;
|
|
55
|
+
|
|
56
|
+
public bool HasIl2CppCodeGeneration;
|
|
57
|
+
public Il2CppCodeGeneration Il2CppCodeGenerationValue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
internal static HyperBuildResult Build(HyperBuildRequest request)
|
|
61
|
+
{
|
|
62
|
+
if (request == null)
|
|
63
|
+
{
|
|
64
|
+
return Fail("Build request is null.");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (string.IsNullOrWhiteSpace(request.OutputPath))
|
|
68
|
+
{
|
|
69
|
+
return Fail("Build output path is missing.");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (EditorApplication.isCompiling)
|
|
73
|
+
{
|
|
74
|
+
return Fail("Unity is compiling. Please wait for compilation to finish before building.");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!ValidateConfigurationAssets(request.Profile))
|
|
78
|
+
{
|
|
79
|
+
return Fail("Configuration assets are not valid. Please configure the Hyper SDK assets correctly.");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
HyperBuildAssistant.ClearBuildInfo();
|
|
83
|
+
HyperBuildAssistant.ResetOptimizationSummary();
|
|
84
|
+
|
|
85
|
+
BuildSettingsSnapshot settingsSnapshot = CaptureBuildSettingsSnapshot();
|
|
86
|
+
|
|
87
|
+
try
|
|
88
|
+
{
|
|
89
|
+
PrepareBuildOutputDirectory(request.OutputPath, request.CleanOutputFolder);
|
|
90
|
+
|
|
91
|
+
ForceAssetRepack();
|
|
92
|
+
|
|
93
|
+
ApplyProfileSettings(request.Profile);
|
|
94
|
+
|
|
95
|
+
BuildPlayerOptions buildOptions = new BuildPlayerOptions
|
|
96
|
+
{
|
|
97
|
+
scenes = GetEnabledScenes(),
|
|
98
|
+
locationPathName = request.OutputPath,
|
|
99
|
+
target = BuildTarget.WebGL,
|
|
100
|
+
options = BuildOptions.DetailedBuildReport
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
string profileLabel = request.Profile == HyperBuildProfile.Development
|
|
104
|
+
? "Development"
|
|
105
|
+
: "Release";
|
|
106
|
+
|
|
107
|
+
HyperDebug.Action($"Starting {profileLabel} Build to: {request.OutputPath}");
|
|
108
|
+
|
|
109
|
+
BuildReport report = BuildPipeline.BuildPlayer(buildOptions);
|
|
110
|
+
|
|
111
|
+
bool succeeded = report.summary.result == BuildResult.Succeeded;
|
|
112
|
+
|
|
113
|
+
if (succeeded)
|
|
114
|
+
{
|
|
115
|
+
HyperDebug.LogSuccess($"{profileLabel} build completed successfully");
|
|
116
|
+
|
|
117
|
+
HyperBuildAssistant.UpdateBuildInfo(request.OutputPath, report);
|
|
118
|
+
|
|
119
|
+
if (request.OpenOutputFolder)
|
|
120
|
+
{
|
|
121
|
+
HyperBuildAssistant.OpenBuildOutputFolder(request.OutputPath);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return new HyperBuildResult
|
|
125
|
+
{
|
|
126
|
+
Succeeded = true,
|
|
127
|
+
BuildResult = report.summary.result,
|
|
128
|
+
OutputPath = request.OutputPath,
|
|
129
|
+
TotalSizeBytes = (long)report.summary.totalSize,
|
|
130
|
+
Message = $"{profileLabel} build completed successfully."
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
HyperDebug.LogError($"{profileLabel} build failed: {report.summary.result}");
|
|
135
|
+
|
|
136
|
+
HyperBuildAssistant.UpdateBuildInfo(request.OutputPath, null);
|
|
137
|
+
|
|
138
|
+
return new HyperBuildResult
|
|
139
|
+
{
|
|
140
|
+
Succeeded = false,
|
|
141
|
+
BuildResult = report.summary.result,
|
|
142
|
+
OutputPath = request.OutputPath,
|
|
143
|
+
TotalSizeBytes = (long)report.summary.totalSize,
|
|
144
|
+
Message = $"{profileLabel} build failed: {report.summary.result}"
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
catch (Exception ex)
|
|
148
|
+
{
|
|
149
|
+
HyperDebug.LogError($"Hyper build failed: {ex.Message}\n{ex.StackTrace}");
|
|
150
|
+
|
|
151
|
+
HyperBuildAssistant.UpdateBuildInfo(request.OutputPath, null);
|
|
152
|
+
|
|
153
|
+
return new HyperBuildResult
|
|
154
|
+
{
|
|
155
|
+
Succeeded = false,
|
|
156
|
+
BuildResult = BuildResult.Failed,
|
|
157
|
+
OutputPath = request.OutputPath,
|
|
158
|
+
Message = ex.Message
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
finally
|
|
162
|
+
{
|
|
163
|
+
RestoreBuildSettingsSnapshot(settingsSnapshot);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private static HyperBuildResult Fail(string message)
|
|
168
|
+
{
|
|
169
|
+
HyperDebug.LogError(message);
|
|
170
|
+
|
|
171
|
+
return new HyperBuildResult
|
|
172
|
+
{
|
|
173
|
+
Succeeded = false,
|
|
174
|
+
BuildResult = BuildResult.Failed,
|
|
175
|
+
Message = message
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private static void PrepareBuildOutputDirectory(string outputPath, bool cleanOutputFolder)
|
|
180
|
+
{
|
|
181
|
+
if (!cleanOutputFolder)
|
|
182
|
+
{
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!Directory.Exists(outputPath))
|
|
187
|
+
{
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try
|
|
192
|
+
{
|
|
193
|
+
Directory.Delete(outputPath, true);
|
|
194
|
+
|
|
195
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
196
|
+
{
|
|
197
|
+
HyperDebug.Log($"Cleaned existing build folder: {outputPath}");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (Exception ex)
|
|
201
|
+
{
|
|
202
|
+
HyperDebug.LogWarning($"Could not clean build folder: {ex.Message}");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private static void ApplyProfileSettings(HyperBuildProfile profile)
|
|
207
|
+
{
|
|
208
|
+
switch (profile)
|
|
209
|
+
{
|
|
210
|
+
case HyperBuildProfile.Development:
|
|
211
|
+
SetBuildDefineSymbols(isRelease: false);
|
|
212
|
+
ApplyDevelopmentBuildSettings();
|
|
213
|
+
break;
|
|
214
|
+
|
|
215
|
+
case HyperBuildProfile.Release:
|
|
216
|
+
SetBuildDefineSymbols(isRelease: true);
|
|
217
|
+
HyperBuildAssistant.AddOptimizationSummary("Runtime: Unity debug logger disabled in player (HYPER_RELEASE_BUILD)");
|
|
218
|
+
ApplyReleaseBuildSettings();
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
default:
|
|
222
|
+
throw new ArgumentOutOfRangeException(nameof(profile), profile, "Unknown Hyper build profile.");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private static BuildSettingsSnapshot CaptureBuildSettingsSnapshot()
|
|
227
|
+
{
|
|
228
|
+
var snapshot = new BuildSettingsSnapshot();
|
|
229
|
+
|
|
230
|
+
try
|
|
231
|
+
{
|
|
232
|
+
Type webglType = typeof(PlayerSettings.WebGL);
|
|
233
|
+
|
|
234
|
+
var codeOptProp = webglType.GetProperty("codeOptimization");
|
|
235
|
+
if (codeOptProp != null)
|
|
236
|
+
{
|
|
237
|
+
snapshot.CodeOptimizationValue = codeOptProp.GetValue(null);
|
|
238
|
+
snapshot.HasCodeOptimization = true;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
var debugSymbolProp = webglType.GetProperty("debugSymbolMode");
|
|
242
|
+
if (debugSymbolProp != null)
|
|
243
|
+
{
|
|
244
|
+
snapshot.DebugSymbolModeValue = debugSymbolProp.GetValue(null);
|
|
245
|
+
snapshot.HasDebugSymbolMode = true;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
catch (Exception ex)
|
|
249
|
+
{
|
|
250
|
+
HyperDebug.LogWarning($"Could not capture code optimization/debug symbols: {ex.Message}");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
try
|
|
254
|
+
{
|
|
255
|
+
snapshot.ExceptionSupportValue = PlayerSettings.WebGL.exceptionSupport;
|
|
256
|
+
snapshot.HasExceptionSupport = true;
|
|
257
|
+
}
|
|
258
|
+
catch (Exception ex)
|
|
259
|
+
{
|
|
260
|
+
HyperDebug.LogWarning($"Could not capture exception support: {ex.Message}");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
try
|
|
264
|
+
{
|
|
265
|
+
snapshot.Il2CppCodeGenerationValue = PlayerSettings.GetIl2CppCodeGeneration(NamedBuildTarget.WebGL);
|
|
266
|
+
snapshot.HasIl2CppCodeGeneration = true;
|
|
267
|
+
}
|
|
268
|
+
catch (Exception ex)
|
|
269
|
+
{
|
|
270
|
+
HyperDebug.LogWarning($"Could not capture IL2CPP code generation: {ex.Message}");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return snapshot;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private static void RestoreBuildSettingsSnapshot(BuildSettingsSnapshot snapshot)
|
|
277
|
+
{
|
|
278
|
+
try
|
|
279
|
+
{
|
|
280
|
+
Type webglType = typeof(PlayerSettings.WebGL);
|
|
281
|
+
|
|
282
|
+
if (snapshot.HasCodeOptimization)
|
|
283
|
+
{
|
|
284
|
+
var codeOptProp = webglType.GetProperty("codeOptimization");
|
|
285
|
+
codeOptProp?.SetValue(null, snapshot.CodeOptimizationValue);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (snapshot.HasDebugSymbolMode)
|
|
289
|
+
{
|
|
290
|
+
var debugSymbolProp = webglType.GetProperty("debugSymbolMode");
|
|
291
|
+
debugSymbolProp?.SetValue(null, snapshot.DebugSymbolModeValue);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
catch (Exception ex)
|
|
295
|
+
{
|
|
296
|
+
HyperDebug.LogWarning($"Could not restore code optimization/debug symbols: {ex.Message}");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
try
|
|
300
|
+
{
|
|
301
|
+
if (snapshot.HasExceptionSupport)
|
|
302
|
+
{
|
|
303
|
+
PlayerSettings.WebGL.exceptionSupport = snapshot.ExceptionSupportValue;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (Exception ex)
|
|
307
|
+
{
|
|
308
|
+
HyperDebug.LogWarning($"Could not restore exception support: {ex.Message}");
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
try
|
|
312
|
+
{
|
|
313
|
+
if (snapshot.HasIl2CppCodeGeneration)
|
|
314
|
+
{
|
|
315
|
+
PlayerSettings.SetIl2CppCodeGeneration(NamedBuildTarget.WebGL, snapshot.Il2CppCodeGenerationValue);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
catch (Exception ex)
|
|
319
|
+
{
|
|
320
|
+
HyperDebug.LogWarning($"Could not restore IL2CPP code generation: {ex.Message}");
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
AssetDatabase.Refresh();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private static void ApplyDevelopmentBuildSettings()
|
|
327
|
+
{
|
|
328
|
+
try
|
|
329
|
+
{
|
|
330
|
+
Type webglType = typeof(PlayerSettings.WebGL);
|
|
331
|
+
var codeOptProp = webglType.GetProperty("codeOptimization");
|
|
332
|
+
|
|
333
|
+
if (codeOptProp != null)
|
|
334
|
+
{
|
|
335
|
+
Type enumType = codeOptProp.PropertyType;
|
|
336
|
+
object shorterBuildValue = Enum.Parse(enumType, "ShorterBuildTime");
|
|
337
|
+
codeOptProp.SetValue(null, shorterBuildValue);
|
|
338
|
+
|
|
339
|
+
HyperBuildAssistant.AddOptimizationSummary("Code Optimization → Shorter Build Time");
|
|
340
|
+
|
|
341
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
342
|
+
{
|
|
343
|
+
HyperDebug.LogSuccess("Development build: Code Optimization → Shorter Build Time");
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
catch (Exception ex)
|
|
348
|
+
{
|
|
349
|
+
HyperDebug.LogWarning($"Could not set Code Optimization: {ex.Message}");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
try
|
|
353
|
+
{
|
|
354
|
+
Type webglType = typeof(PlayerSettings.WebGL);
|
|
355
|
+
var debugSymbolModeProp = webglType.GetProperty("debugSymbolMode");
|
|
356
|
+
|
|
357
|
+
if (debugSymbolModeProp != null)
|
|
358
|
+
{
|
|
359
|
+
object embeddedValue = Enum.ToObject(debugSymbolModeProp.PropertyType, 2);
|
|
360
|
+
debugSymbolModeProp.SetValue(null, embeddedValue);
|
|
361
|
+
|
|
362
|
+
HyperBuildAssistant.AddOptimizationSummary("Debug Symbols → Embedded");
|
|
363
|
+
|
|
364
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
365
|
+
{
|
|
366
|
+
HyperDebug.LogSuccess("Development build: Debug Symbols → Embedded");
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
catch (Exception ex)
|
|
371
|
+
{
|
|
372
|
+
HyperDebug.LogWarning($"Could not set Debug Symbols: {ex.Message}");
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
try
|
|
376
|
+
{
|
|
377
|
+
PlayerSettings.WebGL.exceptionSupport = WebGLExceptionSupport.FullWithoutStacktrace;
|
|
378
|
+
HyperBuildAssistant.AddOptimizationSummary("Exception Support → Full Without Stacktrace");
|
|
379
|
+
|
|
380
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
381
|
+
{
|
|
382
|
+
HyperDebug.LogSuccess("Development build: Exception Support → Full Without Stacktrace");
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (Exception ex)
|
|
386
|
+
{
|
|
387
|
+
HyperDebug.LogWarning($"Could not set Exception Support: {ex.Message}");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
HyperBuildAssistant.AddOptimizationSummary("Unity Development Build flag NOT used (keeps Brotli compression)");
|
|
391
|
+
HyperBuildAssistant.AddOptimizationSummary("Using Hyper dev API URL");
|
|
392
|
+
|
|
393
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
394
|
+
{
|
|
395
|
+
HyperDebug.Log("Development build settings applied: Fast iteration with Brotli compression");
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
private static void ApplyReleaseBuildSettings()
|
|
400
|
+
{
|
|
401
|
+
string currentCodeOpt = "";
|
|
402
|
+
|
|
403
|
+
try
|
|
404
|
+
{
|
|
405
|
+
Type webglType = typeof(PlayerSettings.WebGL);
|
|
406
|
+
var codeOptProp = webglType.GetProperty("codeOptimization");
|
|
407
|
+
|
|
408
|
+
if (codeOptProp != null)
|
|
409
|
+
{
|
|
410
|
+
object value = codeOptProp.GetValue(null);
|
|
411
|
+
if (value != null)
|
|
412
|
+
{
|
|
413
|
+
currentCodeOpt = value.ToString();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (Exception ex)
|
|
418
|
+
{
|
|
419
|
+
HyperDebug.LogWarning($"Could not read current Code Optimization setting: {ex.Message}");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
bool isShorterBuildTime = !string.IsNullOrEmpty(currentCodeOpt) &&
|
|
423
|
+
currentCodeOpt.Contains("ShorterBuildTime");
|
|
424
|
+
|
|
425
|
+
if (isShorterBuildTime)
|
|
426
|
+
{
|
|
427
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
428
|
+
{
|
|
429
|
+
HyperDebug.Log("Release build: Respecting developer's 'Shorter Build Time' choice - no Code Optimization changes applied.");
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
bool isRuntimePreference = !string.IsNullOrEmpty(currentCodeOpt) &&
|
|
436
|
+
(currentCodeOpt.Contains("Runtime") || currentCodeOpt.Contains("Faster"));
|
|
437
|
+
|
|
438
|
+
bool isDiskPreference = !string.IsNullOrEmpty(currentCodeOpt) &&
|
|
439
|
+
(currentCodeOpt.Contains("DiskSize") || currentCodeOpt.Contains("Disk"));
|
|
440
|
+
|
|
441
|
+
bool wantsDiskSize = isDiskPreference ||
|
|
442
|
+
string.IsNullOrEmpty(currentCodeOpt) ||
|
|
443
|
+
(!isRuntimePreference && !isDiskPreference);
|
|
444
|
+
|
|
445
|
+
try
|
|
446
|
+
{
|
|
447
|
+
Type webglType = typeof(PlayerSettings.WebGL);
|
|
448
|
+
var codeOptProp = webglType.GetProperty("codeOptimization");
|
|
449
|
+
|
|
450
|
+
if (codeOptProp != null)
|
|
451
|
+
{
|
|
452
|
+
Type enumType = codeOptProp.PropertyType;
|
|
453
|
+
string[] enumNames = Enum.GetNames(enumType);
|
|
454
|
+
|
|
455
|
+
string targetValue = wantsDiskSize
|
|
456
|
+
? Array.IndexOf(enumNames, "DiskSizeLTO") >= 0 ? "DiskSizeLTO" : "DiskSize"
|
|
457
|
+
: Array.IndexOf(enumNames, "FasterRuntimeLTO") >= 0 ? "FasterRuntimeLTO" : "FasterRuntime";
|
|
458
|
+
|
|
459
|
+
object enumValue = Enum.Parse(enumType, targetValue);
|
|
460
|
+
codeOptProp.SetValue(null, enumValue);
|
|
461
|
+
|
|
462
|
+
HyperBuildAssistant.AddOptimizationSummary($"Code Optimization → {targetValue}");
|
|
463
|
+
|
|
464
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
465
|
+
{
|
|
466
|
+
HyperDebug.LogSuccess($"Release build: Code Optimization → {targetValue}");
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
catch (Exception ex)
|
|
471
|
+
{
|
|
472
|
+
HyperDebug.LogWarning($"Could not set Code Optimization: {ex.Message}");
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
try
|
|
476
|
+
{
|
|
477
|
+
if (wantsDiskSize)
|
|
478
|
+
{
|
|
479
|
+
PlayerSettings.SetIl2CppCodeGeneration(NamedBuildTarget.WebGL, Il2CppCodeGeneration.OptimizeSize);
|
|
480
|
+
HyperBuildAssistant.AddOptimizationSummary("IL2CPP Code Generation → Optimize Size");
|
|
481
|
+
|
|
482
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
483
|
+
{
|
|
484
|
+
HyperDebug.LogSuccess("Release build: IL2CPP Code Generation → Optimize Size");
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
else
|
|
488
|
+
{
|
|
489
|
+
PlayerSettings.SetIl2CppCodeGeneration(NamedBuildTarget.WebGL, Il2CppCodeGeneration.OptimizeSpeed);
|
|
490
|
+
HyperBuildAssistant.AddOptimizationSummary("IL2CPP Code Generation → Optimize Speed");
|
|
491
|
+
|
|
492
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
493
|
+
{
|
|
494
|
+
HyperDebug.LogSuccess("Release build: IL2CPP Code Generation → Optimize Speed");
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
catch (Exception)
|
|
499
|
+
{
|
|
500
|
+
HyperDebug.LogWarning("IL2CPP code generation setting not available in this Unity version");
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
private static void SetBuildDefineSymbols(bool isRelease)
|
|
505
|
+
{
|
|
506
|
+
try
|
|
507
|
+
{
|
|
508
|
+
string defines = PlayerSettings.GetScriptingDefineSymbols(NamedBuildTarget.WebGL);
|
|
509
|
+
|
|
510
|
+
bool hasReleaseDefine = HasDefine(defines, ReleaseDefine);
|
|
511
|
+
bool hasDevelopmentDefine = HasDefine(defines, DevelopmentDefine);
|
|
512
|
+
|
|
513
|
+
if (isRelease)
|
|
514
|
+
{
|
|
515
|
+
if (!hasReleaseDefine)
|
|
516
|
+
{
|
|
517
|
+
defines = AddDefine(defines, ReleaseDefine);
|
|
518
|
+
HyperDebug.LogSuccess("Set HYPER_RELEASE_BUILD (production API URL; Unity debug logger off in player)");
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (hasDevelopmentDefine)
|
|
522
|
+
{
|
|
523
|
+
defines = RemoveDefine(defines, DevelopmentDefine);
|
|
524
|
+
HyperDebug.LogSuccess("Removed HYPER_DEVELOPMENT_BUILD define symbol for release build");
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
else
|
|
528
|
+
{
|
|
529
|
+
if (hasReleaseDefine)
|
|
530
|
+
{
|
|
531
|
+
defines = RemoveDefine(defines, ReleaseDefine);
|
|
532
|
+
HyperDebug.LogSuccess("Removed HYPER_RELEASE_BUILD define symbol for dev API URL");
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (!hasDevelopmentDefine)
|
|
536
|
+
{
|
|
537
|
+
defines = AddDefine(defines, DevelopmentDefine);
|
|
538
|
+
HyperDebug.LogSuccess("Set HYPER_DEVELOPMENT_BUILD define symbol for development build");
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
PlayerSettings.SetScriptingDefineSymbols(NamedBuildTarget.WebGL, defines);
|
|
543
|
+
}
|
|
544
|
+
catch (Exception ex)
|
|
545
|
+
{
|
|
546
|
+
HyperDebug.LogWarning($"Could not set Hyper build define symbols: {ex.Message}");
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
private static bool HasDefine(string defines, string targetDefine)
|
|
551
|
+
{
|
|
552
|
+
if (string.IsNullOrWhiteSpace(defines))
|
|
553
|
+
return false;
|
|
554
|
+
|
|
555
|
+
string[] splitDefines = defines.Split(';');
|
|
556
|
+
|
|
557
|
+
foreach (string define in splitDefines)
|
|
558
|
+
{
|
|
559
|
+
if (define.Trim() == targetDefine)
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
private static string AddDefine(string defines, string targetDefine)
|
|
567
|
+
{
|
|
568
|
+
if (string.IsNullOrWhiteSpace(defines))
|
|
569
|
+
return targetDefine;
|
|
570
|
+
|
|
571
|
+
if (HasDefine(defines, targetDefine))
|
|
572
|
+
return defines;
|
|
573
|
+
|
|
574
|
+
return $"{defines};{targetDefine}";
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
private static string RemoveDefine(string defines, string targetDefine)
|
|
578
|
+
{
|
|
579
|
+
if (string.IsNullOrWhiteSpace(defines))
|
|
580
|
+
return "";
|
|
581
|
+
|
|
582
|
+
string[] splitDefines = defines.Split(';');
|
|
583
|
+
string cleaned = "";
|
|
584
|
+
|
|
585
|
+
foreach (string define in splitDefines)
|
|
586
|
+
{
|
|
587
|
+
string trimmed = define.Trim();
|
|
588
|
+
|
|
589
|
+
if (string.IsNullOrWhiteSpace(trimmed))
|
|
590
|
+
continue;
|
|
591
|
+
|
|
592
|
+
if (trimmed == targetDefine)
|
|
593
|
+
continue;
|
|
594
|
+
|
|
595
|
+
cleaned = string.IsNullOrEmpty(cleaned)
|
|
596
|
+
? trimmed
|
|
597
|
+
: $"{cleaned};{trimmed}";
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
return cleaned;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
private static string[] GetEnabledScenes()
|
|
604
|
+
{
|
|
605
|
+
var scenes = new System.Collections.Generic.List<string>();
|
|
606
|
+
|
|
607
|
+
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
|
|
608
|
+
{
|
|
609
|
+
if (scene.enabled)
|
|
610
|
+
{
|
|
611
|
+
scenes.Add(scene.path);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return scenes.ToArray();
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
private static void ForceAssetRepack()
|
|
619
|
+
{
|
|
620
|
+
const string hyperLoaderScenePath = HyperConstants.HYPER_LOADER_SCENE_PATH;
|
|
621
|
+
const string markerPrefix = "__HyperSDK_BuildMarker";
|
|
622
|
+
|
|
623
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
624
|
+
{
|
|
625
|
+
HyperDebug.Log("ForceAssetRepack() called");
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
try
|
|
629
|
+
{
|
|
630
|
+
Scene hyperLoaderScene = EditorSceneManager.GetSceneByPath(hyperLoaderScenePath);
|
|
631
|
+
bool sceneWasLoaded = hyperLoaderScene.IsValid() && hyperLoaderScene.isLoaded;
|
|
632
|
+
|
|
633
|
+
if (!sceneWasLoaded)
|
|
634
|
+
{
|
|
635
|
+
hyperLoaderScene = EditorSceneManager.OpenScene(hyperLoaderScenePath, OpenSceneMode.Additive);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
GameObject markerObject = FindMarkerObject(hyperLoaderScene, markerPrefix);
|
|
639
|
+
|
|
640
|
+
if (markerObject == null)
|
|
641
|
+
{
|
|
642
|
+
markerObject = new GameObject(markerPrefix);
|
|
643
|
+
|
|
644
|
+
if (hyperLoaderScene.rootCount > 0)
|
|
645
|
+
{
|
|
646
|
+
markerObject.transform.SetParent(hyperLoaderScene.GetRootGameObjects()[0].transform, false);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
EditorSceneManager.MoveGameObjectToScene(markerObject, hyperLoaderScene);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
string newName = $"{markerPrefix}_{DateTime.Now.Ticks}";
|
|
653
|
+
markerObject.name = newName;
|
|
654
|
+
|
|
655
|
+
EditorSceneManager.MarkSceneDirty(hyperLoaderScene);
|
|
656
|
+
EditorSceneManager.SaveScene(hyperLoaderScene);
|
|
657
|
+
|
|
658
|
+
if (HyperBuildAssistant.IsSDKDeveloper())
|
|
659
|
+
{
|
|
660
|
+
HyperDebug.Log($"Renamed build marker to '{newName}'");
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (!sceneWasLoaded)
|
|
664
|
+
{
|
|
665
|
+
EditorSceneManager.CloseScene(hyperLoaderScene, true);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
catch (Exception ex)
|
|
669
|
+
{
|
|
670
|
+
HyperDebug.LogWarning($"Could not force asset repack: {ex.Message}");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
private static GameObject FindMarkerObject(Scene scene, string markerPrefix)
|
|
675
|
+
{
|
|
676
|
+
foreach (GameObject root in scene.GetRootGameObjects())
|
|
677
|
+
{
|
|
678
|
+
Transform marker = FindMarkerRecursive(root.transform, markerPrefix);
|
|
679
|
+
|
|
680
|
+
if (marker != null)
|
|
681
|
+
{
|
|
682
|
+
return marker.gameObject;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
private static Transform FindMarkerRecursive(Transform parent, string markerPrefix)
|
|
690
|
+
{
|
|
691
|
+
if (parent.name.StartsWith(markerPrefix, StringComparison.Ordinal))
|
|
692
|
+
{
|
|
693
|
+
return parent;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
foreach (Transform child in parent)
|
|
697
|
+
{
|
|
698
|
+
Transform result = FindMarkerRecursive(child, markerPrefix);
|
|
699
|
+
|
|
700
|
+
if (result != null)
|
|
701
|
+
return result;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
private static bool LoadConfigurationAssets()
|
|
708
|
+
{
|
|
709
|
+
_gameContentConfig = AssetDatabase.LoadAssetAtPath<HyperGameContentConfig>(
|
|
710
|
+
HyperConstants.GAME_CONTENT_ASSET_PATH);
|
|
711
|
+
|
|
712
|
+
if (_gameContentConfig == null)
|
|
713
|
+
{
|
|
714
|
+
HyperDebug.LogError($"HyperGameContentConfig not found at: {HyperConstants.GAME_CONTENT_ASSET_PATH}");
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
_sdkSettings = AssetDatabase.LoadAssetAtPath<HyperSDKSettings>(
|
|
719
|
+
HyperConstants.SETTINGS_ASSET_PATH);
|
|
720
|
+
|
|
721
|
+
if (_sdkSettings == null)
|
|
722
|
+
{
|
|
723
|
+
HyperDebug.LogError($"HyperSDKSettings not found at: {HyperConstants.SETTINGS_ASSET_PATH}");
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
private static bool ValidateConfigurationAssets(HyperBuildProfile profile)
|
|
731
|
+
{
|
|
732
|
+
if (!LoadConfigurationAssets())
|
|
733
|
+
{
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
if (profile == HyperBuildProfile.Development)
|
|
738
|
+
{
|
|
739
|
+
if (!_gameContentConfig.HasScenesContent)
|
|
740
|
+
{
|
|
741
|
+
HyperDebug.LogError("HyperGameContentConfig is missing scenes content. Development builds require scenes content.");
|
|
742
|
+
return false;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
else if (profile == HyperBuildProfile.Release)
|
|
746
|
+
{
|
|
747
|
+
if (!_gameContentConfig.HasScenesContent)
|
|
748
|
+
{
|
|
749
|
+
HyperDebug.LogError("HyperGameContentConfig is missing scenes content. Release builds require scenes content.");
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (!_gameContentConfig.HasPosterContent)
|
|
754
|
+
{
|
|
755
|
+
HyperDebug.LogError("HyperGameContentConfig is missing poster content. Release builds require poster content.");
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
if (!_sdkSettings.IsConfigured)
|
|
761
|
+
{
|
|
762
|
+
HyperDebug.LogError("HyperSDKSettings is not configured. Please configure at least one platform/orientation flag.");
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
public static class HyperBuildCLI
|
|
771
|
+
{
|
|
772
|
+
public static void BuildFromCommandLine()
|
|
773
|
+
{
|
|
774
|
+
string[] args = Environment.GetCommandLineArgs();
|
|
775
|
+
|
|
776
|
+
string profileValue = GetArg(args, "-hyperBuildProfile", "release");
|
|
777
|
+
string outputPath = GetArg(args, "-hyperBuildOutputPath", "");
|
|
778
|
+
|
|
779
|
+
if (string.IsNullOrWhiteSpace(outputPath))
|
|
780
|
+
{
|
|
781
|
+
HyperDebug.LogError("Missing required argument: -hyperBuildOutputPath <path>");
|
|
782
|
+
EditorApplication.Exit(1);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
HyperBuildProfile profile;
|
|
787
|
+
|
|
788
|
+
if (profileValue.Equals("development", StringComparison.OrdinalIgnoreCase) ||
|
|
789
|
+
profileValue.Equals("dev", StringComparison.OrdinalIgnoreCase))
|
|
790
|
+
{
|
|
791
|
+
profile = HyperBuildProfile.Development;
|
|
792
|
+
}
|
|
793
|
+
else if (profileValue.Equals("release", StringComparison.OrdinalIgnoreCase) ||
|
|
794
|
+
profileValue.Equals("prod", StringComparison.OrdinalIgnoreCase))
|
|
795
|
+
{
|
|
796
|
+
profile = HyperBuildProfile.Release;
|
|
797
|
+
}
|
|
798
|
+
else
|
|
799
|
+
{
|
|
800
|
+
HyperDebug.LogError($"Invalid -hyperBuildProfile value: {profileValue}. Expected development or release.");
|
|
801
|
+
EditorApplication.Exit(1);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
HyperBuildResult result = HyperBuildPipeline.Build(new HyperBuildRequest
|
|
806
|
+
{
|
|
807
|
+
Profile = profile,
|
|
808
|
+
OutputPath = outputPath,
|
|
809
|
+
CleanOutputFolder = true,
|
|
810
|
+
OpenOutputFolder = false,
|
|
811
|
+
IsCliBuild = true
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
if (result.Succeeded)
|
|
815
|
+
{
|
|
816
|
+
HyperDebug.Log($"Hyper build succeeded: {result.OutputPath}");
|
|
817
|
+
EditorApplication.Exit(0);
|
|
818
|
+
}
|
|
819
|
+
else
|
|
820
|
+
{
|
|
821
|
+
HyperDebug.LogError($"Hyper build failed: {result.Message}");
|
|
822
|
+
EditorApplication.Exit(1);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
private static string GetArg(string[] args, string argName, string fallback)
|
|
827
|
+
{
|
|
828
|
+
for (int i = 0; i < args.Length - 1; i++)
|
|
829
|
+
{
|
|
830
|
+
if (args[i] == argName)
|
|
831
|
+
{
|
|
832
|
+
return args[i + 1];
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
return fallback;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
#endif
|