Integrate COM logging HUD fixes and hopper dispensing
Подробный список изменений: - Добавлено файловое логирование игровых сессий в game.log и расширена диагностика COM-подключений. - Подключен native COM transport с fallback-логикой для IL2CPP и добавлен плагин ComNative.dll. - Исправлена логика one-way платформ, чтобы игрок проходил сквозь платформы при нахождении ниже их верхней точки. - Переработана компоновка gameplay HUD: верхние плашки выровнены, левая уменьшена, центральная плашка очков центрирована и масштабирована. - Добавлена общая выдача призов через хоппер с командами запуска/остановки мотора и ожиданием датчика. - Подключен сервисный тест хоппера в настройках и обновлены связанные тесты. - Добавлены скриншоты визуальной проверки HUD.
@ -84,14 +84,6 @@ MonoBehaviour:
|
||||
volume: 0.55
|
||||
pitchRange: {x: 0.96, y: 1.04}
|
||||
spatial: 1
|
||||
- eventId: 31
|
||||
channel: 2
|
||||
outputGroupOverride: {fileID: 0}
|
||||
clips:
|
||||
- {fileID: 8300000, guid: e3dc6a0fbf543b64388f7b60615f4145, type: 3}
|
||||
volume: 0.7
|
||||
pitchRange: {x: 0.96, y: 1.04}
|
||||
spatial: 1
|
||||
- eventId: 32
|
||||
channel: 2
|
||||
outputGroupOverride: {fileID: 0}
|
||||
|
||||
8
Assets/Plugins/x86_64.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8480e16cd88119a4083023fb213dffce
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/x86_64/ComNative.dll
Normal file
2
Assets/Plugins/x86_64/ComNative.dll.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 265471db36c70b54180317c720985aad
|
||||
@ -260,7 +260,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::DanroJump.UI.Gameplay.GameplayHudController
|
||||
visualTreeAsset: {fileID: 9197481963319205126, guid: e5019473f4474704f8a8e8c93608eafc, type: 3}
|
||||
panelSettings: {fileID: 11400000, guid: d0960c9338bdb86469da533ffbbbc1fb, type: 2}
|
||||
sortingOrder: 10
|
||||
sortingOrder: 5000
|
||||
scoreLabelName: ScoreValue
|
||||
heightLabelName: HeightValue
|
||||
bestHeightLabelName: BestHeightValue
|
||||
|
||||
BIN
Assets/Screenshots/gameplay-hud-aligned-no-overlap.png
Normal file
|
After Width: | Height: | Size: 413 KiB |
169
Assets/Screenshots/gameplay-hud-aligned-no-overlap.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5281feb3e8fadf4195b417283d66194
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -6613811265633659565
|
||||
second: gameplay-hud-aligned-no-overlap_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-aligned-no-overlap_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 355dd6402b50734a0800000000000000
|
||||
internalID: -6613811265633659565
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-aligned-no-overlap_0: -6613811265633659565
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-final-aligned.png
Normal file
|
After Width: | Height: | Size: 402 KiB |
169
Assets/Screenshots/gameplay-hud-final-aligned.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33859e507258e7f4bb6888557906181e
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -88504916756509590
|
||||
second: gameplay-hud-final-aligned_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-final-aligned_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: a6c4ad34f3195cef0800000000000000
|
||||
internalID: -88504916756509590
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-final-aligned_0: -88504916756509590
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-layout-check-1.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
169
Assets/Screenshots/gameplay-hud-layout-check-1.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18810d73ea59a4b449afdc1c8e6f5863
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 1204845118186171250
|
||||
second: gameplay-hud-layout-check-1_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-layout-check-1_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1080
|
||||
height: 1920
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 27ba9de504878b010800000000000000
|
||||
internalID: 1204845118186171250
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-layout-check-1_0: 1204845118186171250
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-layout-check.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
169
Assets/Screenshots/gameplay-hud-layout-check.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 387580a6fdae7ff42900412e409ef078
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -7993827095130345330
|
||||
second: gameplay-hud-layout-check_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-layout-check_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1080
|
||||
height: 1920
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: e80fcde2c98301190800000000000000
|
||||
internalID: -7993827095130345330
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-layout-check_0: -7993827095130345330
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 400 KiB |
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ab9dc1160c053340b1ba0dd9805f456
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -2984284117762596666
|
||||
second: gameplay-hud-left-padding-center-true-center_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-left-padding-center-true-center_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 6c0abe30861b596d0800000000000000
|
||||
internalID: -2984284117762596666
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-left-padding-center-true-center_0: -2984284117762596666
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
After Width: | Height: | Size: 415 KiB |
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c74775832b90654dac4c794c1d0e647
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 192430222544730116
|
||||
second: gameplay-hud-left-smaller-center-bigger-final_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-left-smaller-center-bigger-final_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 408f3d29446aba200800000000000000
|
||||
internalID: 192430222544730116
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-left-smaller-center-bigger-final_0: 192430222544730116
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-left-smaller-center-bigger.png
Normal file
|
After Width: | Height: | Size: 400 KiB |
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61863c92cb6f70f4f824aaa5b38a05e0
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -5553616215781586425
|
||||
second: gameplay-hud-left-smaller-center-bigger_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-left-smaller-center-bigger_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 70a4d7fd9779de2b0800000000000000
|
||||
internalID: -5553616215781586425
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-left-smaller-center-bigger_0: -5553616215781586425
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-runtime-check.png
Normal file
|
After Width: | Height: | Size: 404 KiB |
169
Assets/Screenshots/gameplay-hud-runtime-check.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1000adfacd6f4bf4b972e3c18b1abd29
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -7200965495179829446
|
||||
second: gameplay-hud-runtime-check_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-runtime-check_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: a3f16f3d808011c90800000000000000
|
||||
internalID: -7200965495179829446
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-runtime-check_0: -7200965495179829446
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-runtime-ui-check-final-fixed.png
Normal file
|
After Width: | Height: | Size: 397 KiB |
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2b4729c8644bc5439846cb05511ba42
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -1398601438865487644
|
||||
second: gameplay-hud-runtime-ui-check-final-fixed_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-runtime-ui-check-final-fixed_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 4e88216c66b279ce0800000000000000
|
||||
internalID: -1398601438865487644
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-runtime-ui-check-final-fixed_0: -1398601438865487644
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-runtime-ui-check-final.png
Normal file
|
After Width: | Height: | Size: 398 KiB |
169
Assets/Screenshots/gameplay-hud-runtime-ui-check-final.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2885c47a0ecb53e47b356f30dd10bd5b
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 8421283597357811696
|
||||
second: gameplay-hud-runtime-ui-check-final_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-runtime-ui-check-final_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 0f7065d50d86ed470800000000000000
|
||||
internalID: 8421283597357811696
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-runtime-ui-check-final_0: 8421283597357811696
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-runtime-ui-check-fixed.png
Normal file
|
After Width: | Height: | Size: 399 KiB |
169
Assets/Screenshots/gameplay-hud-runtime-ui-check-fixed.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ce49b63caafebb4d877b2bfd5421507
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 8905311186297662870
|
||||
second: gameplay-hud-runtime-ui-check-fixed_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-runtime-ui-check-fixed_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 69da5917755069b70800000000000000
|
||||
internalID: 8905311186297662870
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-runtime-ui-check-fixed_0: 8905311186297662870
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-runtime-ui-check-sorting.png
Normal file
|
After Width: | Height: | Size: 395 KiB |
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de42086cba591cd4fa8265deb11c9809
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 4112799035560915661
|
||||
second: gameplay-hud-runtime-ui-check-sorting_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-runtime-ui-check-sorting_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: dc27d2baee8931930800000000000000
|
||||
internalID: 4112799035560915661
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-runtime-ui-check-sorting_0: 4112799035560915661
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-runtime-ui-check.png
Normal file
|
After Width: | Height: | Size: 404 KiB |
169
Assets/Screenshots/gameplay-hud-runtime-ui-check.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b707582a4e3e16c4182a4f982fd90ea8
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 7529376751934918786
|
||||
second: gameplay-hud-runtime-ui-check_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-runtime-ui-check_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 2805a277348bd7860800000000000000
|
||||
internalID: 7529376751934918786
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-runtime-ui-check_0: 7529376751934918786
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/gameplay-hud-same-height-sub-sprite.png
Normal file
|
After Width: | Height: | Size: 422 KiB |
169
Assets/Screenshots/gameplay-hud-same-height-sub-sprite.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b456d48c0a913544c97ec3620d29f2b6
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -3297423903188290487
|
||||
second: gameplay-hud-same-height-sub-sprite_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: gameplay-hud-same-height-sub-sprite_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 94474983e623d32d0800000000000000
|
||||
internalID: -3297423903188290487
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
gameplay-hud-same-height-sub-sprite_0: -3297423903188290487
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/screenshot-20260706-085727.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
169
Assets/Screenshots/screenshot-20260706-085727.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee6fd35711026f94abe3fa4d082a89e3
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 5866824435928499895
|
||||
second: screenshot-20260706-085727_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: screenshot-20260706-085727_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 7b6891f9db52b6150800000000000000
|
||||
internalID: 5866824435928499895
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
screenshot-20260706-085727_0: 5866824435928499895
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/screenshot-20260706-085751.png
Normal file
|
After Width: | Height: | Size: 412 KiB |
169
Assets/Screenshots/screenshot-20260706-085751.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9b8b0aea1c298d42961d9f239378684
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 8860738017832214241
|
||||
second: screenshot-20260706-085751_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: screenshot-20260706-085751_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 1ee10b0f74aa7fa70800000000000000
|
||||
internalID: 8860738017832214241
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
screenshot-20260706-085751_0: 8860738017832214241
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/screenshot-20260706-085804.png
Normal file
|
After Width: | Height: | Size: 367 KiB |
169
Assets/Screenshots/screenshot-20260706-085804.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9b5b32ece6d79f4c8f07068d4145c73
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -84736916317270727
|
||||
second: screenshot-20260706-085804_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: screenshot-20260706-085804_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 93d0c8b3934f2def0800000000000000
|
||||
internalID: -84736916317270727
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
screenshot-20260706-085804_0: -84736916317270727
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/screenshot-20260706-091834.png
Normal file
|
After Width: | Height: | Size: 376 KiB |
169
Assets/Screenshots/screenshot-20260706-091834.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b27172e5ea1648e41bb3249612633fdf
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -5655167601327757581
|
||||
second: screenshot-20260706-091834_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: screenshot-20260706-091834_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 3f6af89670fc481b0800000000000000
|
||||
internalID: -5655167601327757581
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
screenshot-20260706-091834_0: -5655167601327757581
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Screenshots/screenshot-20260706-092024.png
Normal file
|
After Width: | Height: | Size: 413 KiB |
169
Assets/Screenshots/screenshot-20260706-092024.png.meta
Normal file
@ -0,0 +1,169 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 544707e8a80be704da33766e4e1b7b2d
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 8766466611136954131
|
||||
second: screenshot-20260706-092024_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: screenshot-20260706-092024_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 701
|
||||
height: 1246
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 31ff324afeeb8a970800000000000000
|
||||
internalID: 8766466611136954131
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
screenshot-20260706-092024_0: 8766466611136954131
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,7 +1,9 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DanroJump.Debugging;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace DanroJump.Bootstrap
|
||||
@ -13,6 +15,7 @@ namespace DanroJump.Bootstrap
|
||||
public sealed class BootstrapEntryPoint : MonoBehaviour
|
||||
{
|
||||
private const float AspectTolerance = 0.0025f;
|
||||
private const string GameLogFileName = "game.log";
|
||||
private static BootstrapEntryPoint instance;
|
||||
|
||||
[SerializeField] private string mainMenuSceneName = "MainMenu";
|
||||
@ -26,6 +29,8 @@ namespace DanroJump.Bootstrap
|
||||
[SerializeField] [Min(0.1f)] private float aspectCheckInterval = 0.5f;
|
||||
|
||||
private float nextAspectCheckTime;
|
||||
private InputAction fullscreenToggleAction;
|
||||
private FileLogger fileLogger;
|
||||
|
||||
/// <summary>
|
||||
/// Создает singleton bootstrap-объект и применяет разрешение билда до загрузки меню.
|
||||
@ -50,6 +55,38 @@ namespace DanroJump.Bootstrap
|
||||
ApplyBuildAspectResolution();
|
||||
EnforceBuildAspectOnStartupAsync(this.GetCancellationTokenOnDestroy()).Forget(Debug.LogException);
|
||||
}
|
||||
|
||||
// Инициализируем файловый логгер — пишем game.log в корень папки игры.
|
||||
InitFileLogger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует InputAction для переключения полноэкранного режима по F11.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
fullscreenToggleAction = new InputAction("FullscreenToggle", InputActionType.Button, "<Keyboard>/f11");
|
||||
fullscreenToggleAction.performed += OnFullscreenTogglePerformed;
|
||||
fullscreenToggleAction.Enable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Снимает подписку и отключает InputAction при деактивации объекта.
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
if (fullscreenToggleAction != null)
|
||||
{
|
||||
fullscreenToggleAction.performed -= OnFullscreenTogglePerformed;
|
||||
fullscreenToggleAction.Disable();
|
||||
fullscreenToggleAction.Dispose();
|
||||
fullscreenToggleAction = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFullscreenTogglePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -70,6 +107,33 @@ namespace DanroJump.Bootstrap
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переключает полноэкранный режим по нажатию F11.
|
||||
/// В билде учитывает целевой aspect ratio и разрешение монитора.
|
||||
/// </summary>
|
||||
private void ToggleFullscreen()
|
||||
{
|
||||
bool isCurrentlyFullscreen = Screen.fullScreen;
|
||||
|
||||
if (isCurrentlyFullscreen)
|
||||
{
|
||||
// Выход из полноэкранного режима — переходим в Windowed с aspect-корректным разрешением
|
||||
Vector2Int resolution = CalculateTargetResolution();
|
||||
Screen.SetResolution(resolution.x, resolution.y, FullScreenMode.Windowed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Вход в полноэкранный режим — используем native разрешение монитора
|
||||
Resolution native = Screen.currentResolution;
|
||||
FullScreenMode targetMode = FullScreenMode.FullScreenWindow;
|
||||
#if UNITY_STANDALONE_WIN
|
||||
// На Windows ExclusiveFullScreen даёт минимальный input lag
|
||||
targetMode = FullScreenMode.FullScreenWindow;
|
||||
#endif
|
||||
Screen.SetResolution(native.width, native.height, targetMode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Загружает сцену главного меню после bootstrap-настройки.
|
||||
/// </summary>
|
||||
@ -138,12 +202,66 @@ namespace DanroJump.Bootstrap
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
DisposeFileLogger();
|
||||
|
||||
if (instance == this)
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт FileLogger и подписывает его на все сообщения Unity Debug.Log.
|
||||
/// В билде лог пишется рядом с .exe, в редакторе — в корень проекта.
|
||||
/// </summary>
|
||||
private void InitFileLogger()
|
||||
{
|
||||
if (fileLogger != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string logDirectory = ResolveGameRootDirectory();
|
||||
string logPath = Path.Combine(logDirectory, GameLogFileName);
|
||||
fileLogger = new FileLogger(logPath, append: true);
|
||||
Application.logMessageReceived += fileLogger.HandleUnityLog;
|
||||
Debug.Log($"[BootstrapEntryPoint] Game log writes to: {fileLogger.FilePath}", this);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[BootstrapEntryPoint] Failed to init FileLogger: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static string ResolveGameRootDirectory()
|
||||
{
|
||||
string dataPath = Application.dataPath;
|
||||
var dataDirectory = new DirectoryInfo(dataPath);
|
||||
|
||||
#if UNITY_STANDALONE_OSX && !UNITY_EDITOR
|
||||
return dataDirectory.Parent?.Parent?.FullName ?? Path.GetFullPath(".");
|
||||
#else
|
||||
return dataDirectory.Parent?.FullName ?? Path.GetFullPath(".");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Корректно отписывается и освобождает FileLogger.
|
||||
/// </summary>
|
||||
private void DisposeFileLogger()
|
||||
{
|
||||
if (fileLogger == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Application.logMessageReceived -= fileLogger.HandleUnityLog;
|
||||
fileLogger.Dispose();
|
||||
fileLogger = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Несколько кадров подряд повторяет установку разрешения, пока Unity завершает старт окна.
|
||||
/// </summary>
|
||||
|
||||
395
Assets/Scripts/Runtime/Debugging/FileLogger.cs
Normal file
@ -0,0 +1,395 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace DanroJump.Debugging
|
||||
{
|
||||
/// <summary>
|
||||
/// Логгер для записи сообщений в файл. Совместим с CompositeLogger.
|
||||
/// </summary>
|
||||
public class FileLogger : ILogger, IDisposable
|
||||
{
|
||||
public ILogHandler logHandler { get; set; }
|
||||
public LogType filterLogType { get; set; }
|
||||
|
||||
public bool logEnabled { get; set; } = true;
|
||||
|
||||
private readonly string _filePath;
|
||||
private readonly object _lock = new object();
|
||||
private StreamWriter _writer;
|
||||
private bool _disposed;
|
||||
private bool _footerWritten;
|
||||
|
||||
/// <summary>
|
||||
/// Создает файловый логгер с указанным путём к файлу.
|
||||
/// </summary>
|
||||
/// <param name="filePath">Полный путь к файлу лога. Если null, используется Application.persistentDataPath/game.log</param>
|
||||
/// <param name="append">Если true, добавляет к существующему файлу, иначе перезаписывает</param>
|
||||
public FileLogger(string filePath = null, bool append = true)
|
||||
{
|
||||
_filePath = filePath ?? Path.Combine(Application.persistentDataPath, "game.log");
|
||||
filterLogType = LogType.Exception;
|
||||
|
||||
try
|
||||
{
|
||||
// Создаем директорию если её нет
|
||||
string directory = Path.GetDirectoryName(_filePath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
// Открываем файл для записи
|
||||
_writer = new StreamWriter(_filePath, append, Encoding.UTF8)
|
||||
{
|
||||
AutoFlush = true // Автоматически сбрасывать буфер для надёжности
|
||||
};
|
||||
|
||||
// Записываем заголовок
|
||||
WriteHeader();
|
||||
|
||||
// Подписываемся на завершение приложения для гарантированной записи
|
||||
Application.quitting += OnApplicationQuitting;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Не удалось открыть файл лога: {_filePath}\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public string FilePath => _filePath;
|
||||
|
||||
private void WriteHeader()
|
||||
{
|
||||
if (_writer != null)
|
||||
{
|
||||
_writer.WriteLine("================================================================================");
|
||||
_writer.WriteLine($"Новая сессия логирования начата: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
_writer.WriteLine($"Unity версия: {Application.unityVersion}");
|
||||
_writer.WriteLine($"Платформа: {Application.platform}");
|
||||
_writer.WriteLine($"Путь к логу: {_filePath}");
|
||||
_writer.WriteLine("================================================================================");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsLogTypeAllowed(LogType logType)
|
||||
{
|
||||
return logEnabled && logType <= filterLogType;
|
||||
}
|
||||
|
||||
private void WriteToFile(LogType logType, string message)
|
||||
{
|
||||
if (!logEnabled || _disposed || _writer == null)
|
||||
return;
|
||||
|
||||
if (!IsLogTypeAllowed(logType))
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
|
||||
string logTypeStr = GetLogTypeString(logType);
|
||||
_writer.WriteLine($"[{timestamp}] [{logTypeStr}] {message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка записи в файл: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetLogTypeString(LogType logType)
|
||||
{
|
||||
return logType switch
|
||||
{
|
||||
LogType.Error => "ERROR",
|
||||
LogType.Assert => "ASSERT",
|
||||
LogType.Warning => "WARNING",
|
||||
LogType.Log => "INFO",
|
||||
LogType.Exception => "EXCEPTION",
|
||||
_ => "UNKNOWN"
|
||||
};
|
||||
}
|
||||
|
||||
private string FormatMessage(object message, Object context = null)
|
||||
{
|
||||
string msg = message?.ToString() ?? "null";
|
||||
if (context != null)
|
||||
{
|
||||
msg += $" (Context: {context.name})";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
private string FormatMessage(string tag, object message, Object context = null)
|
||||
{
|
||||
string msg = $"[{tag}] {message?.ToString() ?? "null"}";
|
||||
if (context != null)
|
||||
{
|
||||
msg += $" (Context: {context.name})";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
#region ILogger Implementation
|
||||
|
||||
public void Log(LogType logType, object message)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(message));
|
||||
}
|
||||
|
||||
public void Log(LogType logType, object message, Object context)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(message, context));
|
||||
}
|
||||
|
||||
public void Log(LogType logType, string tag, object message)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void Log(LogType logType, string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(logType, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void Log(object message)
|
||||
{
|
||||
WriteToFile(LogType.Log, FormatMessage(message));
|
||||
}
|
||||
|
||||
public void Log(string tag, object message)
|
||||
{
|
||||
WriteToFile(LogType.Log, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void Log(string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(LogType.Log, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void LogWarning(string tag, object message)
|
||||
{
|
||||
WriteToFile(LogType.Warning, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void LogWarning(string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(LogType.Warning, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void LogError(string tag, object message)
|
||||
{
|
||||
WriteToFile(LogType.Error, FormatMessage(tag, message));
|
||||
}
|
||||
|
||||
public void LogError(string tag, object message, Object context)
|
||||
{
|
||||
WriteToFile(LogType.Error, FormatMessage(tag, message, context));
|
||||
}
|
||||
|
||||
public void LogFormat(LogType logType, string format, params object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string message = string.Format(format, args);
|
||||
WriteToFile(logType, message);
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
WriteToFile(LogType.Error, $"Ошибка форматирования: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LogFormat(LogType logType, Object context, string format, params object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string message = string.Format(format, args);
|
||||
WriteToFile(logType, FormatMessage(message, context));
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
WriteToFile(LogType.Error, $"Ошибка форматирования: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LogException(Exception exception)
|
||||
{
|
||||
if (exception == null)
|
||||
return;
|
||||
|
||||
WriteToFile(LogType.Exception, $"{exception.GetType().Name}: {exception.Message}");
|
||||
WriteToFile(LogType.Exception, $"StackTrace:\n{exception.StackTrace}");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
WriteToFile(LogType.Exception,
|
||||
$"Inner Exception: {exception.InnerException.GetType().Name}: {exception.InnerException.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LogException(Exception exception, Object context)
|
||||
{
|
||||
if (exception == null)
|
||||
return;
|
||||
|
||||
string contextInfo = context != null ? $" (Context: {context.name})" : "";
|
||||
WriteToFile(LogType.Exception, $"{exception.GetType().Name}: {exception.Message}{contextInfo}");
|
||||
WriteToFile(LogType.Exception, $"StackTrace:\n{exception.StackTrace}");
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
WriteToFile(LogType.Exception,
|
||||
$"Inner Exception: {exception.InnerException.GetType().Name}: {exception.InnerException.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Обработчик для Application.logMessageReceived — перенаправляет все Debug.Log в файл.
|
||||
/// </summary>
|
||||
public void HandleUnityLog(string logString, string stackTrace, LogType type)
|
||||
{
|
||||
if (type == LogType.Exception)
|
||||
{
|
||||
WriteToFile(type, $"{logString}\n{stackTrace}");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteToFile(type, logString);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationQuitting()
|
||||
{
|
||||
WriteFooter();
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void WriteFooter()
|
||||
{
|
||||
if (_footerWritten || _disposed || _writer == null) return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_footerWritten) return;
|
||||
_footerWritten = true;
|
||||
|
||||
try
|
||||
{
|
||||
_writer.WriteLine();
|
||||
_writer.WriteLine("================================================================================");
|
||||
_writer.WriteLine($"Сессия логирования завершена: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
_writer.WriteLine("================================================================================");
|
||||
_writer.Flush();
|
||||
}
|
||||
catch (ObjectDisposedException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при записи footer: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Принудительно сбрасывает буфер на диск
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_writer?.Flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при сбросе буфера: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Очищает файл лога
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_writer?.Close();
|
||||
File.WriteAllText(_filePath, string.Empty);
|
||||
_writer = new StreamWriter(_filePath, true, Encoding.UTF8) { AutoFlush = true };
|
||||
WriteHeader();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при очистке файла: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Гарантированно записываем footer
|
||||
WriteFooter();
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
Application.quitting -= OnApplicationQuitting;
|
||||
}
|
||||
|
||||
if (_writer != null)
|
||||
{
|
||||
|
||||
_writer.Dispose();
|
||||
_writer = null;
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// Поток уже закрыт — игнорируем.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[FileLogger] Ошибка при закрытии файла: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~FileLogger()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Runtime/Debugging/FileLogger.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d029602fde45ab04f85586e245e48a1a
|
||||
@ -80,7 +80,6 @@ namespace DanroJump.Gameplay
|
||||
private bool moveActionWasEnabled;
|
||||
#endif
|
||||
private Transform wrapVisualCloneRoot;
|
||||
private Transform visualRootClone;
|
||||
private readonly List<SpriteRenderer> sourceRenderers = new();
|
||||
private readonly List<SpriteRenderer> wrapRendererClones = new();
|
||||
private readonly List<IPlatformLandingHandler> landingHandlerBuffer = new();
|
||||
@ -1591,29 +1590,13 @@ namespace DanroJump.Gameplay
|
||||
sourceRenderers.Clear();
|
||||
wrapRendererClones.Clear();
|
||||
|
||||
if (wrapVisualCloneRoot == null)
|
||||
if (visualRoot != null)
|
||||
{
|
||||
wrapVisualCloneRoot = new GameObject($"{name} Wrap Visuals").transform;
|
||||
wrapVisualCloneRoot.SetParent(transform, false);
|
||||
wrapVisualCloneRoot.gameObject.SetActive(false);
|
||||
sourceRenderers.AddRange(visualRoot.GetComponentsInChildren<SpriteRenderer>(true));
|
||||
}
|
||||
|
||||
if (visualRootClone == null)
|
||||
else
|
||||
{
|
||||
visualRootClone = new GameObject("VisualRoot Clone").transform;
|
||||
visualRootClone.SetParent(wrapVisualCloneRoot, false);
|
||||
}
|
||||
|
||||
var allRenderers = visualRoot != null
|
||||
? visualRoot.GetComponentsInChildren<SpriteRenderer>(true)
|
||||
: GetComponentsInChildren<SpriteRenderer>(true);
|
||||
|
||||
foreach (var r in allRenderers)
|
||||
{
|
||||
if (r != null && (wrapVisualCloneRoot == null || !r.transform.IsChildOf(wrapVisualCloneRoot)))
|
||||
{
|
||||
sourceRenderers.Add(r);
|
||||
}
|
||||
sourceRenderers.AddRange(GetComponentsInChildren<SpriteRenderer>(true));
|
||||
}
|
||||
|
||||
if (sourceRenderers.Count == 0)
|
||||
@ -1621,6 +1604,12 @@ namespace DanroJump.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
if (wrapVisualCloneRoot == null)
|
||||
{
|
||||
wrapVisualCloneRoot = new GameObject($"{name} Wrap Visuals").transform;
|
||||
wrapVisualCloneRoot.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
for (var index = sourceRenderers.Count - 1; index >= 0; index--)
|
||||
{
|
||||
var sourceRenderer = sourceRenderers[index];
|
||||
@ -1631,62 +1620,9 @@ namespace DanroJump.Gameplay
|
||||
}
|
||||
|
||||
var clone = new GameObject($"{sourceRenderer.name} Wrap Clone").AddComponent<SpriteRenderer>();
|
||||
clone.transform.SetParent(visualRootClone, false);
|
||||
clone.transform.SetParent(wrapVisualCloneRoot, false);
|
||||
wrapRendererClones.Insert(0, clone);
|
||||
}
|
||||
|
||||
RebuildWrapCollider();
|
||||
}
|
||||
|
||||
private void RebuildWrapCollider()
|
||||
{
|
||||
if (wrapVisualCloneRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var oldColliders = wrapVisualCloneRoot.GetComponents<Collider2D>();
|
||||
foreach (var old in oldColliders)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
Destroy(old);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyImmediate(old);
|
||||
}
|
||||
}
|
||||
|
||||
var sourceCollider = GetComponent<Collider2D>();
|
||||
if (sourceCollider != null)
|
||||
{
|
||||
if (sourceCollider is BoxCollider2D boxCol)
|
||||
{
|
||||
var cloneCol = wrapVisualCloneRoot.gameObject.AddComponent<BoxCollider2D>();
|
||||
cloneCol.size = boxCol.size;
|
||||
cloneCol.offset = boxCol.offset;
|
||||
cloneCol.isTrigger = boxCol.isTrigger;
|
||||
cloneCol.sharedMaterial = boxCol.sharedMaterial;
|
||||
}
|
||||
else if (sourceCollider is CircleCollider2D circleCol)
|
||||
{
|
||||
var cloneCol = wrapVisualCloneRoot.gameObject.AddComponent<CircleCollider2D>();
|
||||
cloneCol.radius = circleCol.radius;
|
||||
cloneCol.offset = circleCol.offset;
|
||||
cloneCol.isTrigger = circleCol.isTrigger;
|
||||
cloneCol.sharedMaterial = circleCol.sharedMaterial;
|
||||
}
|
||||
else if (sourceCollider is CapsuleCollider2D capsuleCol)
|
||||
{
|
||||
var cloneCol = wrapVisualCloneRoot.gameObject.AddComponent<CapsuleCollider2D>();
|
||||
cloneCol.size = capsuleCol.size;
|
||||
cloneCol.offset = capsuleCol.offset;
|
||||
cloneCol.direction = capsuleCol.direction;
|
||||
cloneCol.isTrigger = capsuleCol.isTrigger;
|
||||
cloneCol.sharedMaterial = capsuleCol.sharedMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1726,20 +1662,11 @@ namespace DanroJump.Gameplay
|
||||
CopyWrappedVisuals(new Vector3(wrapOffsetX, 0f, 0f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Копирует состояние исходных SpriteRenderer в wrap-клоны.
|
||||
/// </summary>
|
||||
private void CopyWrappedVisuals(Vector3 offset)
|
||||
{
|
||||
if (wrapVisualCloneRoot != null)
|
||||
{
|
||||
wrapVisualCloneRoot.localPosition = offset;
|
||||
}
|
||||
|
||||
if (visualRoot != null && visualRootClone != null)
|
||||
{
|
||||
visualRootClone.localPosition = visualRoot.localPosition;
|
||||
visualRootClone.localRotation = visualRoot.localRotation;
|
||||
visualRootClone.localScale = visualRoot.localScale;
|
||||
}
|
||||
|
||||
for (var index = 0; index < sourceRenderers.Count; index++)
|
||||
{
|
||||
var source = sourceRenderers[index];
|
||||
@ -1769,9 +1696,8 @@ namespace DanroJump.Gameplay
|
||||
clone.sortingLayerID = source.sortingLayerID;
|
||||
clone.sortingOrder = source.sortingOrder;
|
||||
clone.sharedMaterial = source.sharedMaterial;
|
||||
clone.transform.localPosition = source.transform.localPosition;
|
||||
clone.transform.localRotation = source.transform.localRotation;
|
||||
clone.transform.localScale = source.transform.localScale;
|
||||
clone.transform.SetPositionAndRotation(source.transform.position + offset, source.transform.rotation);
|
||||
clone.transform.localScale = source.transform.lossyScale;
|
||||
clone.gameObject.layer = source.gameObject.layer;
|
||||
}
|
||||
catch (MissingReferenceException)
|
||||
|
||||
@ -5,7 +5,7 @@ namespace DanroJump.Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Кастомная one-way логика платформы.
|
||||
/// Игнорирует столкновение, если GroundCheck игрока ниже верхней границы платформы.
|
||||
/// Игнорирует столкновение, если нижняя точка игрока ниже верхней границы платформы.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
@ -14,10 +14,8 @@ namespace DanroJump.Gameplay
|
||||
[SerializeField] private JumpPlayerController player;
|
||||
[SerializeField] private float topBoundaryPadding;
|
||||
[SerializeField] private float landingVelocityThreshold = 0.05f;
|
||||
[SerializeField] private float crossingGraceDistance = 0.8f;
|
||||
|
||||
private Collider2D platformCollider;
|
||||
private BoxCollider2D boxPlatformCollider;
|
||||
private Collider2D playerCollider;
|
||||
private float cachedTopY;
|
||||
private Vector3 lastPosition;
|
||||
@ -33,15 +31,7 @@ namespace DanroJump.Gameplay
|
||||
/// </summary>
|
||||
public void UpdateCachedTopY()
|
||||
{
|
||||
if (boxPlatformCollider != null)
|
||||
{
|
||||
var localTop = boxPlatformCollider.offset + Vector2.up * (boxPlatformCollider.size.y * 0.5f);
|
||||
cachedTopY = boxPlatformCollider.transform.TransformPoint(localTop).y;
|
||||
}
|
||||
else
|
||||
{
|
||||
cachedTopY = platformCollider != null ? platformCollider.bounds.max.y : transform.position.y;
|
||||
}
|
||||
cachedTopY = platformCollider != null ? platformCollider.bounds.max.y : transform.position.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -60,7 +50,6 @@ namespace DanroJump.Gameplay
|
||||
private void Awake()
|
||||
{
|
||||
platformCollider = GetComponent<Collider2D>();
|
||||
boxPlatformCollider = platformCollider as BoxCollider2D;
|
||||
platformCollider.usedByEffector = false;
|
||||
|
||||
if (TryGetComponent(out PlatformEffector2D platformEffector))
|
||||
@ -139,7 +128,7 @@ namespace DanroJump.Gameplay
|
||||
/// Проверяет, должен ли игрок столкнуться с платформой в текущем физическом шаге.
|
||||
/// </summary>
|
||||
/// <param name="targetPlayer">Игрок, для которого проверяется столкновение.</param>
|
||||
/// <returns>True, если игрок падает сверху или только что пересек верх платформы сверху вниз.</returns>
|
||||
/// <returns>True, если нижняя точка игрока не ниже верхней границы платформы.</returns>
|
||||
public bool ShouldCollideWith(JumpPlayerController targetPlayer)
|
||||
{
|
||||
if (targetPlayer == null)
|
||||
@ -147,17 +136,10 @@ namespace DanroJump.Gameplay
|
||||
return false;
|
||||
}
|
||||
|
||||
var topY = cachedTopY + topBoundaryPadding;
|
||||
var topY = cachedTopY + Mathf.Max(0f, topBoundaryPadding);
|
||||
var playerLowestY = playerCollider != null ? playerCollider.bounds.min.y : targetPlayer.GroundCheckY;
|
||||
|
||||
if (targetPlayer.GroundCheckY >= topY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Grace-зона закрывает быстрые кадры, когда GroundCheck успел проскочить немного ниже верхней границы.
|
||||
var crossedFromAbove = targetPlayer.PreviousGroundCheckY >= topY &&
|
||||
targetPlayer.GroundCheckY >= topY - crossingGraceDistance;
|
||||
return crossedFromAbove;
|
||||
return playerLowestY >= topY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -53,6 +53,12 @@ namespace DanroJump.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
if (!content.scene.isLoaded)
|
||||
{
|
||||
Object.Destroy(content);
|
||||
return;
|
||||
}
|
||||
|
||||
if (content.TryGetComponent(out PlatformSpawnedContent marker) && marker.SourcePrefab != null)
|
||||
{
|
||||
content.SetActive(false);
|
||||
|
||||
87
Assets/Scripts/Runtime/Hardware/Com/ComHopperDispenser.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace DanroJump.Hardware.Com
|
||||
{
|
||||
/// <summary>
|
||||
/// Единая процедура выдачи капсулы через хоппер: запуск мотора, ожидание датчика и остановка.
|
||||
/// </summary>
|
||||
public static class ComHopperDispenser
|
||||
{
|
||||
public const string StartMotorCommand = "301";
|
||||
public const string StopMotorCommand = "300";
|
||||
public const int DefaultTimeoutSeconds = 10;
|
||||
|
||||
public static UniTask<ComHopperDispenseResult> DispenseAsync(
|
||||
IComSystem com,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return DispenseAsync(com, TimeSpan.FromSeconds(DefaultTimeoutSeconds), cancellationToken);
|
||||
}
|
||||
|
||||
public static async UniTask<ComHopperDispenseResult> DispenseAsync(
|
||||
IComSystem com,
|
||||
TimeSpan timeout,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (com == null)
|
||||
{
|
||||
return ComHopperDispenseResult.Failure("COM-система недоступна.");
|
||||
}
|
||||
|
||||
if (!com.IsRunning)
|
||||
{
|
||||
return ComHopperDispenseResult.Failure("COM-система не запущена.");
|
||||
}
|
||||
|
||||
if (!com.SendToMain(StartMotorCommand))
|
||||
{
|
||||
return ComHopperDispenseResult.Failure("Не удалось отправить команду запуска хоппера.");
|
||||
}
|
||||
|
||||
var sensorTriggered = new UniTaskCompletionSource();
|
||||
UnityAction onTriggered = () => sensorTriggered.TrySetResult();
|
||||
com.HopperSensorTriggered.AddListener(onTriggered);
|
||||
|
||||
try
|
||||
{
|
||||
var winner = await UniTask.WhenAny(
|
||||
sensorTriggered.Task,
|
||||
UniTask.Delay(timeout, DelayType.Realtime, PlayerLoopTiming.Update, cancellationToken));
|
||||
|
||||
return winner == 0
|
||||
? ComHopperDispenseResult.Success("Капсула выдана успешно.")
|
||||
: ComHopperDispenseResult.Failure($"Датчик хоппера не сработал за {timeout.TotalSeconds:0.#} сек.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
com.HopperSensorTriggered.RemoveListener(onTriggered);
|
||||
com.SendToMain(StopMotorCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ComHopperDispenseResult
|
||||
{
|
||||
private ComHopperDispenseResult(bool isSuccess, string message)
|
||||
{
|
||||
IsSuccess = isSuccess;
|
||||
Message = message ?? string.Empty;
|
||||
}
|
||||
|
||||
public bool IsSuccess { get; }
|
||||
public string Message { get; }
|
||||
|
||||
public static ComHopperDispenseResult Success(string message)
|
||||
{
|
||||
return new ComHopperDispenseResult(true, message);
|
||||
}
|
||||
|
||||
public static ComHopperDispenseResult Failure(string message)
|
||||
{
|
||||
return new ComHopperDispenseResult(false, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3402102c626636f48aa68fbc9154cde6
|
||||
@ -301,8 +301,8 @@ namespace DanroJump.Hardware.Com
|
||||
return;
|
||||
}
|
||||
|
||||
portProvider = customPortProvider ?? new ReflectionComPortProvider();
|
||||
transportFactory = customTransportFactory ?? new ReflectionSerialComTransportFactory();
|
||||
portProvider = customPortProvider ?? CreateDefaultPortProvider();
|
||||
transportFactory = customTransportFactory ?? CreateDefaultTransportFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -441,10 +441,24 @@ namespace DanroJump.Hardware.Com
|
||||
ResetDeviceSelections();
|
||||
ClearQueues();
|
||||
|
||||
string[] ports = SelectPorts(portProvider.GetPortNames());
|
||||
string[] detectedPorts = portProvider.GetPortNames();
|
||||
if (ShouldLog(DebugLogChannel.ComLifecycle, logLifecycle))
|
||||
{
|
||||
LogDebug(DebugLogChannel.ComLifecycle, $"Starting. Selected ports: {(ports.Length > 0 ? string.Join(", ", ports) : "<none>")}");
|
||||
LogDebug(
|
||||
DebugLogChannel.ComLifecycle,
|
||||
$"Detected ports: {(detectedPorts.Length > 0 ? string.Join(", ", detectedPorts) : "<none>")}. " +
|
||||
$"scanAll={useAllDetectedPorts} explicit=[{FormatList(explicitPorts)}] preferredMain={FormatDebugValue(preferredMainPort)}");
|
||||
}
|
||||
|
||||
string[] ports = SelectPorts(detectedPorts);
|
||||
if (ShouldLog(DebugLogChannel.ComLifecycle, logLifecycle))
|
||||
{
|
||||
LogDebug(
|
||||
DebugLogChannel.ComLifecycle,
|
||||
$"Starting. Selected ports: {(ports.Length > 0 ? string.Join(", ", ports) : "<none>")}. " +
|
||||
$"serial={baudRate}/{dataBits}/{parity}/{stopBits} readTimeoutMs={readTimeoutMs} writeTimeoutMs={writeTimeoutMs} " +
|
||||
$"encryptedHandshake={useEncryptedHandshake} handshakeTimeoutMs={handshakeTimeoutMs} " +
|
||||
$"roleRequest={FormatDebugValue(roleRequestCommand)} rolePrefix={FormatDebugValue(roleResponsePrefix)}");
|
||||
}
|
||||
if (ports.Length == 0)
|
||||
{
|
||||
@ -474,8 +488,22 @@ namespace DanroJump.Hardware.Com
|
||||
|
||||
private void EnsureInfrastructure()
|
||||
{
|
||||
portProvider ??= new ReflectionComPortProvider();
|
||||
transportFactory ??= new ReflectionSerialComTransportFactory();
|
||||
portProvider ??= CreateDefaultPortProvider();
|
||||
transportFactory ??= CreateDefaultTransportFactory();
|
||||
}
|
||||
|
||||
private static IComPortProvider CreateDefaultPortProvider()
|
||||
{
|
||||
return new FallbackComPortProvider(
|
||||
new ReflectionComPortProvider(),
|
||||
new NativeComPortProvider());
|
||||
}
|
||||
|
||||
private static IComTransportFactory CreateDefaultTransportFactory()
|
||||
{
|
||||
return new FallbackComTransportFactory(
|
||||
new ReflectionSerialComTransportFactory(),
|
||||
new NativeComTransportFactory());
|
||||
}
|
||||
|
||||
private void EnsureLightingSystem()
|
||||
@ -1257,6 +1285,7 @@ namespace DanroJump.Hardware.Com
|
||||
roleRequestCommand,
|
||||
roleResponsePrefix,
|
||||
roleRequestTimeoutMs,
|
||||
message => LogDebug(DebugLogChannel.ComLifecycle, logLifecycle, message),
|
||||
message => LogWarning(DebugLogChannel.ComLifecycle, logLifecycle, message));
|
||||
|
||||
Subscribe(device);
|
||||
@ -1611,6 +1640,25 @@ namespace DanroJump.Hardware.Com
|
||||
return string.IsNullOrWhiteSpace(value) ? "<unknown>" : value;
|
||||
}
|
||||
|
||||
private static string FormatList(IEnumerable<string> values)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
List<string> filtered = new();
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
filtered.Add(value.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
return filtered.Count > 0 ? string.Join(", ", filtered) : "";
|
||||
}
|
||||
|
||||
private static async UniTask RunLoggedTaskAsync(Func<UniTask> taskFactory, CancellationToken token, string operationName)
|
||||
{
|
||||
try
|
||||
@ -1759,6 +1807,7 @@ namespace DanroJump.Hardware.Com
|
||||
private readonly string roleRequestCommand;
|
||||
private readonly string roleResponsePrefix;
|
||||
private readonly int roleRequestTimeoutMs;
|
||||
private readonly Action<string> logInfo;
|
||||
private readonly Action<string> logWarning;
|
||||
private readonly byte[] aesKey;
|
||||
|
||||
@ -1798,6 +1847,7 @@ namespace DanroJump.Hardware.Com
|
||||
string roleRequestCommand,
|
||||
string roleResponsePrefix,
|
||||
int roleRequestTimeoutMs,
|
||||
Action<string> logInfo,
|
||||
Action<string> logWarning)
|
||||
{
|
||||
this.transportFactory = transportFactory ?? throw new ArgumentNullException(nameof(transportFactory));
|
||||
@ -1817,6 +1867,7 @@ namespace DanroJump.Hardware.Com
|
||||
this.roleRequestCommand = roleRequestCommand?.Trim() ?? "";
|
||||
this.roleResponsePrefix = string.IsNullOrWhiteSpace(roleResponsePrefix) ? "ROLE" : roleResponsePrefix.Trim();
|
||||
this.roleRequestTimeoutMs = Mathf.Max(200, roleRequestTimeoutMs);
|
||||
this.logInfo = logInfo;
|
||||
this.logWarning = logWarning;
|
||||
aesKey = BuildAesKey();
|
||||
}
|
||||
@ -1899,14 +1950,17 @@ namespace DanroJump.Hardware.Com
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo($"{PortName} read loop starting.");
|
||||
RunLoggedTask(() => ReadLoopAsync(localCts.Token), localCts.Token, $"{PortName} read loop");
|
||||
|
||||
if (useEncryptedHandshake)
|
||||
{
|
||||
LogInfo($"{PortName} encrypted handshake starting.");
|
||||
RunLoggedTask(() => RunHandshakeAsync(localCts.Token), localCts.Token, $"{PortName} handshake");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo($"{PortName} encrypted handshake disabled; marking operational.");
|
||||
MarkOperational();
|
||||
}
|
||||
|
||||
@ -1963,6 +2017,7 @@ namespace DanroJump.Hardware.Com
|
||||
{
|
||||
try
|
||||
{
|
||||
LogInfo($"{PortName} opening serial port. settings={baudRate}/{dataBits}/{parity}/{stopBits} readTimeoutMs={readTimeoutMs} writeTimeoutMs={writeTimeoutMs}");
|
||||
lock (ioLock)
|
||||
{
|
||||
serialPort = transportFactory.Create(new SerialSettings(
|
||||
@ -1980,11 +2035,12 @@ namespace DanroJump.Hardware.Com
|
||||
}
|
||||
|
||||
lastCoinTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
LogInfo($"{PortName} serial port opened successfully.");
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogWarning($"Failed to open {PortName}: {exception.Message}");
|
||||
LogWarning($"Failed to open {PortName}: {exception.GetType().Name}: {exception.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2092,6 +2148,7 @@ namespace DanroJump.Hardware.Com
|
||||
handshakeCompletion = NewCompletion<bool>();
|
||||
chalCompletion = NewCompletion<bool>();
|
||||
requestHex = GenerateRandomBlock16Hex();
|
||||
LogInfo($"{PortName} handshake: sending challenge request command 07<random16>.");
|
||||
Send("07" + requestHex, true);
|
||||
|
||||
var (chalReceived, _) = await UniTask.WhenAny(
|
||||
@ -2104,12 +2161,14 @@ namespace DanroJump.Hardware.Com
|
||||
return;
|
||||
}
|
||||
|
||||
LogInfo($"{PortName} handshake: CHAL received, waiting RAES.");
|
||||
var (handshakeFinished, handshakeSucceeded) = await UniTask.WhenAny(
|
||||
handshakeCompletion.Task,
|
||||
UniTask.Delay(handshakeTimeoutMs, DelayType.Realtime, PlayerLoopTiming.Update, token));
|
||||
await UniTask.SwitchToThreadPool();
|
||||
if (handshakeFinished && handshakeSucceeded)
|
||||
{
|
||||
LogInfo($"{PortName} handshake: RAES verified.");
|
||||
MarkOperational();
|
||||
return;
|
||||
}
|
||||
@ -2126,12 +2185,14 @@ namespace DanroJump.Hardware.Com
|
||||
|
||||
if (handshakeStage == HandshakeStage.WaitingChal && line.StartsWith("CHAL", StringComparison.Ordinal))
|
||||
{
|
||||
LogInfo($"{PortName} handshake line received: CHAL length={line.Length}.");
|
||||
HandleChal(line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handshakeStage == HandshakeStage.WaitingRaes && line.StartsWith("RAES", StringComparison.Ordinal))
|
||||
{
|
||||
LogInfo($"{PortName} handshake line received: RAES length={line.Length}.");
|
||||
HandleRaes(line);
|
||||
}
|
||||
}
|
||||
@ -2207,6 +2268,7 @@ namespace DanroJump.Hardware.Com
|
||||
isOperational = true;
|
||||
handshakeStage = HandshakeStage.Completed;
|
||||
missedInputResponses = 0;
|
||||
LogInfo($"{PortName} marked operational. Sending startup commands.");
|
||||
|
||||
Send("2171", true);
|
||||
Send("890003", true);
|
||||
@ -2230,6 +2292,7 @@ namespace DanroJump.Hardware.Com
|
||||
if (!string.IsNullOrWhiteSpace(roleRequestCommand))
|
||||
{
|
||||
roleCompletion = NewCompletion<string>();
|
||||
LogInfo($"{PortName} identity: requesting role with command {roleRequestCommand}, expecting prefix {roleResponsePrefix}.");
|
||||
Send(roleRequestCommand);
|
||||
|
||||
var (roleReceived, role) = await UniTask.WhenAny(
|
||||
@ -2239,10 +2302,16 @@ namespace DanroJump.Hardware.Com
|
||||
if (roleReceived)
|
||||
{
|
||||
Role = role;
|
||||
LogInfo($"{PortName} identity: role received '{Role}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo($"{PortName} identity: role request timed out after {roleRequestTimeoutMs} ms.");
|
||||
}
|
||||
}
|
||||
|
||||
macCompletion = NewCompletion<string>();
|
||||
LogInfo($"{PortName} identity: requesting MAC with command 06.");
|
||||
Send("06");
|
||||
|
||||
var (macReceived, macAddress) = await UniTask.WhenAny(
|
||||
@ -2252,6 +2321,11 @@ namespace DanroJump.Hardware.Com
|
||||
if (macReceived)
|
||||
{
|
||||
MacAddress = macAddress;
|
||||
LogInfo($"{PortName} identity: MAC received {MacAddress}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo($"{PortName} identity: MAC request timed out after {roleRequestTimeoutMs} ms.");
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@ -2528,6 +2602,7 @@ namespace DanroJump.Hardware.Com
|
||||
}
|
||||
|
||||
isOperational = false;
|
||||
LogInfo($"{PortName} notifying disconnected.");
|
||||
localCts?.Cancel();
|
||||
ClosePort();
|
||||
Disconnected?.Invoke(this);
|
||||
@ -2559,9 +2634,15 @@ namespace DanroJump.Hardware.Com
|
||||
|
||||
serialPort.Dispose();
|
||||
serialPort = null;
|
||||
LogInfo($"{PortName} serial port closed.");
|
||||
}
|
||||
}
|
||||
|
||||
private void LogInfo(string message)
|
||||
{
|
||||
logInfo?.Invoke(message);
|
||||
}
|
||||
|
||||
private string EncryptHexBlock16(string plainHex)
|
||||
{
|
||||
byte[] plain = HexToBytes(plainHex);
|
||||
|
||||
@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DanroJump.Hardware.Com
|
||||
{
|
||||
/// <summary>
|
||||
/// Поставщик портов, который переходит на запасной источник, если основной не нашел порты или упал.
|
||||
/// </summary>
|
||||
public sealed class FallbackComPortProvider : IComPortProvider
|
||||
{
|
||||
private readonly IComPortProvider primaryProvider;
|
||||
private readonly IComPortProvider fallbackProvider;
|
||||
|
||||
public FallbackComPortProvider(IComPortProvider primaryProvider, IComPortProvider fallbackProvider)
|
||||
{
|
||||
this.primaryProvider = primaryProvider ?? throw new ArgumentNullException(nameof(primaryProvider));
|
||||
this.fallbackProvider = fallbackProvider ?? throw new ArgumentNullException(nameof(fallbackProvider));
|
||||
}
|
||||
|
||||
public string[] GetPortNames()
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] primaryPorts = primaryProvider.GetPortNames() ?? Array.Empty<string>();
|
||||
if (primaryPorts.Length > 0)
|
||||
{
|
||||
return primaryPorts;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[ComSystem] Primary COM port provider returned no ports. Trying native ComNative provider.");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogWarning($"[ComSystem] Primary COM port provider failed: {exception.GetType().Name}: {exception.Message}. Trying native ComNative provider.");
|
||||
}
|
||||
|
||||
return fallbackProvider.GetPortNames() ?? Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Фабрика транспорта, которая открывает порт через основной backend и переключается на запасной при ошибке.
|
||||
/// </summary>
|
||||
public sealed class FallbackComTransportFactory : IComTransportFactory
|
||||
{
|
||||
private readonly IComTransportFactory primaryFactory;
|
||||
private readonly IComTransportFactory fallbackFactory;
|
||||
|
||||
public FallbackComTransportFactory(IComTransportFactory primaryFactory, IComTransportFactory fallbackFactory)
|
||||
{
|
||||
this.primaryFactory = primaryFactory ?? throw new ArgumentNullException(nameof(primaryFactory));
|
||||
this.fallbackFactory = fallbackFactory ?? throw new ArgumentNullException(nameof(fallbackFactory));
|
||||
}
|
||||
|
||||
public IComTransport Create(SerialSettings settings)
|
||||
{
|
||||
return new FallbackComTransport(settings, primaryFactory, fallbackFactory);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class FallbackComTransport : IComTransport
|
||||
{
|
||||
private const string PrimaryBackendName = "System.IO.Ports";
|
||||
private const string FallbackBackendName = "ComNative";
|
||||
|
||||
private readonly SerialSettings settings;
|
||||
private readonly IComTransportFactory primaryFactory;
|
||||
private readonly IComTransportFactory fallbackFactory;
|
||||
private IComTransport activeTransport;
|
||||
private string activeBackendName = "";
|
||||
|
||||
public FallbackComTransport(
|
||||
SerialSettings settings,
|
||||
IComTransportFactory primaryFactory,
|
||||
IComTransportFactory fallbackFactory)
|
||||
{
|
||||
this.settings = settings;
|
||||
this.primaryFactory = primaryFactory;
|
||||
this.fallbackFactory = fallbackFactory;
|
||||
}
|
||||
|
||||
public bool IsOpen => activeTransport != null && activeTransport.IsOpen;
|
||||
|
||||
public void Open()
|
||||
{
|
||||
if (IsOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Exception primaryException = null;
|
||||
try
|
||||
{
|
||||
OpenWith(primaryFactory, PrimaryBackendName);
|
||||
return;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
primaryException = exception;
|
||||
DisposeActiveTransport();
|
||||
Debug.LogWarning($"[ComSystem] System.IO.Ports failed for {settings.PortName}: {exception.GetType().Name}: {exception.Message}. Trying ComNative.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
OpenWith(fallbackFactory, FallbackBackendName);
|
||||
}
|
||||
catch (Exception fallbackException)
|
||||
{
|
||||
DisposeActiveTransport();
|
||||
throw new InvalidOperationException(
|
||||
$"Both COM backends failed for {settings.PortName}. " +
|
||||
$"System.IO.Ports: {primaryException.GetType().Name}: {primaryException.Message}. " +
|
||||
$"ComNative: {fallbackException.GetType().Name}: {fallbackException.Message}",
|
||||
fallbackException);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
activeTransport?.Close();
|
||||
}
|
||||
|
||||
public void DiscardInBuffer()
|
||||
{
|
||||
try
|
||||
{
|
||||
RequireActiveTransport().DiscardInBuffer();
|
||||
}
|
||||
catch (Exception exception) when (TrySwitchToFallback(exception, "discard input buffer"))
|
||||
{
|
||||
RequireActiveTransport().DiscardInBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardOutBuffer()
|
||||
{
|
||||
try
|
||||
{
|
||||
RequireActiveTransport().DiscardOutBuffer();
|
||||
}
|
||||
catch (Exception exception) when (TrySwitchToFallback(exception, "discard output buffer"))
|
||||
{
|
||||
RequireActiveTransport().DiscardOutBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
public string ReadLine()
|
||||
{
|
||||
try
|
||||
{
|
||||
return RequireActiveTransport().ReadLine();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception exception) when (TrySwitchToFallback(exception, "read"))
|
||||
{
|
||||
return RequireActiveTransport().ReadLine();
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteLine(string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
RequireActiveTransport().WriteLine(value);
|
||||
}
|
||||
catch (Exception exception) when (TrySwitchToFallback(exception, "write"))
|
||||
{
|
||||
RequireActiveTransport().WriteLine(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeActiveTransport();
|
||||
}
|
||||
|
||||
private void OpenWith(IComTransportFactory factory, string backendName)
|
||||
{
|
||||
activeTransport = factory.Create(settings);
|
||||
activeTransport.Open();
|
||||
activeBackendName = backendName;
|
||||
Debug.Log($"[ComSystem] {settings.PortName} serial backend selected: {activeBackendName}.");
|
||||
}
|
||||
|
||||
private IComTransport RequireActiveTransport()
|
||||
{
|
||||
if (activeTransport == null)
|
||||
{
|
||||
throw new InvalidOperationException($"COM port {settings.PortName} has no active transport backend.");
|
||||
}
|
||||
|
||||
return activeTransport;
|
||||
}
|
||||
|
||||
private bool TrySwitchToFallback(Exception exception, string operationName)
|
||||
{
|
||||
if (!string.Equals(activeBackendName, PrimaryBackendName, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.LogWarning(
|
||||
$"[ComSystem] {PrimaryBackendName} {operationName} failed for {settings.PortName}: " +
|
||||
$"{exception.GetType().Name}: {exception.Message}. Switching to {FallbackBackendName}.");
|
||||
|
||||
DisposeActiveTransport();
|
||||
OpenWith(fallbackFactory, FallbackBackendName);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void DisposeActiveTransport()
|
||||
{
|
||||
try
|
||||
{
|
||||
activeTransport?.Dispose();
|
||||
}
|
||||
finally
|
||||
{
|
||||
activeTransport = null;
|
||||
activeBackendName = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 931f17b413d5e4b4ab7315bb21e810a0
|
||||
@ -0,0 +1,266 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DanroJump.Hardware.Com
|
||||
{
|
||||
/// <summary>
|
||||
/// Получает список COM-портов через native-плагин ComNative.
|
||||
/// </summary>
|
||||
public sealed class NativeComPortProvider : IComPortProvider
|
||||
{
|
||||
public string[] GetPortNames()
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] ports = ComNativeMethods.ListPorts();
|
||||
Debug.Log($"[ComSystem] ComNative.ListPorts returned: {(ports.Length > 0 ? string.Join(", ", ports) : "<none>")}");
|
||||
return ports;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogWarning($"[ComSystem] ComNative.ListPorts failed: {exception.GetType().Name}: {exception.Message}");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает COM-транспорт через native-плагин ComNative.
|
||||
/// </summary>
|
||||
public sealed class NativeComTransportFactory : IComTransportFactory
|
||||
{
|
||||
public IComTransport Create(SerialSettings settings)
|
||||
{
|
||||
return new NativeComTransport(settings);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Native serial-транспорт для IL2CPP-билдов, где System.IO.Ports.SerialPort может быть недоступен.
|
||||
/// </summary>
|
||||
internal sealed class NativeComTransport : IComTransport
|
||||
{
|
||||
private const int ReadBufferSize = 4096;
|
||||
private const int MaxFlushLines = 100;
|
||||
|
||||
private readonly SerialSettings settings;
|
||||
private int handleId;
|
||||
|
||||
public NativeComTransport(SerialSettings settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public bool IsOpen => handleId > 0;
|
||||
|
||||
public void Open()
|
||||
{
|
||||
if (IsOpen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handleId = ComNativeMethods.Serial_Open(
|
||||
settings.PortName,
|
||||
settings.BaudRate,
|
||||
settings.DataBits,
|
||||
ConvertParity(settings.Parity),
|
||||
ConvertStopBits(settings.StopBits),
|
||||
settings.ReadTimeoutMs,
|
||||
settings.WriteTimeoutMs);
|
||||
|
||||
if (handleId <= 0)
|
||||
{
|
||||
string nativeError = ComNativeMethods.GetLastError();
|
||||
handleId = 0;
|
||||
throw new IOException($"ComNative failed to open {settings.PortName}: {nativeError}");
|
||||
}
|
||||
|
||||
Debug.Log($"[ComSystem] ComNative opened {settings.PortName} with handle {handleId}.");
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (handleId <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int closingHandle = handleId;
|
||||
handleId = 0;
|
||||
int result = ComNativeMethods.Serial_Close(closingHandle);
|
||||
if (result < 0)
|
||||
{
|
||||
Debug.LogWarning($"[ComSystem] ComNative close failed for handle {closingHandle}: {ComNativeMethods.GetLastError()}");
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardInBuffer()
|
||||
{
|
||||
EnsureOpen();
|
||||
|
||||
byte[] buffer = new byte[ReadBufferSize];
|
||||
for (int i = 0; i < MaxFlushLines; i++)
|
||||
{
|
||||
int read = ComNativeMethods.Serial_ReadLineUTF8_bytes(handleId, buffer, buffer.Length);
|
||||
if (read <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardOutBuffer()
|
||||
{
|
||||
// Native plugin has no explicit outgoing-buffer flush API.
|
||||
}
|
||||
|
||||
public string ReadLine()
|
||||
{
|
||||
EnsureOpen();
|
||||
|
||||
byte[] buffer = new byte[ReadBufferSize];
|
||||
int read = ComNativeMethods.Serial_ReadLineUTF8_bytes(handleId, buffer, buffer.Length);
|
||||
if (read == 0)
|
||||
{
|
||||
throw new TimeoutException();
|
||||
}
|
||||
|
||||
if (read < 0)
|
||||
{
|
||||
throw new IOException($"ComNative read failed on {settings.PortName}: {ComNativeMethods.GetLastError()}");
|
||||
}
|
||||
|
||||
int count = Math.Min(read, buffer.Length);
|
||||
return Encoding.UTF8.GetString(buffer, 0, count).TrimEnd('\r', '\n');
|
||||
}
|
||||
|
||||
public void WriteLine(string value)
|
||||
{
|
||||
EnsureOpen();
|
||||
|
||||
int result = ComNativeMethods.Serial_WriteStringUTF8(handleId, value ?? "", appendNewline: 1);
|
||||
if (result < 0)
|
||||
{
|
||||
throw new IOException($"ComNative write failed on {settings.PortName}: {ComNativeMethods.GetLastError()}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void EnsureOpen()
|
||||
{
|
||||
if (!IsOpen)
|
||||
{
|
||||
throw new InvalidOperationException($"ComNative port {settings.PortName} is not open.");
|
||||
}
|
||||
}
|
||||
|
||||
private static int ConvertParity(SerialParity parity)
|
||||
{
|
||||
return parity switch
|
||||
{
|
||||
SerialParity.Odd => 1,
|
||||
SerialParity.Even => 2,
|
||||
SerialParity.Mark => 3,
|
||||
SerialParity.Space => 4,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
private static int ConvertStopBits(SerialStopBits stopBits)
|
||||
{
|
||||
return stopBits switch
|
||||
{
|
||||
SerialStopBits.Two => 2,
|
||||
SerialStopBits.OnePointFive => 3,
|
||||
_ => 1
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ComNativeMethods
|
||||
{
|
||||
private const string Dll = "ComNative";
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
|
||||
public static extern int Serial_ListPortsLength();
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
|
||||
public static extern int Serial_ListPorts(StringBuilder buffer, int bufferChars);
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
|
||||
public static extern int Serial_Open(
|
||||
string portName,
|
||||
int baud,
|
||||
int dataBits,
|
||||
int parity,
|
||||
int stopBits,
|
||||
int readTimeoutMs,
|
||||
int writeTimeoutMs);
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int Serial_Close(int handleId);
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int Serial_CloseAll();
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
|
||||
public static extern int Serial_WriteStringUTF8(int handleId, string utf8, int appendNewline);
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Serial_ReadLineUTF8")]
|
||||
public static extern int Serial_ReadLineUTF8_bytes(int handleId, byte[] buffer, int bufferSize);
|
||||
|
||||
[DllImport(Dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
|
||||
public static extern int Serial_GetLastErrorW(StringBuilder buffer, int bufferChars);
|
||||
|
||||
public static string GetLastError()
|
||||
{
|
||||
int requiredLength = Serial_GetLastErrorW(null, 0);
|
||||
if (requiredLength < 0)
|
||||
{
|
||||
return $"Serial_GetLastErrorW failed with code {requiredLength}.";
|
||||
}
|
||||
|
||||
var buffer = new StringBuilder(Math.Max(requiredLength, 1));
|
||||
int result = Serial_GetLastErrorW(buffer, buffer.Capacity);
|
||||
return result < 0 ? $"Serial_GetLastErrorW failed with code {result}." : buffer.ToString();
|
||||
}
|
||||
|
||||
public static string[] ListPorts()
|
||||
{
|
||||
int requiredLength = Serial_ListPortsLength();
|
||||
if (requiredLength <= 1)
|
||||
{
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
var buffer = new StringBuilder(requiredLength);
|
||||
int result = Serial_ListPorts(buffer, buffer.Capacity);
|
||||
if (result < 0)
|
||||
{
|
||||
throw new IOException($"ComNative port listing failed: {GetLastError()}");
|
||||
}
|
||||
|
||||
string joined = buffer.ToString();
|
||||
if (string.IsNullOrWhiteSpace(joined))
|
||||
{
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
string[] rawPorts = joined.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int i = 0; i < rawPorts.Length; i++)
|
||||
{
|
||||
rawPorts[i] = rawPorts[i].Trim();
|
||||
}
|
||||
|
||||
return rawPorts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19898e41b209f744f91b180136b8f18c
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
@ -9,29 +10,189 @@ namespace DanroJump.Hardware.Com
|
||||
/// </summary>
|
||||
public sealed class ReflectionComPortProvider : IComPortProvider
|
||||
{
|
||||
private static readonly Type SerialPortType = Type.GetType("System.IO.Ports.SerialPort, System");
|
||||
private static readonly Type SerialPortType = FindSerialPortType();
|
||||
private static bool diagnosticLogged;
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает имена доступных serial-портов или пустой список, если API недоступен.
|
||||
/// </summary>
|
||||
public string[] GetPortNames()
|
||||
{
|
||||
LogSerialPortDiagnosticOnce();
|
||||
|
||||
string[] registryPorts = GetWindowsRegistryPortNames();
|
||||
if (SerialPortType == null)
|
||||
{
|
||||
Debug.LogWarning("[ComSystem] System.IO.Ports.SerialPort is not available in this Unity profile.");
|
||||
return Array.Empty<string>();
|
||||
return registryPorts;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return (string[])SerialPortType.GetMethod("GetPortNames", BindingFlags.Public | BindingFlags.Static)
|
||||
?.Invoke(null, null) ?? Array.Empty<string>();
|
||||
var getPortNamesMethod = SerialPortType.GetMethod("GetPortNames", BindingFlags.Public | BindingFlags.Static);
|
||||
if (getPortNamesMethod == null)
|
||||
{
|
||||
Debug.LogWarning("[ComSystem] System.IO.Ports.SerialPort.GetPortNames() is not available.");
|
||||
return registryPorts;
|
||||
}
|
||||
|
||||
var ports = (string[])getPortNamesMethod.Invoke(null, null) ?? Array.Empty<string>();
|
||||
Debug.Log($"[ComSystem] SerialPort.GetPortNames returned: {(ports.Length > 0 ? string.Join(", ", ports) : "<none>")}");
|
||||
return ports.Length > 0 ? ports : registryPorts;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogWarning($"[ComSystem] Failed to list COM ports: {Unwrap(exception).Message}");
|
||||
Exception unwrapped = Unwrap(exception);
|
||||
Debug.LogWarning($"[ComSystem] Failed to list COM ports via SerialPort.GetPortNames: {unwrapped.GetType().Name}: {unwrapped.Message}");
|
||||
return registryPorts;
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] GetWindowsRegistryPortNames()
|
||||
{
|
||||
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
|
||||
try
|
||||
{
|
||||
Type registryType = FindType("Microsoft.Win32.Registry");
|
||||
Type registryKeyType = FindType("Microsoft.Win32.RegistryKey");
|
||||
if (registryType == null || registryKeyType == null)
|
||||
{
|
||||
Debug.Log("[ComSystem] Windows registry API is not available for COM fallback.");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
object localMachine = registryType.GetProperty("LocalMachine", BindingFlags.Public | BindingFlags.Static)
|
||||
?.GetValue(null);
|
||||
if (localMachine == null)
|
||||
{
|
||||
localMachine = registryType.GetField("LocalMachine", BindingFlags.Public | BindingFlags.Static)
|
||||
?.GetValue(null);
|
||||
}
|
||||
|
||||
if (localMachine == null)
|
||||
{
|
||||
Debug.Log("[ComSystem] Windows registry fallback could not access LocalMachine.");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
MethodInfo openSubKey = registryKeyType.GetMethod(
|
||||
"OpenSubKey",
|
||||
BindingFlags.Public | BindingFlags.Instance,
|
||||
null,
|
||||
new[] { typeof(string) },
|
||||
null);
|
||||
MethodInfo getValueNames = registryKeyType.GetMethod(
|
||||
"GetValueNames",
|
||||
BindingFlags.Public | BindingFlags.Instance,
|
||||
null,
|
||||
Type.EmptyTypes,
|
||||
null);
|
||||
MethodInfo getValue = registryKeyType.GetMethod(
|
||||
"GetValue",
|
||||
BindingFlags.Public | BindingFlags.Instance,
|
||||
null,
|
||||
new[] { typeof(string) },
|
||||
null);
|
||||
|
||||
if (openSubKey == null || getValueNames == null || getValue == null)
|
||||
{
|
||||
Debug.Log("[ComSystem] Windows registry fallback methods are not available.");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
object serialCommKey = openSubKey.Invoke(localMachine, new object[] { @"HARDWARE\DEVICEMAP\SERIALCOMM" });
|
||||
if (serialCommKey == null)
|
||||
{
|
||||
Debug.Log("[ComSystem] Windows registry fallback did not find HARDWARE\\DEVICEMAP\\SERIALCOMM.");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
using (serialCommKey as IDisposable)
|
||||
{
|
||||
var valueNames = (string[])getValueNames.Invoke(serialCommKey, null) ?? Array.Empty<string>();
|
||||
var ports = new List<string>();
|
||||
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (string valueName in valueNames)
|
||||
{
|
||||
string portName = getValue.Invoke(serialCommKey, new object[] { valueName }) as string;
|
||||
if (string.IsNullOrWhiteSpace(portName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
portName = portName.Trim();
|
||||
if (!seen.Add(portName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ports.Add(portName);
|
||||
}
|
||||
|
||||
ports.Sort(StringComparer.OrdinalIgnoreCase);
|
||||
Debug.Log($"[ComSystem] Windows registry COM fallback returned: {(ports.Count > 0 ? string.Join(", ", ports) : "<none>")}");
|
||||
return ports.ToArray();
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Exception unwrapped = Unwrap(exception);
|
||||
Debug.LogWarning($"[ComSystem] Windows registry COM fallback failed: {unwrapped.GetType().Name}: {unwrapped.Message}");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
#else
|
||||
return Array.Empty<string>();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static Type FindSerialPortType()
|
||||
{
|
||||
var type = Type.GetType("System.IO.Ports.SerialPort, System", false) ??
|
||||
Type.GetType("System.IO.Ports.SerialPort, System.IO.Ports", false);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
type = assembly.GetType("System.IO.Ports.SerialPort", false);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void LogSerialPortDiagnosticOnce()
|
||||
{
|
||||
if (diagnosticLogged)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
diagnosticLogged = true;
|
||||
string message = SerialPortType == null
|
||||
? "SerialPort API resolution failed."
|
||||
: $"SerialPort API resolved from assembly: {SerialPortType.Assembly.FullName}";
|
||||
Debug.Log($"[ComSystem] {message}");
|
||||
}
|
||||
|
||||
private static Type FindType(string fullName)
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
Type type = assembly.GetType(fullName, false);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -25,9 +25,9 @@ namespace DanroJump.Hardware.Com
|
||||
{
|
||||
private const BindingFlags InstancePublicFlags = BindingFlags.Public | BindingFlags.Instance;
|
||||
|
||||
private static readonly Type SerialPortType = Type.GetType("System.IO.Ports.SerialPort, System");
|
||||
private static readonly Type ParityType = Type.GetType("System.IO.Ports.Parity, System");
|
||||
private static readonly Type StopBitsType = Type.GetType("System.IO.Ports.StopBits, System");
|
||||
private static readonly Type SerialPortType = FindSystemIoPortsType("SerialPort");
|
||||
private static readonly Type ParityType = FindSystemIoPortsType("Parity");
|
||||
private static readonly Type StopBitsType = FindSystemIoPortsType("StopBits");
|
||||
private static readonly PropertyInfo IsOpenProperty = SerialPortType?.GetProperty("IsOpen", InstancePublicFlags);
|
||||
private static readonly PropertyInfo DataBitsProperty = SerialPortType?.GetProperty("DataBits", InstancePublicFlags);
|
||||
private static readonly PropertyInfo ParityProperty = SerialPortType?.GetProperty("Parity", InstancePublicFlags);
|
||||
@ -64,7 +64,9 @@ namespace DanroJump.Hardware.Com
|
||||
{
|
||||
if (SerialPortType == null)
|
||||
{
|
||||
throw new InvalidOperationException("System.IO.Ports.SerialPort is not available.");
|
||||
throw new InvalidOperationException(
|
||||
"System.IO.Ports.SerialPort is not available. " +
|
||||
"Check Unity API compatibility/scripting backend and whether System.IO.Ports is present in the player.");
|
||||
}
|
||||
|
||||
EnsureRequiredMetadata();
|
||||
@ -214,5 +216,27 @@ namespace DanroJump.Hardware.Com
|
||||
|
||||
return Enum.Parse(enumType, value);
|
||||
}
|
||||
|
||||
private static Type FindSystemIoPortsType(string typeName)
|
||||
{
|
||||
string fullName = "System.IO.Ports." + typeName;
|
||||
var type = Type.GetType(fullName + ", System", false) ??
|
||||
Type.GetType(fullName + ", System.IO.Ports", false);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
type = assembly.GetType(fullName, false);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,8 +48,8 @@ namespace DanroJump.Settings
|
||||
ServiceSettingsKeys.Currency),
|
||||
ServiceSettingsKeys.HopperTestButton => ServiceSettingsActionResult.Success(
|
||||
"Тест выдачи",
|
||||
"Тест выдачи подготовлен. Аппаратная команда будет подключена через призовой контур.",
|
||||
"Проверка hopper/выдачи"),
|
||||
"Запускается тест хоппера: мотор выдачи будет включен до срабатывания датчика или таймаута.",
|
||||
ServiceSettingsKeys.HopperTestButton),
|
||||
ServiceSettingsKeys.LevelsPrizesButton => ServiceSettingsActionResult.Success(
|
||||
"Настройки призов",
|
||||
PrizeInfoFormatter.Build(settings),
|
||||
|
||||
@ -43,6 +43,12 @@ namespace DanroJump.UI.Gameplay
|
||||
menuButton.RegisterCallback<FocusInEvent>(HandleButtonFocusIn);
|
||||
menuButton.RegisterCallback<FocusOutEvent>(HandleButtonFocusOut);
|
||||
}
|
||||
|
||||
if (root != null)
|
||||
{
|
||||
root.RegisterCallback<KeyDownEvent>(HandleKeyDown, TrickleDown.TrickleDown);
|
||||
root.RegisterCallback<NavigationMoveEvent>(HandleNavigationMove, TrickleDown.TrickleDown);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action ContinueRequested;
|
||||
@ -124,6 +130,12 @@ namespace DanroJump.UI.Gameplay
|
||||
menuButton.UnregisterCallback<FocusInEvent>(HandleButtonFocusIn);
|
||||
menuButton.UnregisterCallback<FocusOutEvent>(HandleButtonFocusOut);
|
||||
}
|
||||
|
||||
if (root != null)
|
||||
{
|
||||
root.UnregisterCallback<KeyDownEvent>(HandleKeyDown, TrickleDown.TrickleDown);
|
||||
root.UnregisterCallback<NavigationMoveEvent>(HandleNavigationMove, TrickleDown.TrickleDown);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Color FocusedButtonTint = new Color32(0xCE, 0xFF, 0x1A, 0xFF);
|
||||
@ -178,5 +190,102 @@ namespace DanroJump.UI.Gameplay
|
||||
{
|
||||
return Time.unscaledTime < inputEnabledAtTime;
|
||||
}
|
||||
|
||||
private void HandleKeyDown(KeyDownEvent evt)
|
||||
{
|
||||
if (IsInputGuardActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var focusedElement = root?.panel?.focusController?.focusedElement as VisualElement;
|
||||
|
||||
var direction = 0;
|
||||
switch (evt.keyCode)
|
||||
{
|
||||
case KeyCode.Tab:
|
||||
direction = evt.shiftKey ? -1 : 1;
|
||||
break;
|
||||
case KeyCode.LeftArrow:
|
||||
case KeyCode.UpArrow:
|
||||
case KeyCode.A:
|
||||
case KeyCode.W:
|
||||
direction = -1;
|
||||
break;
|
||||
case KeyCode.RightArrow:
|
||||
case KeyCode.DownArrow:
|
||||
case KeyCode.D:
|
||||
case KeyCode.S:
|
||||
direction = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (direction != 0)
|
||||
{
|
||||
NavigateFocus(focusedElement, direction);
|
||||
evt.StopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleNavigationMove(NavigationMoveEvent evt)
|
||||
{
|
||||
if (IsInputGuardActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var focusedElement = root?.panel?.focusController?.focusedElement as VisualElement;
|
||||
var direction = 0;
|
||||
switch (evt.direction)
|
||||
{
|
||||
case NavigationMoveEvent.Direction.Left:
|
||||
case NavigationMoveEvent.Direction.Up:
|
||||
direction = -1;
|
||||
break;
|
||||
case NavigationMoveEvent.Direction.Right:
|
||||
case NavigationMoveEvent.Direction.Down:
|
||||
direction = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (direction != 0)
|
||||
{
|
||||
NavigateFocus(focusedElement, direction);
|
||||
evt.StopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
private void NavigateFocus(VisualElement current, int direction)
|
||||
{
|
||||
if (continueButton == null || menuButton == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!continueButton.enabledSelf)
|
||||
{
|
||||
menuButton.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (current == continueButton)
|
||||
{
|
||||
if (direction > 0)
|
||||
{
|
||||
menuButton.Focus();
|
||||
}
|
||||
}
|
||||
else if (current == menuButton)
|
||||
{
|
||||
if (direction < 0)
|
||||
{
|
||||
continueButton.Focus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FocusDefaultButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ namespace DanroJump.UI.Gameplay
|
||||
{
|
||||
[SerializeField] private VisualTreeAsset visualTreeAsset;
|
||||
[SerializeField] private PanelSettings panelSettings;
|
||||
[SerializeField] private int sortingOrder = 10;
|
||||
[SerializeField] private int sortingOrder = 5000;
|
||||
[SerializeField] private string scoreLabelName = "ScoreValue";
|
||||
[SerializeField] private string heightLabelName = "HeightValue";
|
||||
[SerializeField] private string bestHeightLabelName = "BestHeightValue";
|
||||
@ -59,6 +59,17 @@ namespace DanroJump.UI.Gameplay
|
||||
private bool isSubscribedToSession;
|
||||
private bool isSubscribedToPrizeFlow;
|
||||
|
||||
private int lastScore = -1;
|
||||
private int lastHeight = -1;
|
||||
private int lastRecord = -1;
|
||||
private int lastLives = -1;
|
||||
private int lastCoins = -1;
|
||||
private int lastDeaths = -1;
|
||||
private int lastCombo = -1;
|
||||
private GameplaySessionState lastState = (GameplaySessionState)(-1);
|
||||
private bool isSubscribedToSettings;
|
||||
private bool enabledStatsInSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Получает игровую сессию из DI-контейнера сцены.
|
||||
/// </summary>
|
||||
@ -91,6 +102,7 @@ namespace DanroJump.UI.Gameplay
|
||||
BindPrizeOverlay();
|
||||
BindContinueOverlay();
|
||||
ShowLastPrizeResultIfNeeded();
|
||||
ResetCache();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
@ -101,6 +113,7 @@ namespace DanroJump.UI.Gameplay
|
||||
{
|
||||
SubscribeToSession();
|
||||
SubscribeToPrizeFlow();
|
||||
SubscribeToSettings();
|
||||
|
||||
if (refreshCancellation == null)
|
||||
{
|
||||
@ -108,6 +121,7 @@ namespace DanroJump.UI.Gameplay
|
||||
RefreshContinuouslyAsync(refreshCancellation.Token).Forget(Debug.LogException);
|
||||
}
|
||||
|
||||
ResetCache();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
@ -139,6 +153,7 @@ namespace DanroJump.UI.Gameplay
|
||||
|
||||
UnsubscribeFromSession();
|
||||
UnsubscribeFromPrizeFlow();
|
||||
UnsubscribeFromSettings();
|
||||
prizeResultOverlay?.Dispose();
|
||||
prizeResultOverlay = null;
|
||||
prizeOverlayRoot = null;
|
||||
@ -162,9 +177,18 @@ namespace DanroJump.UI.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
document.visualTreeAsset = visualTreeAsset;
|
||||
document.panelSettings = panelSettings;
|
||||
document.sortingOrder = sortingOrder;
|
||||
if (document.visualTreeAsset != visualTreeAsset)
|
||||
{
|
||||
document.visualTreeAsset = visualTreeAsset;
|
||||
}
|
||||
if (document.panelSettings != panelSettings)
|
||||
{
|
||||
document.panelSettings = panelSettings;
|
||||
}
|
||||
if (document.sortingOrder != sortingOrder)
|
||||
{
|
||||
document.sortingOrder = sortingOrder;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -191,6 +215,11 @@ namespace DanroJump.UI.Gameplay
|
||||
|
||||
private void BindPrizeOverlay()
|
||||
{
|
||||
if (prizeResultOverlay != null && prizeOverlayRoot != null && prizeOverlayRoot.panel != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var root = document != null ? document.rootVisualElement : null;
|
||||
var overlayRoot = root?.Q<VisualElement>("PrizeResultOverlay");
|
||||
if (overlayRoot == null)
|
||||
@ -198,12 +227,6 @@ namespace DanroJump.UI.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
if (prizeResultOverlay != null && prizeOverlayRoot == overlayRoot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
prizeResultOverlay?.Dispose();
|
||||
prizeOverlayRoot = overlayRoot;
|
||||
prizeResultOverlay = new PrizeResultOverlayWindow(overlayRoot, audioService);
|
||||
prizeResultOverlay.ReturnRequested += HandlePrizeReturnRequested;
|
||||
@ -211,6 +234,11 @@ namespace DanroJump.UI.Gameplay
|
||||
|
||||
private void BindContinueOverlay()
|
||||
{
|
||||
if (continueGameOverlay != null && continueOverlayRoot != null && continueOverlayRoot.panel != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var root = document != null ? document.rootVisualElement : null;
|
||||
var overlayRoot = root?.Q<VisualElement>("ContinueGameOverlay");
|
||||
if (overlayRoot == null)
|
||||
@ -218,12 +246,6 @@ namespace DanroJump.UI.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
if (continueGameOverlay != null && continueOverlayRoot == overlayRoot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
continueGameOverlay?.Dispose();
|
||||
continueOverlayRoot = overlayRoot;
|
||||
continueGameOverlay = new ContinueGameOverlayWindow(overlayRoot, audioService);
|
||||
continueGameOverlay.ContinueRequested += HandleContinueRequested;
|
||||
@ -243,29 +265,76 @@ namespace DanroJump.UI.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
SetLabel(scoreLabel, session.Score.ToString());
|
||||
SetLabel(heightLabel, $"{session.MaxRunHeight:0} м");
|
||||
SetLabel(bestHeightLabel, $"{session.RecordHeight:0} м");
|
||||
SetLabel(livesLabel, session.RemainingLives.ToString());
|
||||
SetLabel(coinsLabel, session.Coins.ToString());
|
||||
SetLabel(deathsLabel, session.DeathCount.ToString());
|
||||
SetLabel(stateLabel, FormatState(session.State));
|
||||
int currentScore = session.Score;
|
||||
if (currentScore != lastScore)
|
||||
{
|
||||
SetLabel(scoreLabel, currentScore.ToString());
|
||||
lastScore = currentScore;
|
||||
}
|
||||
|
||||
int currentHeight = Mathf.FloorToInt(session.MaxRunHeight);
|
||||
if (currentHeight != lastHeight)
|
||||
{
|
||||
SetLabel(heightLabel, $"{currentHeight} м");
|
||||
lastHeight = currentHeight;
|
||||
}
|
||||
|
||||
int currentRecord = Mathf.FloorToInt(session.RecordHeight);
|
||||
if (currentRecord != lastRecord)
|
||||
{
|
||||
SetLabel(bestHeightLabel, $"{currentRecord} м");
|
||||
lastRecord = currentRecord;
|
||||
}
|
||||
|
||||
int currentLives = session.RemainingLives;
|
||||
if (currentLives != lastLives)
|
||||
{
|
||||
SetLabel(livesLabel, currentLives.ToString());
|
||||
lastLives = currentLives;
|
||||
}
|
||||
|
||||
int currentCoins = session.Coins;
|
||||
if (currentCoins != lastCoins)
|
||||
{
|
||||
SetLabel(coinsLabel, currentCoins.ToString());
|
||||
lastCoins = currentCoins;
|
||||
}
|
||||
|
||||
int currentDeaths = session.DeathCount;
|
||||
if (currentDeaths != lastDeaths)
|
||||
{
|
||||
SetLabel(deathsLabel, currentDeaths.ToString());
|
||||
lastDeaths = currentDeaths;
|
||||
}
|
||||
|
||||
GameplaySessionState currentState = session.State;
|
||||
if (currentState != lastState)
|
||||
{
|
||||
SetLabel(stateLabel, FormatState(currentState));
|
||||
lastState = currentState;
|
||||
}
|
||||
|
||||
if (comboLabel != null)
|
||||
{
|
||||
if (session.CurrentCombo > 1)
|
||||
int currentCombo = session.CurrentCombo;
|
||||
if (currentCombo > 1)
|
||||
{
|
||||
var comboText = $"x{session.CurrentCombo} COMBO!";
|
||||
if (comboLabel.text != comboText)
|
||||
if (currentCombo != lastCombo)
|
||||
{
|
||||
var comboText = $"x{currentCombo} COMBO!";
|
||||
comboLabel.text = comboText;
|
||||
comboLabel.style.display = DisplayStyle.Flex;
|
||||
PulseComboLabel();
|
||||
lastCombo = currentCombo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
comboLabel.style.display = DisplayStyle.None;
|
||||
if (lastCombo != currentCombo)
|
||||
{
|
||||
comboLabel.style.display = DisplayStyle.None;
|
||||
lastCombo = currentCombo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,12 +389,14 @@ namespace DanroJump.UI.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
developmentStatsRoot.style.display = ShouldShowDevelopmentStats
|
||||
? DisplayStyle.Flex
|
||||
: DisplayStyle.None;
|
||||
var targetDisplay = ShouldShowDevelopmentStats ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
if (developmentStatsRoot.style.display != targetDisplay)
|
||||
{
|
||||
developmentStatsRoot.style.display = targetDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ShouldShowDevelopmentStats => Debug.isDebugBuild || Application.isEditor;
|
||||
private bool ShouldShowDevelopmentStats => enabledStatsInSettings && (Debug.isDebugBuild || Application.isEditor);
|
||||
|
||||
/// <summary>
|
||||
/// Подстраховывает HUD от событий, которые могли прийти до подписки.
|
||||
@ -368,10 +439,60 @@ namespace DanroJump.UI.Gameplay
|
||||
|
||||
UnsubscribeFromSession();
|
||||
session = injectedSession;
|
||||
ResetCache();
|
||||
SubscribeToSession();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void ResetCache()
|
||||
{
|
||||
lastScore = -1;
|
||||
lastHeight = -1;
|
||||
lastRecord = -1;
|
||||
lastLives = -1;
|
||||
lastCoins = -1;
|
||||
lastDeaths = -1;
|
||||
lastCombo = -1;
|
||||
lastState = (GameplaySessionState)(-1);
|
||||
}
|
||||
|
||||
private void SubscribeToSettings()
|
||||
{
|
||||
if (serviceSettings == null || isSubscribedToSettings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
serviceSettings.SettingChanged += HandleSettingChanged;
|
||||
isSubscribedToSettings = true;
|
||||
UpdateStatsVisibilityCache();
|
||||
}
|
||||
|
||||
private void UnsubscribeFromSettings()
|
||||
{
|
||||
if (serviceSettings == null || !isSubscribedToSettings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
serviceSettings.SettingChanged -= HandleSettingChanged;
|
||||
isSubscribedToSettings = false;
|
||||
}
|
||||
|
||||
private void HandleSettingChanged(string key, DanroJump.Settings.ServiceSettingValue value)
|
||||
{
|
||||
if (key == DanroJump.Settings.ServiceSettingsKeys.StatisticsButton)
|
||||
{
|
||||
UpdateStatsVisibilityCache();
|
||||
RefreshDevelopmentStatsVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStatsVisibilityCache()
|
||||
{
|
||||
enabledStatsInSettings = serviceSettings != null && serviceSettings.GetBool(DanroJump.Settings.ServiceSettingsKeys.StatisticsButton);
|
||||
}
|
||||
|
||||
private void SubscribeToSession()
|
||||
{
|
||||
if (!isActiveAndEnabled || session == null || isSubscribedToSession)
|
||||
@ -612,10 +733,9 @@ namespace DanroJump.UI.Gameplay
|
||||
|
||||
if (result.RewardKind == PrizeRewardKind.Hopper)
|
||||
{
|
||||
success = await DispenseHopperAsync(comSystem, token);
|
||||
detailMessage = success
|
||||
? "Капсула выдана успешно!"
|
||||
: "Ошибка выдачи: датчик хоппера не сработал за 10 секунд.";
|
||||
var hopperResult = await ComHopperDispenser.DispenseAsync(comSystem, token);
|
||||
success = hopperResult.IsSuccess;
|
||||
detailMessage = hopperResult.Message;
|
||||
}
|
||||
else if (result.RewardKind == PrizeRewardKind.PrizeStand)
|
||||
{
|
||||
@ -676,35 +796,5 @@ namespace DanroJump.UI.Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<bool> DispenseHopperAsync(IComSystem com, CancellationToken token)
|
||||
{
|
||||
if (com == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!com.SendToMain("301"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var tcs = new UniTaskCompletionSource();
|
||||
UnityEngine.Events.UnityAction onTriggered = () => tcs.TrySetResult();
|
||||
com.HopperSensorTriggered.AddListener(onTriggered);
|
||||
|
||||
try
|
||||
{
|
||||
await UniTask.WhenAny(
|
||||
tcs.Task,
|
||||
UniTask.Delay(TimeSpan.FromSeconds(10), cancellationToken: token)
|
||||
);
|
||||
return tcs.Task.Status == UniTaskStatus.Succeeded;
|
||||
}
|
||||
finally
|
||||
{
|
||||
com.HopperSensorTriggered.RemoveListener(onTriggered);
|
||||
com.SendToMain("300");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DanroJump.Audio;
|
||||
@ -66,6 +67,7 @@ namespace DanroJump.UI.MainMenu
|
||||
private IReadOnlyServiceSettings serviceSettings;
|
||||
private IServiceSettingsService serviceSettingsService;
|
||||
private ISceneFlowService sceneFlow;
|
||||
private IComSystem comSystem;
|
||||
private IComCreditWallet creditWallet;
|
||||
private IGameAudioService audioService;
|
||||
private IPrizeSessionStateService prizeSessionState;
|
||||
@ -92,6 +94,7 @@ namespace DanroJump.UI.MainMenu
|
||||
serviceSettingsService = injectedSettingsService;
|
||||
serviceSettings = injectedServiceSettings ?? injectedSettingsService;
|
||||
sceneFlow = injectedSceneFlow;
|
||||
comSystem = injectedComSystem;
|
||||
creditWallet = injectedComSystem;
|
||||
audioService = injectedAudioService;
|
||||
prizeSessionState = injectedPrizeSessionState;
|
||||
@ -253,6 +256,11 @@ namespace DanroJump.UI.MainMenu
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryRunHopperTest(result))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (serviceInfoModal == null || serviceInfoModal.Root == null)
|
||||
{
|
||||
return;
|
||||
@ -262,6 +270,64 @@ namespace DanroJump.UI.MainMenu
|
||||
modalStack?.Open(serviceInfoModal);
|
||||
}
|
||||
|
||||
private bool TryRunHopperTest(ServiceSettingsActionResult result)
|
||||
{
|
||||
if (!string.Equals(result.FocusKey, ServiceSettingsKeys.HopperTestButton, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (serviceInfoModal == null || serviceInfoModal.Root == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
serviceInfoModal.SetContent(
|
||||
"Тест выдачи",
|
||||
"Запускается тест хоппера...",
|
||||
"Хоппер");
|
||||
modalStack?.Open(serviceInfoModal);
|
||||
RunHopperTestAsync(this.GetCancellationTokenOnDestroy()).Forget(Debug.LogException);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async UniTask RunHopperTestAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
ResolveComSystemIfNeeded();
|
||||
|
||||
if (comSystem == null)
|
||||
{
|
||||
audioService?.Play(GameAudioEvent.UiError);
|
||||
serviceInfoModal?.SetContent(
|
||||
"Тест выдачи",
|
||||
"Ошибка: COM-система недоступна. Проверь подключение платы и запуск COM-сервиса.",
|
||||
"Хоппер");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
serviceInfoModal?.SetContent(
|
||||
"Тест выдачи",
|
||||
"Хоппер включен. Ожидаю срабатывание датчика выдачи...",
|
||||
"Хоппер");
|
||||
|
||||
var result = await ComHopperDispenser.DispenseAsync(comSystem, cancellationToken);
|
||||
audioService?.Play(result.IsSuccess ? GameAudioEvent.UiSubmit : GameAudioEvent.UiError);
|
||||
serviceInfoModal?.SetContent(
|
||||
"Тест выдачи",
|
||||
result.Message,
|
||||
"Хоппер");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
serviceInfoModal?.SetContent(
|
||||
"Тест выдачи",
|
||||
"Тест хоппера отменен.",
|
||||
"Хоппер");
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryOpenServiceTextInput(ServiceSettingsActionResult result)
|
||||
{
|
||||
if (serviceSettingsService == null ||
|
||||
@ -659,7 +725,13 @@ namespace DanroJump.UI.MainMenu
|
||||
|
||||
if (creditWallet == null && projectContext.Container.HasBinding<IComSystem>())
|
||||
{
|
||||
creditWallet = projectContext.Container.Resolve<IComSystem>();
|
||||
comSystem = projectContext.Container.Resolve<IComSystem>();
|
||||
creditWallet = comSystem;
|
||||
}
|
||||
|
||||
if (comSystem == null && projectContext.Container.HasBinding<IComSystem>())
|
||||
{
|
||||
comSystem = projectContext.Container.Resolve<IComSystem>();
|
||||
}
|
||||
|
||||
if (creditWallet == null && projectContext.Container.HasBinding<IComCreditWallet>())
|
||||
@ -693,7 +765,18 @@ namespace DanroJump.UI.MainMenu
|
||||
}
|
||||
|
||||
ResolveServiceSettingsIfNeeded();
|
||||
creditWallet ??= ComSystem.Instance;
|
||||
creditWallet ??= comSystem ?? ComSystem.Instance;
|
||||
}
|
||||
|
||||
private void ResolveComSystemIfNeeded()
|
||||
{
|
||||
if (comSystem != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResolveServiceSettingsIfNeeded();
|
||||
comSystem ??= ComSystem.Instance;
|
||||
}
|
||||
|
||||
private void RegisterCreditCallbacks()
|
||||
|
||||
113
Assets/Tests/EditMode/Editor/ComHopperDispenserTests.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DanroJump.Hardware.Com;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DanroJump.Tests.EditMode
|
||||
{
|
||||
public sealed class ComHopperDispenserTests
|
||||
{
|
||||
[Test]
|
||||
public async Task DispenseAsync_StartsAndStopsMotorOnTimeout()
|
||||
{
|
||||
var com = new StubComSystem { IsRunningValue = true };
|
||||
|
||||
var result = await ComHopperDispenser
|
||||
.DispenseAsync(com, TimeSpan.Zero, CancellationToken.None)
|
||||
.AsTask();
|
||||
|
||||
Assert.That(result.IsSuccess, Is.False);
|
||||
Assert.That(result.Message, Does.Contain("Датчик хоппера"));
|
||||
Assert.That(com.SentCommands, Is.EqualTo(new[]
|
||||
{
|
||||
ComHopperDispenser.StartMotorCommand,
|
||||
ComHopperDispenser.StopMotorCommand
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DispenseAsync_NotRunningComReturnsFailureWithoutCommands()
|
||||
{
|
||||
var com = new StubComSystem { IsRunningValue = false };
|
||||
|
||||
var result = await ComHopperDispenser
|
||||
.DispenseAsync(com, TimeSpan.Zero, CancellationToken.None)
|
||||
.AsTask();
|
||||
|
||||
Assert.That(result.IsSuccess, Is.False);
|
||||
Assert.That(result.Message, Does.Contain("не запущена"));
|
||||
Assert.That(com.SentCommands, Is.Empty);
|
||||
}
|
||||
|
||||
private sealed class StubComSystem : IComSystem
|
||||
{
|
||||
public readonly List<string> SentCommands = new();
|
||||
|
||||
public bool IsRunningValue { get; set; }
|
||||
public bool IsRunning => IsRunningValue;
|
||||
public string MainDeviceId => "main";
|
||||
public string PrizeStandDeviceId => "stand";
|
||||
public IReadOnlyCollection<string> ConnectedDeviceIds => new[] { "main" };
|
||||
public UnityEngine.Events.UnityEvent<string> DeviceAuthorized { get; } = new();
|
||||
public UnityEngine.Events.UnityEvent<string> DeviceDisconnected { get; } = new();
|
||||
public UnityEngine.Events.UnityEvent<int> PrizeBoxOpened { get; } = new();
|
||||
public int Credits => 0;
|
||||
public UnityEngine.Events.UnityEvent<int> CreditAdded { get; } = new();
|
||||
public UnityEngine.Events.UnityEvent<int> CreditRemoved { get; } = new();
|
||||
public UnityEngine.Events.UnityEvent<int> CreditsChanged { get; } = new();
|
||||
public string LastMainInputBits => string.Empty;
|
||||
public string LastMainAdcValues => string.Empty;
|
||||
public UnityEngine.Events.UnityEvent<string> MainInputReceived { get; } = new();
|
||||
public UnityEngine.Events.UnityEvent<string> MainAdcReceived { get; } = new();
|
||||
public UnityEngine.Events.UnityEvent HopperSensorTriggered { get; } = new();
|
||||
|
||||
public void StartSystem() { }
|
||||
public void StopSystem(bool sendShutdownCommands) { }
|
||||
public bool SendToMain(string command)
|
||||
{
|
||||
SentCommands.Add(command);
|
||||
return true;
|
||||
}
|
||||
public bool SendToDevice(string deviceId, string command) => true;
|
||||
public void SendToAll(string command) { }
|
||||
public string GetDeviceRole(string deviceId) => string.Empty;
|
||||
public string GetDeviceMac(string deviceId) => string.Empty;
|
||||
public UniTask<IReadOnlyDictionary<int, PrizeBoxStatus>> GetPrizeBoxStatusesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return UniTask.FromResult<IReadOnlyDictionary<int, PrizeBoxStatus>>(new Dictionary<int, PrizeBoxStatus>());
|
||||
}
|
||||
public UniTask<int[]> GetReadyPrizeBoxesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return UniTask.FromResult(Array.Empty<int>());
|
||||
}
|
||||
public UniTask<PrizeOpenResult> OpenPrizeBoxAsync(int boxNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return UniTask.FromResult(PrizeOpenResult.Fail(boxNumber, "stub"));
|
||||
}
|
||||
public UniTask<PrizeOpenResult> ForceOpenPrizeBoxAsync(int boxNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return UniTask.FromResult(PrizeOpenResult.Fail(boxNumber, "stub"));
|
||||
}
|
||||
public bool SetPrizeStandIdleLighting() => true;
|
||||
public bool HighlightPrizeBox(int boxNumber) => true;
|
||||
public void AddCredit(int amount = 1) { }
|
||||
public bool TrySpendCredits(int amount = 1) => false;
|
||||
public void SetCredits(int value) { }
|
||||
public string GetLastInputBits(string deviceId) => string.Empty;
|
||||
public string GetLastAdcValues(string deviceId) => string.Empty;
|
||||
public void PlayBoardLight(LightMode mode, float cycles = -1f) { }
|
||||
public void PlayBoardLightSequence(IReadOnlyList<LightStep> steps, bool loop) { }
|
||||
public void PlayDefaultBoardLight() { }
|
||||
public void StopBoardLightSequence() { }
|
||||
public void StopAllBoardEffects() { }
|
||||
public void BlinkHat() { }
|
||||
public void BlinkHat(float intervalSeconds) { }
|
||||
public void StopHatBlink(bool leaveHatEnabled = true) { }
|
||||
public void PauseLighting() { }
|
||||
public void ResumeLighting() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d77880810c968aa408b9b36b0ee7e9ea
|
||||
168
Assets/Tests/EditMode/Editor/ComTransportFallbackTests.cs
Normal file
@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using DanroJump.Hardware.Com;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DanroJump.Tests.EditMode
|
||||
{
|
||||
public sealed class ComTransportFallbackTests
|
||||
{
|
||||
private static readonly SerialSettings TestSettings = new(
|
||||
"COM_TEST",
|
||||
115200,
|
||||
8,
|
||||
SerialParity.None,
|
||||
SerialStopBits.One,
|
||||
50,
|
||||
100);
|
||||
|
||||
[Test]
|
||||
public void FallbackComTransportFactory_Open_UsesPrimaryWhenPrimarySucceeds()
|
||||
{
|
||||
var primaryTransport = new FakeComTransport();
|
||||
var fallbackTransport = new FakeComTransport();
|
||||
var factory = new FallbackComTransportFactory(
|
||||
new FakeComTransportFactory(primaryTransport),
|
||||
new FakeComTransportFactory(fallbackTransport));
|
||||
|
||||
using IComTransport transport = factory.Create(TestSettings);
|
||||
transport.Open();
|
||||
|
||||
Assert.That(primaryTransport.OpenCount, Is.EqualTo(1));
|
||||
Assert.That(fallbackTransport.OpenCount, Is.EqualTo(0));
|
||||
Assert.That(transport.IsOpen, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FallbackComTransportFactory_Open_UsesFallbackWhenPrimaryOpenFails()
|
||||
{
|
||||
var primaryTransport = new FakeComTransport(openException: new InvalidOperationException("SerialPort failed"));
|
||||
var fallbackTransport = new FakeComTransport();
|
||||
var factory = new FallbackComTransportFactory(
|
||||
new FakeComTransportFactory(primaryTransport),
|
||||
new FakeComTransportFactory(fallbackTransport));
|
||||
|
||||
using IComTransport transport = factory.Create(TestSettings);
|
||||
transport.Open();
|
||||
|
||||
Assert.That(primaryTransport.OpenCount, Is.EqualTo(1));
|
||||
Assert.That(primaryTransport.DisposeCount, Is.EqualTo(1));
|
||||
Assert.That(fallbackTransport.OpenCount, Is.EqualTo(1));
|
||||
Assert.That(transport.IsOpen, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FallbackComTransportFactory_DiscardInBuffer_UsesFallbackWhenPrimaryOperationFails()
|
||||
{
|
||||
var primaryTransport = new FakeComTransport(discardInException: new NotSupportedException("Discard failed"));
|
||||
var fallbackTransport = new FakeComTransport();
|
||||
var factory = new FallbackComTransportFactory(
|
||||
new FakeComTransportFactory(primaryTransport),
|
||||
new FakeComTransportFactory(fallbackTransport));
|
||||
|
||||
using IComTransport transport = factory.Create(TestSettings);
|
||||
transport.Open();
|
||||
transport.DiscardInBuffer();
|
||||
|
||||
Assert.That(primaryTransport.OpenCount, Is.EqualTo(1));
|
||||
Assert.That(primaryTransport.DisposeCount, Is.EqualTo(1));
|
||||
Assert.That(fallbackTransport.OpenCount, Is.EqualTo(1));
|
||||
Assert.That(fallbackTransport.DiscardInBufferCount, Is.EqualTo(1));
|
||||
Assert.That(transport.IsOpen, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FallbackComPortProvider_GetPortNames_UsesFallbackWhenPrimaryReturnsEmpty()
|
||||
{
|
||||
var provider = new FallbackComPortProvider(
|
||||
new FakeComPortProvider(Array.Empty<string>()),
|
||||
new FakeComPortProvider(new[] { "COM3" }));
|
||||
|
||||
string[] ports = provider.GetPortNames();
|
||||
|
||||
Assert.That(ports, Is.EqualTo(new[] { "COM3" }));
|
||||
}
|
||||
|
||||
private sealed class FakeComPortProvider : IComPortProvider
|
||||
{
|
||||
private readonly string[] ports;
|
||||
|
||||
public FakeComPortProvider(string[] ports)
|
||||
{
|
||||
this.ports = ports;
|
||||
}
|
||||
|
||||
public string[] GetPortNames()
|
||||
{
|
||||
return ports;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeComTransportFactory : IComTransportFactory
|
||||
{
|
||||
private readonly IComTransport transport;
|
||||
|
||||
public FakeComTransportFactory(IComTransport transport)
|
||||
{
|
||||
this.transport = transport;
|
||||
}
|
||||
|
||||
public IComTransport Create(SerialSettings settings)
|
||||
{
|
||||
return transport;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FakeComTransport : IComTransport
|
||||
{
|
||||
private readonly Exception openException;
|
||||
private readonly Exception discardInException;
|
||||
private bool isOpen;
|
||||
|
||||
public FakeComTransport(Exception openException = null, Exception discardInException = null)
|
||||
{
|
||||
this.openException = openException;
|
||||
this.discardInException = discardInException;
|
||||
}
|
||||
|
||||
public int OpenCount { get; private set; }
|
||||
public int DiscardInBufferCount { get; private set; }
|
||||
public int DisposeCount { get; private set; }
|
||||
public bool IsOpen => isOpen;
|
||||
|
||||
public void Open()
|
||||
{
|
||||
OpenCount++;
|
||||
if (openException != null)
|
||||
{
|
||||
throw openException;
|
||||
}
|
||||
|
||||
isOpen = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
public void DiscardInBuffer()
|
||||
{
|
||||
DiscardInBufferCount++;
|
||||
if (discardInException != null)
|
||||
{
|
||||
throw discardInException;
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardOutBuffer() { }
|
||||
public string ReadLine() => "";
|
||||
public void WriteLine(string value) { }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeCount++;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58c3e63a06e9fc04eac935acec081a3c
|
||||
@ -21,7 +21,7 @@ namespace DanroJump.Tests.EditMode
|
||||
try
|
||||
{
|
||||
var controller = gameObject.AddComponent<GameplayHudController>();
|
||||
var session = new GameplaySession(null, new StubSettings(canContinue: false));
|
||||
var session = new GameplaySession(null, new StubSettings(canContinue: true));
|
||||
TestObjectFactory.SetPrivateField(session, "<State>k__BackingField", GameplaySessionState.GameOver);
|
||||
|
||||
var overlayRoot = CreateContinueOverlayRoot();
|
||||
@ -76,7 +76,7 @@ namespace DanroJump.Tests.EditMode
|
||||
public IReadOnlyDictionary<string, ServiceSettingValue> Snapshot() => new Dictionary<string, ServiceSettingValue>();
|
||||
public ServiceSettingValue Get(string key) => default;
|
||||
public bool GetBool(string key) => key == ServiceSettingsKeys.CanContinueGame && canContinue;
|
||||
public int GetInt(string key) => 0;
|
||||
public int GetInt(string key) => key == ServiceSettingsKeys.ContinueGameCost ? 1 : 0;
|
||||
public float GetFloat(string key) => 0f;
|
||||
public string GetString(string key) => string.Empty;
|
||||
public int GetOptionIndex(string key) => 0;
|
||||
@ -118,6 +118,41 @@ namespace DanroJump.Tests.EditMode
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RefreshDevelopmentStatsVisibility_RequiresServiceSetting()
|
||||
{
|
||||
var gameObject = new GameObject("GameplayHudControllerTest");
|
||||
try
|
||||
{
|
||||
var controller = gameObject.AddComponent<GameplayHudController>();
|
||||
var statsRoot = new VisualElement { name = "RightStats" };
|
||||
|
||||
TestObjectFactory.SetPrivateField(controller, "developmentStatsRoot", statsRoot);
|
||||
TestObjectFactory.SetPrivateField(controller, "enabledStatsInSettings", false);
|
||||
|
||||
InvokeRefreshDevelopmentStatsVisibility(controller);
|
||||
|
||||
Assert.That(statsRoot.style.display.value, Is.EqualTo(DisplayStyle.None));
|
||||
|
||||
TestObjectFactory.SetPrivateField(controller, "enabledStatsInSettings", true);
|
||||
|
||||
InvokeRefreshDevelopmentStatsVisibility(controller);
|
||||
|
||||
Assert.That(statsRoot.style.display.value, Is.EqualTo(DisplayStyle.Flex));
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InvokeRefreshDevelopmentStatsVisibility(GameplayHudController controller)
|
||||
{
|
||||
typeof(GameplayHudController)
|
||||
.GetMethod("RefreshDevelopmentStatsVisibility", BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?.Invoke(controller, null);
|
||||
}
|
||||
|
||||
private sealed class StubComSystem : IComSystem
|
||||
{
|
||||
public List<string> SentCommands = new List<string>();
|
||||
|
||||
79
Assets/Tests/EditMode/Editor/OneWayPlatformColliderTests.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using DanroJump.Gameplay;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DanroJump.Tests.EditMode
|
||||
{
|
||||
public sealed class OneWayPlatformColliderTests
|
||||
{
|
||||
private GameObject playerObject;
|
||||
private GameObject platformObject;
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (playerObject != null)
|
||||
{
|
||||
Object.DestroyImmediate(playerObject);
|
||||
}
|
||||
|
||||
if (platformObject != null)
|
||||
{
|
||||
Object.DestroyImmediate(platformObject);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldCollideWith_ReturnsFalseWhenPlayerBottomIsBelowPlatformTop()
|
||||
{
|
||||
var player = CreatePlayer(centerY: 0.45f, previousGroundCheckY: 0.5f);
|
||||
var oneWayPlatform = CreatePlatform(topY: 0f);
|
||||
|
||||
Assert.That(oneWayPlatform.ShouldCollideWith(player), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldCollideWith_ReturnsTrueWhenPlayerBottomIsAtPlatformTop()
|
||||
{
|
||||
var player = CreatePlayer(centerY: 0.5f, previousGroundCheckY: 0.5f);
|
||||
var oneWayPlatform = CreatePlatform(topY: 0f);
|
||||
|
||||
Assert.That(oneWayPlatform.ShouldCollideWith(player), Is.True);
|
||||
}
|
||||
|
||||
private JumpPlayerController CreatePlayer(float centerY, float previousGroundCheckY)
|
||||
{
|
||||
playerObject = new GameObject("OneWay Platform Test Player");
|
||||
playerObject.transform.position = new Vector3(0f, centerY, 0f);
|
||||
|
||||
var groundCheckObject = new GameObject("GroundCheck");
|
||||
groundCheckObject.transform.SetParent(playerObject.transform, false);
|
||||
groundCheckObject.transform.localPosition = new Vector3(0f, -0.5f, 0f);
|
||||
|
||||
var body = playerObject.AddComponent<Rigidbody2D>();
|
||||
body.gravityScale = 0f;
|
||||
body.linearVelocity = Vector2.down;
|
||||
playerObject.AddComponent<BoxCollider2D>();
|
||||
|
||||
var player = playerObject.AddComponent<JumpPlayerController>();
|
||||
TestObjectFactory.SetPrivateField(player, "<PreviousGroundCheckY>k__BackingField", previousGroundCheckY);
|
||||
TestObjectFactory.SetPrivateField(player, "<PreviousVerticalVelocity>k__BackingField", -1f);
|
||||
return player;
|
||||
}
|
||||
|
||||
private OneWayPlatformCollider CreatePlatform(float topY)
|
||||
{
|
||||
platformObject = new GameObject("OneWay Platform Test Platform");
|
||||
platformObject.transform.position = Vector3.zero;
|
||||
|
||||
var platformCollider = platformObject.AddComponent<BoxCollider2D>();
|
||||
platformCollider.size = new Vector2(2f, 0.2f);
|
||||
platformCollider.offset = new Vector2(0f, topY - platformCollider.size.y * 0.5f);
|
||||
|
||||
var oneWayPlatform = platformObject.AddComponent<OneWayPlatformCollider>();
|
||||
oneWayPlatform.Construct(playerObject.GetComponent<JumpPlayerController>());
|
||||
oneWayPlatform.UpdateCachedTopY();
|
||||
return oneWayPlatform;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6eedb3e116ba1504b8694f7757c6f212
|
||||
@ -140,6 +140,22 @@ namespace DanroJump.Tests.EditMode
|
||||
Assert.That(result.Status, Does.Contain("малый приз включён"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HopperTestButton_ReturnsHopperTestFocusKey()
|
||||
{
|
||||
var definition = TestObjectFactory.CreateSettingDefinition(
|
||||
ServiceSettingsKeys.HopperTestButton,
|
||||
ServiceSettingValueType.Button,
|
||||
ServiceSettingValue.Button());
|
||||
|
||||
var result = ServiceSettingsActionRouter.Execute(definition, new StubReadOnlySettings());
|
||||
|
||||
Assert.That(result.Handled, Is.True);
|
||||
Assert.That(result.Title, Is.EqualTo("Тест выдачи"));
|
||||
Assert.That(result.FocusKey, Is.EqualTo(ServiceSettingsKeys.HopperTestButton));
|
||||
Assert.That(result.Status, Does.Contain("тест хоппера"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void UnknownButton_ReturnsSafeFallback()
|
||||
|
||||
@ -3,31 +3,52 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-top: 20px;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hud-column {
|
||||
flex-direction: column;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.hud-column-left {
|
||||
min-width: 460px;
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
top: 20px;
|
||||
width: 240px;
|
||||
min-width: 0;
|
||||
max-width: 240px;
|
||||
}
|
||||
|
||||
.hud-column-right {
|
||||
min-width: 500px;
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
top: 190px;
|
||||
width: 360px;
|
||||
min-width: 0;
|
||||
max-width: 360px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.hud-center {
|
||||
flex-grow: 1;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 20px;
|
||||
width: 500px;
|
||||
height: 130px;
|
||||
min-width: 0;
|
||||
max-width: 500px;
|
||||
margin-left: -250px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.hud-plaque,
|
||||
@ -45,20 +66,22 @@
|
||||
}
|
||||
|
||||
.hud-plaque-score {
|
||||
width: 450px;
|
||||
min-height: 154px;
|
||||
padding-left: 64px;
|
||||
padding-right: 64px;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 22px;
|
||||
width: 240px;
|
||||
min-height: 104px;
|
||||
padding-left: 14px;
|
||||
padding-right: 24px;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 14px;
|
||||
background-image: url("project://database/Assets/Sprites/UI/Components/plashka_side.png");
|
||||
}
|
||||
|
||||
.hud-height-plaque {
|
||||
min-width: 560px;
|
||||
height: 156px;
|
||||
padding-left: 68px;
|
||||
padding-right: 68px;
|
||||
width: 500px;
|
||||
min-width: 0;
|
||||
max-width: 500px;
|
||||
height: 130px;
|
||||
padding-left: 82px;
|
||||
padding-right: 82px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -66,7 +89,10 @@
|
||||
}
|
||||
|
||||
.hud-height-text {
|
||||
min-width: 280px;
|
||||
width: 280px;
|
||||
min-width: 0;
|
||||
max-width: 280px;
|
||||
margin-top: 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@ -86,45 +112,45 @@
|
||||
}
|
||||
|
||||
.hud-score-value {
|
||||
margin-top: -6px;
|
||||
margin-top: -14px;
|
||||
color: rgb(31, 79, 63);
|
||||
font-size: 66px;
|
||||
font-size: 36px;
|
||||
-unity-font-style: bold;
|
||||
}
|
||||
|
||||
.hud-height-value {
|
||||
margin-top: -2px;
|
||||
color: rgb(31, 79, 63);
|
||||
font-size: 58px;
|
||||
font-size: 32px;
|
||||
-unity-font-style: bold;
|
||||
-unity-text-align: middle-center;
|
||||
}
|
||||
|
||||
.hud-stat-list {
|
||||
width: 500px;
|
||||
width: 360px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.hud-stat-row {
|
||||
height: 86px;
|
||||
margin-bottom: 10px;
|
||||
padding-left: 34px;
|
||||
padding-right: 42px;
|
||||
height: 72px;
|
||||
margin-bottom: 8px;
|
||||
padding-left: 24px;
|
||||
padding-right: 28px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-image: url("project://database/Assets/Sprites/UI/Components/plashka_small.png");
|
||||
}
|
||||
|
||||
.hud-stat-caption {
|
||||
width: 156px;
|
||||
margin-left: 14px;
|
||||
font-size: 20px;
|
||||
width: 124px;
|
||||
margin-left: 10px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.hud-stat-value {
|
||||
flex-grow: 1;
|
||||
color: rgb(31, 79, 63);
|
||||
font-size: 34px;
|
||||
font-size: 28px;
|
||||
-unity-font-style: bold;
|
||||
-unity-text-align: middle-right;
|
||||
}
|
||||
@ -149,8 +175,8 @@
|
||||
}
|
||||
|
||||
.hud-mini-icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
-unity-background-scale-mode: scale-to-fit;
|
||||
background-size: contain;
|
||||
}
|
||||
@ -209,8 +235,8 @@
|
||||
|
||||
.overlay-panel {
|
||||
max-width: 1180px;
|
||||
min-width: 760px;
|
||||
min-height: 430px;
|
||||
min-width: 900px;
|
||||
min-height: 520px;
|
||||
padding-left: 86px;
|
||||
padding-right: 86px;
|
||||
padding-top: 72px;
|
||||
@ -222,7 +248,8 @@
|
||||
|
||||
.prize-panel {
|
||||
max-width: 1280px;
|
||||
min-height: 500px;
|
||||
min-width: 1100px;
|
||||
min-height: 650px;
|
||||
}
|
||||
|
||||
.overlay-title {
|
||||
@ -299,18 +326,17 @@
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
min-width: 360px;
|
||||
height: 106px;
|
||||
min-width: 420px;
|
||||
height: 120px;
|
||||
color: rgb(31, 79, 63);
|
||||
font-size: 36px;
|
||||
font-size: 32px;
|
||||
-unity-font-style: bold;
|
||||
background-image: url("project://database/Assets/Sprites/UI/Components/button_white.png");
|
||||
-unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold");
|
||||
}
|
||||
|
||||
.overlay-button-primary {
|
||||
min-width: 430px;
|
||||
background-image: url("project://database/Assets/Sprites/UI/Components/button.png");
|
||||
min-width: 480px;
|
||||
}
|
||||
|
||||
.overlay-button-secondary {
|
||||
@ -319,7 +345,7 @@
|
||||
|
||||
.overlay-button-single {
|
||||
margin-top: 66px;
|
||||
min-width: 430px;
|
||||
min-width: 480px;
|
||||
}
|
||||
|
||||
.prize-stand-container {
|
||||
|
||||
@ -2,22 +2,22 @@
|
||||
<ui:Template name="GameplayOverlays" src="project://database/Assets/UI/Gameplay/Templates/GameplayOverlays.uxml?fileID=9197481963319205126&guid=0c975b01026d5194dbc5f5264f0eee67&type=3#GameplayOverlays"/>
|
||||
<Style src="project://database/Assets/UI/Gameplay/GameplayHud.uss?fileID=7433441132597879392&guid=40e3d2a4ed0a8e84ba40618caa5869d3&type=3#GameplayHud"/>
|
||||
<ui:VisualElement name="GameplayHudRoot" class="gameplay-hud-root" style="pointer-events: none;">
|
||||
<ui:VisualElement name="LeftStats" class="hud-column hud-column-left">
|
||||
<ui:VisualElement name="VisualElement" class="hud-plaque hud-plaque-score" style="background-image: url("project://database/Assets/Sprites/UI/Components/icon.png?fileID=6934086728263231946&guid=cd717660f24894143bbbd4102e1709e6&type=3#icon_0"); min-width: 25%; max-width: 100%;">
|
||||
<ui:Label text="ВЫСОТА" class="hud-caption hud-caption-center" style="font-size: 48px; -unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); color: rgb(255, 255, 255); -unity-text-align: middle-left;"/>
|
||||
<ui:VisualElement name="LeftStats" class="hud-column hud-column-left" style="max-width: 300px;">
|
||||
<ui:VisualElement name="VisualElement" class="hud-plaque hud-plaque-score" style="background-image: url("project://database/Assets/Sprites/UI/Components/icon.png?fileID=6934086728263231946&guid=cd717660f24894143bbbd4102e1709e6&type=3#icon_0"); width: 260px; -unity-slice-scale: 0.5px; padding-left: 10px; padding-top: 10px; padding-bottom: 10px;">
|
||||
<ui:Label text="ВЫСОТА" class="hud-caption hud-caption-center" style="font-size: 30px; -unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); color: rgb(255, 255, 255); -unity-text-align: middle-left;"/>
|
||||
<ui:Label name="HeightValue" text="0 м" class="hud-height-value" style="-unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); color: rgb(255, 255, 255); -unity-text-align: middle-left;"/>
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="CenterStats" class="hud-center" style="background-image: url("project://database/Assets/Sprites/UI/Components/plashka_levels.png?fileID=2800000&guid=cc33cc4cae199f847975aec2300a7950&type=3#plashka_levels"); -unity-slice-left: 0; -unity-slice-top: 0; -unity-slice-right: 0; -unity-slice-bottom: 0; -unity-slice-scale: 100px; background-size: 100% auto;">
|
||||
<ui:VisualElement name="VisualElement" class="hud-height-plaque" style="background-image: none; min-width: 50%; height: auto; -unity-slice-left: 100; -unity-slice-top: 100; -unity-slice-right: 100; -unity-slice-bottom: 100;">
|
||||
<ui:VisualElement name="CenterStats" class="hud-center" style="background-image: url("project://database/Assets/Sprites/UI/Components/plashka_levels.png?fileID=8483911246306948391&guid=cc33cc4cae199f847975aec2300a7950&type=3#plashka_levels_1"); -unity-slice-left: 152; -unity-slice-top: 0; -unity-slice-right: 157; -unity-slice-bottom: 0; -unity-slice-scale: 0.5px; background-size: 100% 100%; width: 360px; height: 120px; left: 50%; margin-left: -180px;">
|
||||
<ui:VisualElement name="VisualElement" class="hud-height-plaque" style="background-image: none; -unity-slice-left: 100; -unity-slice-top: 100; -unity-slice-right: 100; -unity-slice-bottom: 100; -unity-slice-scale: 1px; padding-left: 48px; padding-right: 48px; width: auto; height: auto; padding-top: 10px;">
|
||||
<ui:VisualElement name="VisualElement" class="hud-icon hud-icon-crystal" style="padding-right: 32px; padding-left: 64px; display: none;"/>
|
||||
<ui:VisualElement class="hud-height-text" style="min-width: 75%; padding-top: 24px; padding-right: 32px; padding-bottom: 22px; padding-left: 32px;">
|
||||
<ui:Label text="ОЧКИ" class="hud-caption" style="color: rgb(255, 255, 255); -unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); font-size: 48px;"/>
|
||||
<ui:VisualElement class="hud-height-text" style="padding-top: 10px; padding-right: 24px; padding-bottom: 6px; padding-left: 24px;">
|
||||
<ui:Label text="ОЧКИ" class="hud-caption" style="color: rgb(255, 255, 255); -unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); font-size: 30px;"/>
|
||||
<ui:Label name="ScoreValue" text="0" class="hud-score-value" style="-unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); color: rgb(255, 255, 255);"/>
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement class="hud-icon hud-icon-crystal hud-icon-crystal-right" style="padding-left: 32px; padding-right: 64px; display: none;"/>
|
||||
</ui:VisualElement>
|
||||
<ui:Label name="ComboValue" text="x2 COMBO!" style="position: absolute; bottom: -80px; align-self: center; font-size: 54px; -unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); color: rgb(255, 140, 0); -unity-text-outline-width: 3px; -unity-text-outline-color: rgb(0, 0, 0); text-shadow: 3px 3px 0px rgba(0,0,0,0.5); display: none; transition-property: scale; transition-duration: 0.08s; transition-timing-function: ease-out;" />
|
||||
<ui:Label name="ComboValue" text="x2 COMBO!" style="position: absolute; bottom: -80px; align-self: center; font-size: 54px; -unity-font-definition: url("project://database/Assets/Fonts/RifficFree-Bold.ttf?fileID=12800000&guid=63991fec8a53abe4d9a7907ef7f0db77&type=3#RifficFree-Bold"); color: rgb(255, 140, 0); -unity-text-outline-width: 3px; -unity-text-outline-color: rgb(0, 0, 0); text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.5); display: none; transition-property: scale; transition-duration: 0.08s; transition-timing-function: ease-out;"/>
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="RightStats" class="hud-column hud-column-right">
|
||||
<ui:VisualElement class="hud-stat-list">
|
||||
|
||||
@ -24,10 +24,10 @@ MonoBehaviour:
|
||||
m_Scale: 1
|
||||
m_ReferenceDpi: 96
|
||||
m_FallbackDpi: 96
|
||||
m_ReferenceResolution: {x: 1920, y: 1080}
|
||||
m_ReferenceResolution: {x: 1080, y: 1920}
|
||||
m_ScreenMatchMode: 0
|
||||
m_Match: 0
|
||||
m_SortingOrder: 0
|
||||
m_Match: 0.5
|
||||
m_SortingOrder: 5000
|
||||
m_TargetDisplay: 0
|
||||
m_BindingLogLevel: 0
|
||||
m_ClearDepthStencil: 1
|
||||
|
||||