gg.easy.airship 0.1.2160 → 0.1.2162

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.
@@ -44,11 +44,24 @@ jobs:
44
44
  environment: 'platform-production'
45
45
  runs-on: ubuntu-latest
46
46
  steps:
47
+ - name: "Setup Git Config"
48
+ run: |
49
+ git config --global user.email "actions@github.com"
50
+ git config --global user.name "GitHub Actions"
51
+
52
+ - name: Generate a token
53
+ id: generate-token
54
+ uses: actions/create-github-app-token@v1
55
+ with:
56
+ app-id: ${{ secrets.DEPLOY_APP_ID }}
57
+ private-key: ${{ secrets.DEPLOY_APP_PRIVATE_KEY }}
58
+ owner: ${{ github.repository_owner }}
59
+
47
60
  - name: Checkout Airship Template
48
61
  uses: actions/checkout@v4
49
62
  with:
50
63
  repository: easy-games/airship-template
51
- token: ${{ secrets.PULL_PACKAGE_PAT }}
64
+ token: ${{ steps.generate-token.outputs.token }}
52
65
  lfs: true
53
66
  path: airship-template
54
67
  ref: refs/heads/main
@@ -57,7 +70,7 @@ jobs:
57
70
  - name: Update Template Version
58
71
  uses: actions/github-script@v7
59
72
  with:
60
- github-token: ${{ secrets.PULL_PACKAGE_PAT }}
73
+ github-token: ${{ steps.generate-token.outputs.token }}
61
74
  script: |
62
75
  const fs = require('fs');
63
76
  const path = require('path');
@@ -1,9 +1,11 @@
1
1
  using System;
2
2
  using System.Collections;
3
3
  using System.Collections.Generic;
4
+ using System.ComponentModel;
4
5
  using System.Diagnostics;
5
6
  using System.IO;
6
7
  using System.Threading;
8
+ using UnityEditor;
7
9
  using UnityEngine;
8
10
  using Debug = UnityEngine.Debug;
9
11
 
@@ -65,10 +67,16 @@ namespace Airship.Editor {
65
67
  var fullCommandString = string.Join(" ", argList);
66
68
 
67
69
  TypescriptLogService.Log(TypescriptLogLevel.Information, $"Start process 'node {fullCommandString}'");
68
- var compilerProcess = TypescriptCompilationService.RunNodeCommand(directory, fullCommandString);
69
-
70
- TypescriptCompilationService.AttachWatchOutputToUnityConsole(this, arguments, compilerProcess);
71
- processId = compilerProcess.Id;
70
+
71
+ try {
72
+ var compilerProcess = TypescriptCompilationService.RunNodeCommand(directory, fullCommandString);
73
+ TypescriptCompilationService.AttachWatchOutputToUnityConsole(this, arguments, compilerProcess);
74
+ processId = compilerProcess.Id;
75
+ }
76
+ catch (Win32Exception _) {
77
+ EditorUtility.DisplayDialog("Failed to initialize TypeScript",
78
+ "Ensure you have the latest LTS node.js installed, then restart the editor and Unity Hub", "Ok");
79
+ }
72
80
 
73
81
  TypescriptCompilationServicesState.instance.RegisterWatchCompiler(this);
74
82
  yield return null;
@@ -2,6 +2,7 @@ using System;
2
2
  using System.Collections;
3
3
  using System.Collections.Generic;
4
4
  using System.Threading.Tasks;
5
+ using Airship.DevConsole;
5
6
  using Code.Auth;
6
7
  using Code.Http.Internal;
7
8
  using Code.Platform.Shared;
@@ -48,6 +49,21 @@ public class SocketManager : Singleton<SocketManager> {
48
49
  DontDestroyOnLoad(this);
49
50
  }
50
51
 
52
+ private void Start() {
53
+ DevConsole.AddCommand(Command.Create<string>("join", "", "Join a game from given gameId",
54
+ Parameter.Create("gameId", "Game ID of the target game."), async (gameId) => {
55
+ Debug.Log("Requesting transfer to game " + gameId + " ...");
56
+ var packet = $"{{\"gameId\": \"{gameId}\"}}";
57
+ var res = await InternalHttpManager.PostAsync(AirshipPlatformUrl.gameCoordinator + "/transfers/transfer/self", packet);
58
+ if (res.success) {
59
+ Debug.Log("<color=green>Joining...</color>");
60
+ }
61
+ else {
62
+ Debug.LogError("Failed to join game: " + res.error);
63
+ }
64
+ }));
65
+ }
66
+
51
67
  public static async Task<bool> ConnectAsyncInternal() {
52
68
  // print("Connecting to socket with auth token: " + authToken);
53
69
  if (Instance.socket == null) {
@@ -34,6 +34,10 @@ namespace Code.Authentication {
34
34
  public string reason;
35
35
  }
36
36
 
37
+ public struct ServerStartupFailureMessage : NetworkMessage {
38
+ public string reason;
39
+ }
40
+
37
41
  public class EasyAuthenticator : NetworkAuthenticator {
38
42
  private string passkey = "empty";
39
43
 
@@ -57,6 +61,7 @@ namespace Code.Authentication {
57
61
 
58
62
  public override async void OnStartClient() {
59
63
  NetworkClient.RegisterHandler<KickMessage>(Client_OnKickBroadcast, false);
64
+ NetworkClient.RegisterHandler<ServerStartupFailureMessage>(Client_OnServerStartupFailure, false);
60
65
 
61
66
  //Listen to response from server.
62
67
  NetworkClient.RegisterHandler<LoginResponseMessage>(Client_OnLoginResponseMessage, false);
@@ -64,6 +69,7 @@ namespace Code.Authentication {
64
69
 
65
70
  public override void OnStopClient() {
66
71
  NetworkClient.UnregisterHandler<KickMessage>();
72
+ NetworkClient.UnregisterHandler<ServerStartupFailureMessage>();
67
73
  NetworkClient.UnregisterHandler<LoginResponseMessage>();
68
74
  }
69
75
 
@@ -121,6 +127,10 @@ namespace Code.Authentication {
121
127
  TransferManager.Instance.Disconnect(true, kickMessage.reason);
122
128
  }
123
129
 
130
+ private void Client_OnServerStartupFailure(ServerStartupFailureMessage message) {
131
+ TransferManager.Instance.Disconnect(true, message.reason);
132
+ }
133
+
124
134
  /// <summary>
125
135
  /// Received on server when a client sends the password broadcast message.
126
136
  /// </summary>
@@ -220,11 +220,8 @@ public class BundleDownloader : Singleton<BundleDownloader> {
220
220
  }
221
221
 
222
222
  if (!success && RunCore.IsServer()) {
223
- var serverBootstrap = FindAnyObjectByType<ServerBootstrap>();
224
- if (serverBootstrap.IsAgonesEnvironment()) {
225
- Debug.LogError("[SEVERE] Server failed to download bundles. Shutting down!");
226
- serverBootstrap.agones.Shutdown().Wait();
227
- }
223
+ onComplete?.Invoke(false);
224
+ return false;
228
225
  }
229
226
 
230
227
  if (!success && RunCore.IsClient()) {
@@ -268,12 +265,10 @@ public class BundleDownloader : Singleton<BundleDownloader> {
268
265
  if (loadingScreen) {
269
266
  loadingScreen.SetError("Failed to download Main Menu scripts.");
270
267
  }
271
- if (RunCore.IsServer()) {
272
- var serverBootstrap = FindAnyObjectByType<ServerBootstrap>();
273
- if (serverBootstrap.IsAgonesEnvironment()) {
274
- Debug.LogError("[SEVERE] Server failed to download code.zip. Shutting down!");
275
- serverBootstrap.agones.Shutdown().Wait();
276
- }
268
+ if (RunCore.IsServer())
269
+ {
270
+ onComplete?.Invoke(false);
271
+ return false;
277
272
  }
278
273
  } else {
279
274
  File.WriteAllText(Path.Join(package.GetPersistentDataDirectory(), "code_version_" + package.codeVersion + ".txt"), "success");
@@ -7,6 +7,7 @@ using System.Runtime.Serialization;
7
7
  using Agones;
8
8
  using Agones.Model;
9
9
  using Code.Analytics;
10
+ using Code.Authentication;
10
11
  using Code.Bootstrap;
11
12
  using Code.GameBundle;
12
13
  using Code.Http.Internal;
@@ -429,7 +430,15 @@ public class ServerBootstrap : MonoBehaviour
429
430
  if (!RunCore.IsEditor()) {
430
431
  BundleDownloader.Instance.DownloadBundles(startupConfig.CdnUrl, packages.ToArray(), privateBundleFiles, null, gameCodeZipUrl, false,
431
432
  (res) => {
432
- downloadComplete = true;
433
+ if (!res)
434
+ {
435
+ Debug.LogWarning("[Airship]: Failed to download required files. See above logs for details. Shutting down server.");
436
+ ShutdownDueToAssetFailure(1);
437
+ }
438
+ else
439
+ {
440
+ downloadComplete = true;
441
+ }
433
442
  });
434
443
  } else {
435
444
  downloadComplete = true;
@@ -477,13 +486,34 @@ public class ServerBootstrap : MonoBehaviour
477
486
  isServerReady = true;
478
487
  OnServerReady?.Invoke();
479
488
  }
480
-
481
- public void Shutdown() {
489
+
490
+ private void ShutdownInternal(int exitCode = 0) {
482
491
  if (agones && !this.isAgonesShutdownTriggered) {
483
492
  this.isAgonesShutdownTriggered = true;
484
493
  agones.Shutdown();
485
- Application.Quit();
494
+ Application.Quit(exitCode);
495
+ }
496
+ }
497
+
498
+ private void ShutdownDueToAssetFailure(int exitCode = 1) {
499
+ if (NetworkServer.connections != null && NetworkServer.connections.Count > 0) {
500
+ var message = new ServerStartupFailureMessage {
501
+ reason = "Server failed to download required game assets.\n\nIf you are the game developer, ensure your game / packages have all been properly published.\n\nCheck the error console in the Airship Create portal for more details.",
502
+ };
503
+
504
+ foreach (var connection in NetworkServer.connections.Values) {
505
+ if (connection != null) {
506
+ connection.Send(message);
507
+ }
508
+ }
486
509
  }
510
+
511
+ ShutdownInternal(exitCode);
512
+ }
513
+
514
+ public void Shutdown()
515
+ {
516
+ ShutdownInternal(0);
487
517
  }
488
518
 
489
519
  /**
@@ -43,4 +43,4 @@ namespace Code.Bootstrap {
43
43
  }
44
44
  #endif
45
45
  }
46
- }
46
+ }
@@ -88,33 +88,49 @@ namespace Code.Health
88
88
  NetworkClient.RegisterHandler<ClientProfileUploadResponse>(OnClientUploadResponse);
89
89
  }
90
90
 
91
- DevConsole.AddCommand(Command.Create<string, int, bool>(
92
- "profile",
91
+ // Profile without callstacks
92
+ DevConsole.AddCommand(Command.Create<string, int>(
93
+ "profile",
93
94
  "",
94
- "Starts and uploads a profile. Once complete the download link will be printed.",
95
- Parameter.Create("Context", "Options: Server | Client"),
95
+ "Starts and uploads a profile. Once complete the download link will be printed.",
96
+ Parameter.Create("Context", "Options: Server | Client"),
96
97
  Parameter.Create("Duration", "Duration of profile in seconds (max 5s)"),
97
- Parameter.Create("Callstacks", "Enable callstacks for profile (this is laggy)"),
98
- (context, d, callstacks) => {
99
- if (d is < 0 or > 5) {
100
- Debug.LogError("You can only profile for a max of 5s.");
101
- return;
102
- }
98
+ (context, d) => {
99
+ OnProfileCommand(context, d, false);
100
+ }
101
+ ));
103
102
 
104
- if (context.Equals("client", StringComparison.OrdinalIgnoreCase)) {
105
- if (!Debug.isDebugBuild) {
106
- Debug.Log(
107
- "Unable to capture profile log because debug mode is not enabled. Use the development build branch on Steam to enable debug mode.");
108
- return;
109
- }
110
- StartProfiling(d, null, callstacks);
111
- } else if (context.Equals("server", StringComparison.OrdinalIgnoreCase)) {
112
- Debug.Log("Starting a server profile, view server console to monitor progress.");
113
- NetworkClient.Send(new StartServerProfileMessage { DurationSecs = d, CallstacksEnabled = callstacks });
114
- }
103
+ // Deep profile with callstacks
104
+ DevConsole.AddCommand(Command.Create<string, int>(
105
+ "deepprofile",
106
+ "",
107
+ "Starts and uploads a profile with callstacks. Once complete the download link will be printed.",
108
+ Parameter.Create("Context", "Options: Server | Client"),
109
+ Parameter.Create("Duration", "Duration of profile in seconds (max 5s)"),
110
+ (context, d) => {
111
+ OnProfileCommand(context, d, true);
115
112
  }));
116
113
  }
117
114
 
115
+ private void OnProfileCommand(string context, int dur, bool callstacks) {
116
+ if (dur is < 0 or > 5) {
117
+ Debug.LogError("You can only profile for a max of 5s.");
118
+ return;
119
+ }
120
+
121
+ if (context.Equals("client", StringComparison.OrdinalIgnoreCase)) {
122
+ if (!Debug.isDebugBuild) {
123
+ Debug.Log(
124
+ "Unable to capture profile log because debug mode is not enabled. Use the development build branch on Steam to enable debug mode.");
125
+ return;
126
+ }
127
+ StartProfiling(dur, null, callstacks);
128
+ } else if (context.Equals("server", StringComparison.OrdinalIgnoreCase)) {
129
+ Debug.Log("Starting a server profile, view server console to monitor progress.");
130
+ NetworkClient.Send(new StartServerProfileMessage { DurationSecs = dur, CallstacksEnabled = callstacks });
131
+ }
132
+ }
133
+
118
134
  private void Update() {
119
135
  if (Profiler.enabled != lastProfilerEnabled) {
120
136
  lastProfilerEnabled = Profiler.enabled;
@@ -167,12 +183,6 @@ namespace Code.Health
167
183
  }
168
184
 
169
185
  public void StartProfiling(int durationSecs, [CanBeNull] NetworkConnectionToClient profileInitiator, bool enableCallstacks) {
170
- // TODO check that sender is game dev
171
- // if (Profiler.enabled) {
172
- // Debug.LogWarning("Profiler is already running.");
173
- // return;
174
- // }
175
-
176
186
  var date = DateTime.Now.ToString("MM-dd-yyyy h.mm.ss");
177
187
  var fileName = RunCore.IsClient() ? $"Client-Profile-{date}.raw" : $"Server-Profile-{date}.raw";
178
188
  if (!Directory.Exists(Path.Combine(Application.persistentDataPath, "ClientProfiles"))) {
@@ -193,6 +203,7 @@ namespace Code.Health
193
203
  private async void StopProfilingAfterDelay(string logPath, string fileName, float durationSecs, [CanBeNull] NetworkConnectionToClient profileInitiator) {
194
204
  await Task.Delay((int)(durationSecs * 1000));
195
205
  Profiler.enabled = false;
206
+ Profiler.enableBinaryLog = false;
196
207
  Profiler.enableAllocationCallstacks = false;
197
208
  var info = new FileInfo(logPath);
198
209
 
@@ -180,7 +180,14 @@ public class AirshipComponent : MonoBehaviour, ITriggerReceiver {
180
180
  script = runtimeScript;
181
181
  }
182
182
  else {
183
- Debug.LogError($"Failed to find code.zip compiled script. Path: {script.m_path.ToLower()}, GameObject: {gameObject.name}", gameObject);
183
+ var isPackage = scriptPath.StartsWith("Assets/AirshipPackage");
184
+ if (script == null) {
185
+ var suggestion = isPackage ? "have you published this package?" : "have you done a full publish of this game?";
186
+ Debug.LogError($"Could not find compiled script from asset bundle '{scriptPath}' for GameObject {gameObject.name} (Missing Script Asset) - {suggestion}", gameObject);
187
+ }
188
+ else {
189
+ Debug.LogError($"Could not find compiled script in code archive '{script.m_path.ToLower()}' for GameObject {gameObject.name} (Missing Runtime Script Code)", gameObject);
190
+ }
184
191
  return;
185
192
  }
186
193
  #endif
@@ -27,6 +27,7 @@ using UnityEngine.Serialization;
27
27
  using Enum = System.Enum;
28
28
  using System.Globalization;
29
29
  using System.IO;
30
+ using UnityEngine.Networking;
30
31
  using UnityEngine.Profiling;
31
32
  using Debug = UnityEngine.Debug;
32
33
  #if INPUT_SYSTEM_INSTALLED
@@ -1791,96 +1792,6 @@ namespace Airship.DevConsole
1791
1792
  this.Log("<color=red>Console logging has been disabled.</color>");
1792
1793
  }));
1793
1794
 
1794
- AddCommand(Command.Create<string>(
1795
- "enum",
1796
- "",
1797
- "Display information about a specified enum",
1798
- Parameter.Create("enumName", "Name of the enum to get information about (case-sensitive)"),
1799
- s =>
1800
- {
1801
- // Check if the enum type was cached
1802
- Type enumType = _cacheEnumTypes.FirstOrDefault(t => t.Name.Equals(s));
1803
-
1804
- #if INPUT_SYSTEM_INSTALLED
1805
- // Special case for Key
1806
- if (s.Equals("Key"))
1807
- {
1808
- enumType = typeof(Key);
1809
- }
1810
- #endif
1811
-
1812
- if (enumType == null)
1813
- {
1814
- List<Type> options = new List<Type>();
1815
-
1816
- // Search all loaded assemblies for the enum
1817
- foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
1818
- {
1819
- enumType = assembly.GetTypes()
1820
- .SelectMany(t => t.GetMembers())
1821
- .Union(assembly.GetTypes())
1822
- .FirstOrDefault(t => t.ReflectedType != null && t.ReflectedType.IsEnum && (t.ReflectedType.Name.Equals(s) || s.Equals($"{t.ReflectedType.Namespace}.{t.ReflectedType.Name}")))
1823
- ?.ReflectedType;
1824
-
1825
- if (enumType != null)
1826
- {
1827
- if (s.Equals($"{enumType.Namespace}.{enumType.Name}"))
1828
- {
1829
- options = new List<Type>() { enumType };
1830
- break;
1831
- }
1832
-
1833
- options.Add(enumType);
1834
- }
1835
- }
1836
-
1837
- if (options.Count > 1)
1838
- {
1839
- LogError($"Multiple results found: {string.Join(", ", options.Select(x => $"{x.Namespace}.{x.Name}"))}.");
1840
- return;
1841
- }
1842
-
1843
- else if (options.Count == 1)
1844
- {
1845
- // Select the first type
1846
- enumType = options.FirstOrDefault();
1847
-
1848
- // Cache the type
1849
- _cacheEnumTypes.Add(enumType);
1850
- if (_cacheEnumTypes.Count > MaxCachedEnumTypes)
1851
- {
1852
- _cacheEnumTypes.RemoveAt(0);
1853
- }
1854
- }
1855
-
1856
- else
1857
- {
1858
- LogError($"Could not find enum type with the specified name: \"{s}\"");
1859
- return;
1860
- }
1861
- }
1862
-
1863
- LogSeperator($"{enumType.Namespace}.{enumType.Name} ({enumType.GetEnumUnderlyingType().Name}){(enumType.GetCustomAttribute(typeof(FlagsAttribute)) == null ? "" : " [Flags]")}");
1864
-
1865
- FieldInfo[] values = enumType.GetFields();
1866
- string formattedValues = string.Empty;
1867
- bool first = true;
1868
- for (int i = 0; i < values.Length; i++)
1869
- {
1870
- if (values[i].Name.Equals("value__"))
1871
- {
1872
- continue;
1873
- }
1874
-
1875
- formattedValues += $"{(first ? "" : "\n")}{values[i].Name} = {values[i].GetRawConstantValue()}";
1876
- first = false;
1877
- }
1878
- Log(formattedValues);
1879
-
1880
- LogSeperator();
1881
- }
1882
- ));
1883
-
1884
1795
  AddCommand(Command.Create(
1885
1796
  "commands",
1886
1797
  "",
@@ -0,0 +1,97 @@
1
+ %YAML 1.1
2
+ %TAG !u! tag:unity3d.com,2011:
3
+ --- !u!21 &2100000
4
+ Material:
5
+ serializedVersion: 8
6
+ m_ObjectHideFlags: 0
7
+ m_CorrespondingSourceObject: {fileID: 0}
8
+ m_PrefabInstance: {fileID: 0}
9
+ m_PrefabAsset: {fileID: 0}
10
+ m_Name: Timings Graph
11
+ m_Shader: {fileID: 4800000, guid: bc65170c051b0724287a7f1636d87573, type: 3}
12
+ m_Parent: {fileID: 0}
13
+ m_ModifiedSerializedProperties: 0
14
+ m_ValidKeywords: []
15
+ m_InvalidKeywords: []
16
+ m_LightmapFlags: 5
17
+ m_EnableInstancingVariants: 0
18
+ m_DoubleSidedGI: 0
19
+ m_CustomRenderQueue: 4500
20
+ stringTagMap: {}
21
+ disabledShaderPasses: []
22
+ m_LockedProperties:
23
+ m_SavedProperties:
24
+ serializedVersion: 3
25
+ m_TexEnvs:
26
+ - _BumpMap:
27
+ m_Texture: {fileID: 0}
28
+ m_Scale: {x: 1, y: 1}
29
+ m_Offset: {x: 0, y: 0}
30
+ - _DetailAlbedoMap:
31
+ m_Texture: {fileID: 0}
32
+ m_Scale: {x: 1, y: 1}
33
+ m_Offset: {x: 0, y: 0}
34
+ - _DetailMask:
35
+ m_Texture: {fileID: 0}
36
+ m_Scale: {x: 1, y: 1}
37
+ m_Offset: {x: 0, y: 0}
38
+ - _DetailNormalMap:
39
+ m_Texture: {fileID: 0}
40
+ m_Scale: {x: 1, y: 1}
41
+ m_Offset: {x: 0, y: 0}
42
+ - _EmissionMap:
43
+ m_Texture: {fileID: 0}
44
+ m_Scale: {x: 1, y: 1}
45
+ m_Offset: {x: 0, y: 0}
46
+ - _MainTex:
47
+ m_Texture: {fileID: 0}
48
+ m_Scale: {x: 1, y: 1}
49
+ m_Offset: {x: 0, y: 0}
50
+ - _MetallicGlossMap:
51
+ m_Texture: {fileID: 0}
52
+ m_Scale: {x: 1, y: 1}
53
+ m_Offset: {x: 0, y: 0}
54
+ - _OcclusionMap:
55
+ m_Texture: {fileID: 0}
56
+ m_Scale: {x: 1, y: 1}
57
+ m_Offset: {x: 0, y: 0}
58
+ - _ParallaxMap:
59
+ m_Texture: {fileID: 0}
60
+ m_Scale: {x: 1, y: 1}
61
+ m_Offset: {x: 0, y: 0}
62
+ m_Ints: []
63
+ m_Floats:
64
+ - FpsValues_Length: 120
65
+ - PixelSnap: 0
66
+ - ScrollSpeed: 0.2
67
+ - _AmazingThreshold: 0.72
68
+ - _BumpScale: 1
69
+ - _CautionThreshold: 0
70
+ - _ColorMask: 15
71
+ - _Cutoff: 0.5
72
+ - _DetailNormalMapScale: 1
73
+ - _DstBlend: 0
74
+ - _Glossiness: 0.5
75
+ - _GoodThreshold: 0.4
76
+ - _Metallic: 0
77
+ - _Mode: 0
78
+ - _OcclusionStrength: 1
79
+ - _Parallax: 0.02
80
+ - _SrcBlend: 1
81
+ - _Stencil: 0
82
+ - _StencilComp: 8
83
+ - _StencilOp: 0
84
+ - _StencilReadMask: 255
85
+ - _StencilWriteMask: 255
86
+ - _UVSec: 0
87
+ - _UseUIAlphaClip: 0
88
+ - _ZWrite: 1
89
+ m_Colors:
90
+ - _AmazingColor: {r: 0, g: 1, b: 1, a: 1}
91
+ - _CautionColor: {r: 0.9137255, g: 0.76862746, b: 0.41568628, a: 1}
92
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
93
+ - _CriticalColor: {r: 0.20784314, g: 0.6784314, b: 0.62352943, a: 1}
94
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
95
+ - _GoodColor: {r: 0.90588236, g: 0.43529412, b: 0.31764707, a: 1}
96
+ m_BuildTextureStacks: []
97
+ m_AllowLocking: 1
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 5b42a1eb000204cb3af3e64d0b342b92
3
+ NativeFormatImporter:
4
+ externalObjects: {}
5
+ mainObjectFileID: 2100000
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant: