Compare commits
14 Commits
31f2ce338d
...
minigame_e
| Author | SHA1 | Date | |
|---|---|---|---|
| ec1a0e70aa | |||
| 46950aa877 | |||
| ae6b995f45 | |||
| b0e44f156e | |||
| bb3c91ec94 | |||
| 8326f03086 | |||
|
|
2942b22c62 | ||
|
|
38f578c56a | ||
|
|
ef3b50b99f | ||
|
|
af5dfbb7a2 | ||
| 46755fecb3 | |||
| 2ec5c3d855 | |||
| 40c3867d29 | |||
| d110616907 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -99,6 +99,8 @@ InitTestScene*.unity*
|
||||
|
||||
# Auto-generated scenes by play mode tests
|
||||
/[Aa]ssets/[Ii]nit[Tt]est[Ss]cene*.unity*
|
||||
.idea/.idea.AppleHillsProduction/.idea/indexLayout.xml
|
||||
.vscode/extensions.json
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
.idea/.idea.AppleHillsProduction/.idea/indexLayout.xml
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,194 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1021fffcba2a03d40ae5371555089a22
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 7766407121562134464
|
||||
second: monster_head1_0
|
||||
- first:
|
||||
213: -9125130289615156199
|
||||
second: monster_head1_1
|
||||
- first:
|
||||
213: -3901095240998639361
|
||||
second: monster_head1_2
|
||||
- first:
|
||||
213: 8247604547213676640
|
||||
second: monster_head1_3
|
||||
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: Android
|
||||
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: iOS
|
||||
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: monster_head1_1
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 10
|
||||
y: 5
|
||||
width: 246
|
||||
height: 345
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 91cc45e39560d5180800000000000000
|
||||
internalID: -9125130289615156199
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: e64f2633c5a06984296cf655c4c0de04
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
monster_head1_0: 7766407121562134464
|
||||
monster_head1_1: -9125130289615156199
|
||||
monster_head1_2: -3901095240998639361
|
||||
monster_head1_3: 8247604547213676640
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,190 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9ac6c3e349f9b247a0ea03665da57ce
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -7812277834941893986
|
||||
second: monster_head2_0
|
||||
- first:
|
||||
213: 8776893643225885828
|
||||
second: monster_head2_1
|
||||
- first:
|
||||
213: -1611368835902351828
|
||||
second: monster_head2_2
|
||||
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: Android
|
||||
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: iOS
|
||||
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: monster_head2_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 31
|
||||
y: 0
|
||||
width: 200
|
||||
height: 275
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: e9271a943b6359390800000000000000
|
||||
internalID: -7812277834941893986
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 53b458ab419e36f47a2f4e7800de67d7
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
monster_head2_0: -7812277834941893986
|
||||
monster_head2_1: 8776893643225885828
|
||||
monster_head2_2: -1611368835902351828
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,190 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1043ceca06eb2ac48b22c20d281278b0
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 4139348639081821586
|
||||
second: monster_head3_0
|
||||
- first:
|
||||
213: 2144489520682081444
|
||||
second: monster_head3_1
|
||||
- first:
|
||||
213: 6575383119194002169
|
||||
second: monster_head3_2
|
||||
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: Android
|
||||
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: iOS
|
||||
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: monster_head3_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 29
|
||||
y: 0
|
||||
width: 199
|
||||
height: 286
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 295f7f1f7abe17930800000000000000
|
||||
internalID: 4139348639081821586
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: c24627f1ff7adbc498117b1ab2dc914c
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
monster_head3_0: 4139348639081821586
|
||||
monster_head3_1: 2144489520682081444
|
||||
monster_head3_2: 6575383119194002169
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,190 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c85ce41979ed896429c62330c546d3ce
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: -3471612407960728276
|
||||
second: monster_head4_0
|
||||
- first:
|
||||
213: 7033164403599601001
|
||||
second: monster_head4_1
|
||||
- first:
|
||||
213: -8127244325322508915
|
||||
second: monster_head4_2
|
||||
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: Android
|
||||
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: iOS
|
||||
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: monster_head4_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 21
|
||||
y: 0
|
||||
width: 221
|
||||
height: 278
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: c2d89a988ea52dfc0800000000000000
|
||||
internalID: -3471612407960728276
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: dd6e5478aaac282458b9f8d39a624aca
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
monster_head4_0: -3471612407960728276
|
||||
monster_head4_1: 7033164403599601001
|
||||
monster_head4_2: -8127244325322508915
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Art/Textures/DivingBackground.png
Normal file
BIN
Assets/Art/Textures/DivingBackground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
195
Assets/Art/Textures/DivingBackground.png.meta
Normal file
195
Assets/Art/Textures/DivingBackground.png.meta
Normal file
@@ -0,0 +1,195 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad9b785acb09cb247ae2c8cd895863de
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 5958968447627082961
|
||||
second: DivingBackground_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: iOS
|
||||
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: Android
|
||||
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: DivingBackground_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1080
|
||||
height: 1981
|
||||
alignment: 0
|
||||
pivot: {x: 0, y: 0}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: 1dcb29c2b3282b250800000000000000
|
||||
internalID: 5958968447627082961
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
DivingBackground_0: 5958968447627082961
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
48
Assets/Editor/DivingGameManagerEditor.cs
Normal file
48
Assets/Editor/DivingGameManagerEditor.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Minigames.DivingForPictures;
|
||||
|
||||
/// <summary>
|
||||
/// Custom editor for DivingGameManager that adds runtime buttons for testing surfacing and other functionality
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(DivingGameManager))]
|
||||
public class DivingGameManagerEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// Draw the default inspector
|
||||
DrawDefaultInspector();
|
||||
|
||||
// Get the target DivingGameManager
|
||||
DivingGameManager manager = (DivingGameManager)target;
|
||||
|
||||
// Add space between default inspector and custom buttons
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// Separator line
|
||||
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
|
||||
|
||||
// Add a label for the runtime testing section
|
||||
EditorGUILayout.LabelField("Runtime Testing", EditorStyles.boldLabel);
|
||||
|
||||
// Only enable the buttons during play mode
|
||||
EditorGUI.BeginDisabledGroup(!Application.isPlaying);
|
||||
|
||||
// Add the button to call StartSurfacing
|
||||
if (GUILayout.Button("Start Surfacing", GUILayout.Height(30)))
|
||||
{
|
||||
manager.StartSurfacing();
|
||||
}
|
||||
|
||||
// Add a button for breaking a rope (for testing damage)
|
||||
if (GUILayout.Button("Break Rope (Test Damage)", GUILayout.Height(30)))
|
||||
{
|
||||
manager.ForceBreakRope();
|
||||
}
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
// Add explanatory text
|
||||
EditorGUILayout.HelpBox("These buttons only work in Play Mode. 'Start Surfacing' will reverse the trench direction, slow bubbles, and reverse obstacles. 'Break Rope' simulates player taking damage.", MessageType.Info);
|
||||
}
|
||||
}
|
||||
3
Assets/Editor/DivingGameManagerEditor.cs.meta
Normal file
3
Assets/Editor/DivingGameManagerEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bbb340d8d9b4af581770757e86cc1f8
|
||||
timeCreated: 1758532258
|
||||
776
Assets/Editor/PrefabVariantGeneratorWindow.cs
Normal file
776
Assets/Editor/PrefabVariantGeneratorWindow.cs
Normal file
@@ -0,0 +1,776 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
public class PrefabVariantGeneratorWindow : EditorWindow
|
||||
{
|
||||
// Renderer configuration class to track sprite renderers and their assigned sprites
|
||||
[System.Serializable]
|
||||
private class RendererConfig
|
||||
{
|
||||
public string Path; // Hierarchy path to the renderer
|
||||
public string Name; // Display name for the renderer
|
||||
public SpriteRenderer Renderer; // Reference to the actual renderer
|
||||
public Sprite CurrentSprite; // Current sprite in the renderer
|
||||
public List<Sprite> AssignedSprites = new List<Sprite>(); // Sprites to use for variants
|
||||
public bool Enabled = true; // Whether to include in variant generation
|
||||
public bool Expanded = true; // UI expanded state
|
||||
public Vector2 ScrollPosition; // Scroll position for sprite list
|
||||
}
|
||||
|
||||
// Main fields
|
||||
private GameObject sourcePrefab;
|
||||
private GameObject previousSourcePrefab;
|
||||
private List<RendererConfig> detectedRenderers = new List<RendererConfig>();
|
||||
private Vector2 mainScrollPosition;
|
||||
private string variantSaveFolder = "Assets/Prefabs/Variants";
|
||||
private string namingPattern = "{0}_{1}"; // Default: {0} = prefab name, {1} = first renderer sprite
|
||||
private bool userChangedSavePath = false;
|
||||
private int estimatedVariantCount = 0;
|
||||
private int maxSafeVariantCount = 100; // Warn above this number
|
||||
private GUIStyle boldFoldoutStyle;
|
||||
private bool showDefaultHelp = true;
|
||||
|
||||
// Editor window setup
|
||||
[MenuItem("Tools/Sprite Variant Generator")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<PrefabVariantGeneratorWindow>("Prefab Variant Generator");
|
||||
window.minSize = new Vector2(500, 600);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Initialize styles on enable to avoid null reference issues
|
||||
boldFoldoutStyle = new GUIStyle(EditorStyles.foldout)
|
||||
{
|
||||
fontStyle = FontStyle.Bold
|
||||
};
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
// Initialize styles if needed
|
||||
if (boldFoldoutStyle == null)
|
||||
{
|
||||
boldFoldoutStyle = new GUIStyle(EditorStyles.foldout)
|
||||
{
|
||||
fontStyle = FontStyle.Bold
|
||||
};
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("Prefab Variant Generator", EditorStyles.boldLabel);
|
||||
EditorGUILayout.HelpBox("Create multiple prefab variants with different sprites assigned to renderers.", MessageType.Info);
|
||||
|
||||
mainScrollPosition = EditorGUILayout.BeginScrollView(mainScrollPosition);
|
||||
|
||||
// Source Prefab Selection
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Step 1: Select Source Prefab", EditorStyles.boldLabel);
|
||||
|
||||
// Store previous selection to detect changes
|
||||
GameObject newSourcePrefab = (GameObject)EditorGUILayout.ObjectField("Source Prefab", sourcePrefab, typeof(GameObject), false);
|
||||
|
||||
// Check if prefab selection changed
|
||||
if (newSourcePrefab != previousSourcePrefab)
|
||||
{
|
||||
sourcePrefab = newSourcePrefab;
|
||||
previousSourcePrefab = newSourcePrefab;
|
||||
|
||||
// Auto-set save folder to match source prefab's directory if a valid prefab is selected
|
||||
if (sourcePrefab != null && !userChangedSavePath)
|
||||
{
|
||||
string prefabPath = AssetDatabase.GetAssetPath(sourcePrefab);
|
||||
if (!string.IsNullOrEmpty(prefabPath))
|
||||
{
|
||||
variantSaveFolder = Path.GetDirectoryName(prefabPath).Replace("\\", "/");
|
||||
}
|
||||
}
|
||||
|
||||
// Find sprite renderers in the prefab
|
||||
FindRenderersInPrefab();
|
||||
|
||||
// Clear default help once a prefab is selected
|
||||
if (sourcePrefab != null)
|
||||
{
|
||||
showDefaultHelp = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Warn if not a prefab
|
||||
if (sourcePrefab != null && !PrefabUtility.IsPartOfPrefabAsset(sourcePrefab) && !PrefabUtility.IsPartOfPrefabInstance(sourcePrefab))
|
||||
{
|
||||
EditorGUILayout.HelpBox("Please select a prefab asset.", MessageType.Warning);
|
||||
}
|
||||
|
||||
// Display default help if no prefab selected
|
||||
if (showDefaultHelp && sourcePrefab == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
"This tool lets you create prefab variants with different sprites.\n\n" +
|
||||
"1. Select a source prefab\n" +
|
||||
"2. Assign sprites to each detected sprite renderer\n" +
|
||||
"3. Generate all combinations as prefab variants",
|
||||
MessageType.Info
|
||||
);
|
||||
}
|
||||
|
||||
// Only show the rest if a valid prefab is selected
|
||||
if (sourcePrefab != null)
|
||||
{
|
||||
// Renderer sections
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Step 2: Configure Sprite Renderers", EditorStyles.boldLabel);
|
||||
|
||||
if (detectedRenderers.Count == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("No sprite renderers found in prefab. A new renderer will be created.", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox($"{detectedRenderers.Count} sprite renderer{(detectedRenderers.Count > 1 ? "s" : "")} found in prefab.", MessageType.Info);
|
||||
}
|
||||
|
||||
// Display each renderer configuration
|
||||
for (int i = 0; i < detectedRenderers.Count; i++)
|
||||
{
|
||||
DrawRendererSection(detectedRenderers[i], i);
|
||||
}
|
||||
|
||||
// Update estimated variant count
|
||||
UpdateVariantCount();
|
||||
|
||||
// Output settings
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Step 3: Output Settings", EditorStyles.boldLabel);
|
||||
|
||||
// Save folder
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PrefixLabel("Save Folder");
|
||||
EditorGUILayout.SelectableLabel(variantSaveFolder, EditorStyles.textField, GUILayout.Height(EditorGUIUtility.singleLineHeight));
|
||||
if (GUILayout.Button("Select...", GUILayout.Width(80)))
|
||||
{
|
||||
string newFolder = PrefabEditorUtility.SelectFolder(variantSaveFolder, "Prefabs/Variants");
|
||||
if (newFolder != variantSaveFolder)
|
||||
{
|
||||
variantSaveFolder = newFolder;
|
||||
userChangedSavePath = true; // Mark that user manually changed the path
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Add a reset button if user changed the path and a valid prefab is selected
|
||||
if (userChangedSavePath && sourcePrefab != null)
|
||||
{
|
||||
string prefabPath = AssetDatabase.GetAssetPath(sourcePrefab);
|
||||
if (!string.IsNullOrEmpty(prefabPath))
|
||||
{
|
||||
if (GUILayout.Button("Reset Path to Prefab Directory"))
|
||||
{
|
||||
variantSaveFolder = Path.GetDirectoryName(prefabPath).Replace("\\", "/");
|
||||
userChangedSavePath = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Naming pattern field
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PrefixLabel("Naming Pattern");
|
||||
namingPattern = EditorGUILayout.TextField(namingPattern);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Help text for naming pattern
|
||||
StringBuilder helpText = new StringBuilder("Naming placeholders:\n");
|
||||
helpText.AppendLine("{0} = Prefab name");
|
||||
for (int i = 0; i < detectedRenderers.Count; i++)
|
||||
{
|
||||
helpText.AppendLine($"{{{i+1}}} = {detectedRenderers[i].Name} sprite name");
|
||||
}
|
||||
EditorGUILayout.HelpBox(helpText.ToString(), MessageType.Info);
|
||||
|
||||
// Variant count display
|
||||
string variantCountText = $"Will generate {estimatedVariantCount} variant{(estimatedVariantCount != 1 ? "s" : "")}";
|
||||
if (estimatedVariantCount > maxSafeVariantCount)
|
||||
{
|
||||
EditorGUILayout.HelpBox($"Warning: {variantCountText}. This might take some time.", MessageType.Warning);
|
||||
}
|
||||
else if (estimatedVariantCount > 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox(variantCountText, MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("Please assign at least one sprite to each enabled renderer to generate variants.", MessageType.Warning);
|
||||
}
|
||||
|
||||
// Generate button
|
||||
EditorGUILayout.Space();
|
||||
GUI.enabled = estimatedVariantCount > 0;
|
||||
if (GUILayout.Button("Generate Prefab Variants", GUILayout.Height(30)))
|
||||
{
|
||||
// Show warning for large numbers of variants
|
||||
if (estimatedVariantCount > maxSafeVariantCount)
|
||||
{
|
||||
bool proceed = EditorUtility.DisplayDialog(
|
||||
"Generate Many Variants?",
|
||||
$"You are about to generate {estimatedVariantCount} prefab variants. This might take some time and use significant disk space. Continue?",
|
||||
"Generate",
|
||||
"Cancel"
|
||||
);
|
||||
|
||||
if (!proceed) return;
|
||||
}
|
||||
|
||||
GeneratePrefabVariants();
|
||||
}
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void DrawRendererSection(RendererConfig config, int index)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
// Expand/collapse button
|
||||
config.Expanded = EditorGUILayout.Foldout(config.Expanded, "", boldFoldoutStyle);
|
||||
|
||||
// Enable/disable toggle
|
||||
bool newEnabled = EditorGUILayout.Toggle(config.Enabled, GUILayout.Width(20));
|
||||
if (newEnabled != config.Enabled)
|
||||
{
|
||||
config.Enabled = newEnabled;
|
||||
UpdateVariantCount();
|
||||
}
|
||||
|
||||
// Renderer name/title
|
||||
EditorGUILayout.LabelField(config.Name, EditorStyles.boldLabel);
|
||||
|
||||
// Current sprite preview if available
|
||||
if (config.CurrentSprite != null)
|
||||
{
|
||||
GUILayout.Box(
|
||||
AssetPreview.GetAssetPreview(config.CurrentSprite),
|
||||
GUILayout.Width(40),
|
||||
GUILayout.Height(40)
|
||||
);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Only show contents if expanded
|
||||
if (config.Expanded)
|
||||
{
|
||||
// Path display
|
||||
if (!string.IsNullOrEmpty(config.Path))
|
||||
{
|
||||
EditorGUILayout.LabelField($"Path: {config.Path}", EditorStyles.miniLabel);
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!config.Enabled);
|
||||
|
||||
// Sprite selection controls
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
// Drag and drop area for sprites
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(60));
|
||||
EditorGUILayout.LabelField("Drag and drop sprites here", EditorStyles.centeredGreyMiniLabel);
|
||||
|
||||
Rect dropArea = GUILayoutUtility.GetRect(0, 40, GUILayout.ExpandWidth(true));
|
||||
HandleDragAndDrop(dropArea, config);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("Add Selected", GUILayout.Width(100), GUILayout.Height(60)))
|
||||
{
|
||||
AddSelectedSpritesToConfig(config);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("Clear Sprites"))
|
||||
{
|
||||
config.AssignedSprites.Clear();
|
||||
UpdateVariantCount();
|
||||
}
|
||||
|
||||
// Display selected sprites
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField($"Selected Sprites ({config.AssignedSprites.Count}):", EditorStyles.miniBoldLabel);
|
||||
|
||||
// Sprite list
|
||||
config.ScrollPosition = EditorGUILayout.BeginScrollView(config.ScrollPosition, GUILayout.Height(120));
|
||||
for (int i = config.AssignedSprites.Count - 1; i >= 0; i--)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
config.AssignedSprites[i] = (Sprite)EditorGUILayout.ObjectField(
|
||||
config.AssignedSprites[i],
|
||||
typeof(Sprite),
|
||||
false,
|
||||
GUILayout.ExpandWidth(true)
|
||||
);
|
||||
|
||||
// Preview sprite
|
||||
if (config.AssignedSprites[i] != null)
|
||||
{
|
||||
GUILayout.Box(
|
||||
AssetPreview.GetAssetPreview(config.AssignedSprites[i]),
|
||||
GUILayout.Width(40),
|
||||
GUILayout.Height(40)
|
||||
);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Remove", GUILayout.Width(60)))
|
||||
{
|
||||
config.AssignedSprites.RemoveAt(i);
|
||||
UpdateVariantCount();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void HandleDragAndDrop(Rect dropArea, RendererConfig config)
|
||||
{
|
||||
Event evt = Event.current;
|
||||
switch (evt.type)
|
||||
{
|
||||
case EventType.DragUpdated:
|
||||
case EventType.DragPerform:
|
||||
if (!dropArea.Contains(evt.mousePosition))
|
||||
break;
|
||||
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
|
||||
if (evt.type == EventType.DragPerform)
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
bool added = false;
|
||||
|
||||
foreach (var draggedObject in DragAndDrop.objectReferences)
|
||||
{
|
||||
if (draggedObject is Sprite sprite)
|
||||
{
|
||||
if (!config.AssignedSprites.Contains(sprite))
|
||||
{
|
||||
config.AssignedSprites.Add(sprite);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
else if (draggedObject is Texture2D texture)
|
||||
{
|
||||
// Try to get sprites from texture
|
||||
string texturePath = AssetDatabase.GetAssetPath(texture);
|
||||
var sprites = AssetDatabase.LoadAllAssetsAtPath(texturePath)
|
||||
.OfType<Sprite>()
|
||||
.ToArray();
|
||||
|
||||
foreach (var s in sprites)
|
||||
{
|
||||
if (!config.AssignedSprites.Contains(s))
|
||||
{
|
||||
config.AssignedSprites.Add(s);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added)
|
||||
{
|
||||
UpdateVariantCount();
|
||||
}
|
||||
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSelectedSpritesToConfig(RendererConfig config)
|
||||
{
|
||||
var selectedObjects = Selection.objects;
|
||||
bool added = false;
|
||||
|
||||
foreach (var obj in selectedObjects)
|
||||
{
|
||||
if (obj is Sprite sprite)
|
||||
{
|
||||
if (!config.AssignedSprites.Contains(sprite))
|
||||
{
|
||||
config.AssignedSprites.Add(sprite);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
else if (obj is Texture2D texture)
|
||||
{
|
||||
// Try to get sprites from texture
|
||||
string texturePath = AssetDatabase.GetAssetPath(texture);
|
||||
var sprites = AssetDatabase.LoadAllAssetsAtPath(texturePath)
|
||||
.OfType<Sprite>()
|
||||
.ToArray();
|
||||
|
||||
foreach (var s in sprites)
|
||||
{
|
||||
if (!config.AssignedSprites.Contains(s))
|
||||
{
|
||||
config.AssignedSprites.Add(s);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added)
|
||||
{
|
||||
UpdateVariantCount();
|
||||
}
|
||||
}
|
||||
|
||||
private void FindRenderersInPrefab()
|
||||
{
|
||||
detectedRenderers.Clear();
|
||||
|
||||
if (sourcePrefab == null) return;
|
||||
|
||||
// Get all renderers in prefab (including children)
|
||||
GameObject instance = null;
|
||||
|
||||
try
|
||||
{
|
||||
instance = (GameObject)PrefabUtility.InstantiatePrefab(sourcePrefab);
|
||||
SpriteRenderer[] renderers = instance.GetComponentsInChildren<SpriteRenderer>(true);
|
||||
|
||||
for (int i = 0; i < renderers.Length; i++)
|
||||
{
|
||||
var renderer = renderers[i];
|
||||
string path = GetRelativePath(instance.transform, renderer.transform);
|
||||
string name = renderer.gameObject.name;
|
||||
|
||||
// For root object, use "Main"
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
name = "Main";
|
||||
}
|
||||
// For objects with the same name, add index
|
||||
else if (renderers.Count(r => r.gameObject.name == renderer.gameObject.name) > 1)
|
||||
{
|
||||
name = $"{name} ({i+1})";
|
||||
}
|
||||
|
||||
detectedRenderers.Add(new RendererConfig
|
||||
{
|
||||
Path = path,
|
||||
Name = name,
|
||||
Renderer = renderer,
|
||||
CurrentSprite = renderer.sprite,
|
||||
AssignedSprites = renderer.sprite != null ?
|
||||
new List<Sprite> { renderer.sprite } :
|
||||
new List<Sprite>()
|
||||
});
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (instance != null)
|
||||
DestroyImmediate(instance);
|
||||
}
|
||||
|
||||
// If no renderers found, create a default entry
|
||||
if (detectedRenderers.Count == 0)
|
||||
{
|
||||
detectedRenderers.Add(new RendererConfig
|
||||
{
|
||||
Path = "",
|
||||
Name = "Main",
|
||||
Renderer = null,
|
||||
CurrentSprite = null,
|
||||
AssignedSprites = new List<Sprite>()
|
||||
});
|
||||
}
|
||||
|
||||
UpdateVariantCount();
|
||||
}
|
||||
|
||||
private string GetRelativePath(Transform root, Transform target)
|
||||
{
|
||||
if (target == root) return "";
|
||||
|
||||
string path = target.name;
|
||||
Transform parent = target.parent;
|
||||
|
||||
while (parent != null && parent != root)
|
||||
{
|
||||
path = parent.name + "/" + path;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private void UpdateVariantCount()
|
||||
{
|
||||
// Calculate estimated variants
|
||||
estimatedVariantCount = 0;
|
||||
|
||||
// Get only enabled renderers with at least one sprite
|
||||
var enabledConfigs = detectedRenderers
|
||||
.Where(r => r.Enabled && r.AssignedSprites.Count > 0)
|
||||
.ToList();
|
||||
|
||||
if (enabledConfigs.Count > 0)
|
||||
{
|
||||
// Start with count of first renderer's sprites
|
||||
estimatedVariantCount = enabledConfigs[0].AssignedSprites.Count;
|
||||
|
||||
// Multiply by subsequent renderers' sprite counts
|
||||
for (int i = 1; i < enabledConfigs.Count; i++)
|
||||
{
|
||||
estimatedVariantCount *= enabledConfigs[i].AssignedSprites.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<List<Sprite>> GenerateAllCombinations()
|
||||
{
|
||||
var enabledConfigs = detectedRenderers
|
||||
.Where(r => r.Enabled && r.AssignedSprites.Count > 0)
|
||||
.ToList();
|
||||
|
||||
if (enabledConfigs.Count == 0)
|
||||
return new List<List<Sprite>>();
|
||||
|
||||
// Initialize with first renderer's sprites
|
||||
var combinations = enabledConfigs[0].AssignedSprites
|
||||
.Select(s => new List<Sprite> { s })
|
||||
.ToList();
|
||||
|
||||
// Add each subsequent renderer's sprites
|
||||
for (int i = 1; i < enabledConfigs.Count; i++)
|
||||
{
|
||||
var newCombinations = new List<List<Sprite>>();
|
||||
foreach (var combo in combinations)
|
||||
{
|
||||
foreach (var sprite in enabledConfigs[i].AssignedSprites)
|
||||
{
|
||||
var newCombo = new List<Sprite>(combo) { sprite };
|
||||
newCombinations.Add(newCombo);
|
||||
}
|
||||
}
|
||||
combinations = newCombinations;
|
||||
}
|
||||
|
||||
return combinations;
|
||||
}
|
||||
|
||||
private void GeneratePrefabVariants()
|
||||
{
|
||||
if (sourcePrefab == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please select a source prefab.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get enabled renderer configurations
|
||||
var enabledConfigs = detectedRenderers
|
||||
.Where(r => r.Enabled && r.AssignedSprites.Count > 0)
|
||||
.ToList();
|
||||
|
||||
if (enabledConfigs.Count == 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please assign at least one sprite to a renderer.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the save folder exists
|
||||
EnsureFolderExists(variantSaveFolder);
|
||||
|
||||
// Generate all sprite combinations
|
||||
var combinations = GenerateAllCombinations();
|
||||
|
||||
string sourcePrefabPath = AssetDatabase.GetAssetPath(sourcePrefab);
|
||||
string prefabName = Path.GetFileNameWithoutExtension(sourcePrefabPath);
|
||||
int successCount = 0;
|
||||
|
||||
// Show progress bar
|
||||
EditorUtility.DisplayProgressBar("Generating Prefab Variants", "Preparing...", 0f);
|
||||
|
||||
try
|
||||
{
|
||||
// For each combination, create a prefab variant
|
||||
for (int i = 0; i < combinations.Count; i++)
|
||||
{
|
||||
// Update progress
|
||||
if (i % 5 == 0 || i == combinations.Count - 1)
|
||||
{
|
||||
float progress = (float)i / combinations.Count;
|
||||
if (EditorUtility.DisplayCancelableProgressBar(
|
||||
"Generating Prefab Variants",
|
||||
$"Creating variant {i+1} of {combinations.Count}",
|
||||
progress))
|
||||
{
|
||||
// User canceled
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var combination = combinations[i];
|
||||
|
||||
// Generate variant name
|
||||
string variantName = prefabName;
|
||||
string[] spriteNames = new string[combination.Count];
|
||||
|
||||
for (int j = 0; j < combination.Count; j++)
|
||||
{
|
||||
spriteNames[j] = combination[j].name;
|
||||
}
|
||||
|
||||
// Format with the naming pattern
|
||||
object[] formatArgs = new object[spriteNames.Length + 1];
|
||||
formatArgs[0] = prefabName;
|
||||
for (int j = 0; j < spriteNames.Length; j++)
|
||||
{
|
||||
formatArgs[j + 1] = spriteNames[j];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
variantName = string.Format(namingPattern, formatArgs);
|
||||
}
|
||||
catch (System.FormatException)
|
||||
{
|
||||
// Fallback if format fails
|
||||
variantName = $"{prefabName}_{string.Join("_", spriteNames)}";
|
||||
}
|
||||
|
||||
variantName = PrefabEditorUtility.SanitizeFileName(variantName);
|
||||
string variantPath = Path.Combine(variantSaveFolder, variantName + ".prefab").Replace("\\", "/");
|
||||
|
||||
// Create the prefab variant
|
||||
GameObject prefabInstance = (GameObject)PrefabUtility.InstantiatePrefab(sourcePrefab);
|
||||
|
||||
try
|
||||
{
|
||||
// Apply sprites to renderers
|
||||
for (int j = 0; j < enabledConfigs.Count; j++)
|
||||
{
|
||||
SpriteRenderer renderer = null;
|
||||
|
||||
// Find the corresponding renderer in the instance
|
||||
if (string.IsNullOrEmpty(enabledConfigs[j].Path))
|
||||
{
|
||||
// Root object
|
||||
renderer = prefabInstance.GetComponent<SpriteRenderer>();
|
||||
if (renderer == null)
|
||||
{
|
||||
renderer = prefabInstance.AddComponent<SpriteRenderer>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Child object
|
||||
Transform child = prefabInstance.transform.Find(enabledConfigs[j].Path);
|
||||
if (child != null)
|
||||
{
|
||||
renderer = child.GetComponent<SpriteRenderer>();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply sprite if renderer was found
|
||||
if (renderer != null)
|
||||
{
|
||||
renderer.sprite = combination[j];
|
||||
}
|
||||
}
|
||||
|
||||
// Create the prefab variant
|
||||
GameObject prefabVariant = PrefabUtility.SaveAsPrefabAsset(prefabInstance, variantPath);
|
||||
|
||||
if (prefabVariant != null)
|
||||
{
|
||||
successCount++;
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"Error creating prefab variant: {e.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Clean up the instance
|
||||
DestroyImmediate(prefabInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
if (successCount > 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog(
|
||||
"Prefab Variants Created",
|
||||
$"Successfully created {successCount} prefab variants in {variantSaveFolder}.",
|
||||
"OK"
|
||||
);
|
||||
|
||||
// Open the folder in Project view
|
||||
var folderObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(variantSaveFolder);
|
||||
if (folderObject != null)
|
||||
{
|
||||
Selection.activeObject = folderObject;
|
||||
EditorGUIUtility.PingObject(folderObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog(
|
||||
"Prefab Variants",
|
||||
"No prefab variants were created. Please check the console for errors.",
|
||||
"OK"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureFolderExists(string folderPath)
|
||||
{
|
||||
if (!AssetDatabase.IsValidFolder(folderPath))
|
||||
{
|
||||
string[] folderParts = folderPath.Split('/');
|
||||
string currentPath = folderParts[0];
|
||||
|
||||
for (int i = 1; i < folderParts.Length; i++)
|
||||
{
|
||||
string folderName = folderParts[i];
|
||||
string newPath = Path.Combine(currentPath, folderName);
|
||||
|
||||
if (!AssetDatabase.IsValidFolder(newPath))
|
||||
{
|
||||
AssetDatabase.CreateFolder(currentPath, folderName);
|
||||
}
|
||||
|
||||
currentPath = newPath;
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Editor/PrefabVariantGeneratorWindow.cs.meta
Normal file
3
Assets/Editor/PrefabVariantGeneratorWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b49d63944914b3b87e5f6112aee72ca
|
||||
timeCreated: 1758278821
|
||||
42
Assets/Editor/TrenchTileSpawnerEditor.cs
Normal file
42
Assets/Editor/TrenchTileSpawnerEditor.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Minigames.DivingForPictures;
|
||||
|
||||
/// <summary>
|
||||
/// Custom editor for TrenchTileSpawner that adds a runtime button to test the StartSurfacing function
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(TrenchTileSpawner))]
|
||||
public class TrenchTileSpawnerEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// Draw the default inspector
|
||||
DrawDefaultInspector();
|
||||
|
||||
// Get the target TrenchTileSpawner
|
||||
TrenchTileSpawner spawner = (TrenchTileSpawner)target;
|
||||
|
||||
// Add space between default inspector and custom button
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// Separator line
|
||||
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
|
||||
|
||||
// Add a label for the runtime testing section
|
||||
EditorGUILayout.LabelField("Runtime Testing", EditorStyles.boldLabel);
|
||||
|
||||
// Only enable the button during play mode
|
||||
EditorGUI.BeginDisabledGroup(!Application.isPlaying);
|
||||
|
||||
// Add the button to call StartSurfacing
|
||||
if (GUILayout.Button("Start Surfacing", GUILayout.Height(30)))
|
||||
{
|
||||
spawner.StartSurfacing();
|
||||
}
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
// Add explanatory text
|
||||
EditorGUILayout.HelpBox("This button will reverse the direction of the trench movement, making the player surface instead of descend. Only works in Play Mode.", MessageType.Info);
|
||||
}
|
||||
}
|
||||
3
Assets/Editor/TrenchTileSpawnerEditor.cs.meta
Normal file
3
Assets/Editor/TrenchTileSpawnerEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fb1a138e45d4720ba5c95da894b4491
|
||||
timeCreated: 1758531024
|
||||
@@ -43,6 +43,9 @@ namespace Editor.Utilities
|
||||
[Tooltip("Color used for previewing colliders in the scene view")]
|
||||
private Color previewColor = new Color(0.2f, 1f, 0.3f, 0.5f);
|
||||
|
||||
[Tooltip("Layer to assign to GameObjects when colliders are generated")]
|
||||
private int targetLayer = 0;
|
||||
|
||||
private List<Mesh> previewMeshes = new List<Mesh>();
|
||||
|
||||
[MenuItem("Tools/Sprite Collider Generator")]
|
||||
@@ -51,8 +54,29 @@ namespace Editor.Utilities
|
||||
GetWindow<SpriteColliderGenerator>("Sprite Collider Generator");
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Subscribe to scene change events to clear invalid object references
|
||||
UnityEditor.SceneManagement.EditorSceneManager.sceneOpened += OnSceneOpened;
|
||||
UnityEditor.SceneManagement.EditorSceneManager.sceneClosed += OnSceneClosed;
|
||||
|
||||
// Also subscribe to playmode changes as they can invalidate references
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
|
||||
// Subscribe to prefab stage changes (Unity 2018.3+)
|
||||
UnityEditor.SceneManagement.PrefabStage.prefabStageOpened += OnPrefabStageOpened;
|
||||
UnityEditor.SceneManagement.PrefabStage.prefabStageClosing += OnPrefabStageClosing;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// Unsubscribe from events
|
||||
UnityEditor.SceneManagement.EditorSceneManager.sceneOpened -= OnSceneOpened;
|
||||
UnityEditor.SceneManagement.EditorSceneManager.sceneClosed -= OnSceneClosed;
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
UnityEditor.SceneManagement.PrefabStage.prefabStageOpened -= OnPrefabStageOpened;
|
||||
UnityEditor.SceneManagement.PrefabStage.prefabStageClosing -= OnPrefabStageClosing;
|
||||
|
||||
// Clean up any preview meshes when window is closed
|
||||
foreach (var mesh in previewMeshes)
|
||||
{
|
||||
@@ -63,7 +87,53 @@ namespace Editor.Utilities
|
||||
}
|
||||
previewMeshes.Clear();
|
||||
}
|
||||
|
||||
private void OnSceneOpened(UnityEngine.SceneManagement.Scene scene, UnityEditor.SceneManagement.OpenSceneMode mode)
|
||||
{
|
||||
// Clear selected objects when a scene is opened
|
||||
ClearInvalidReferences();
|
||||
}
|
||||
|
||||
private void OnSceneClosed(UnityEngine.SceneManagement.Scene scene)
|
||||
{
|
||||
// Clear selected objects when a scene is closed
|
||||
ClearInvalidReferences();
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
// Clear references when entering/exiting play mode as they become invalid
|
||||
if (state == PlayModeStateChange.ExitingEditMode || state == PlayModeStateChange.ExitingPlayMode)
|
||||
{
|
||||
ClearInvalidReferences();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPrefabStageOpened(UnityEditor.SceneManagement.PrefabStage stage)
|
||||
{
|
||||
// Clear selected objects when entering a prefab stage
|
||||
ClearInvalidReferences();
|
||||
}
|
||||
|
||||
private void OnPrefabStageClosing(UnityEditor.SceneManagement.PrefabStage stage)
|
||||
{
|
||||
// Clear selected objects when exiting a prefab stage
|
||||
ClearInvalidReferences();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears invalid GameObject references from the selected objects list
|
||||
/// </summary>
|
||||
private void ClearInvalidReferences()
|
||||
{
|
||||
if (selectedObjects.Count > 0)
|
||||
{
|
||||
selectedObjects.Clear();
|
||||
ClearPreviews(); // Also clear any preview meshes
|
||||
Repaint(); // Refresh the window UI
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
@@ -146,6 +216,12 @@ namespace Editor.Utilities
|
||||
new GUIContent("Generate Trigger Colliders", "When enabled, creates trigger colliders instead of solid colliders."),
|
||||
generateTriggerColliders);
|
||||
|
||||
// Layer selection
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(new GUIContent("Target Layer:", "Layer to assign to GameObjects when colliders are generated. Leave as 'Nothing' to keep current layer."), GUILayout.Width(180));
|
||||
targetLayer = EditorGUILayout.LayerField(targetLayer);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// Offset option
|
||||
offsetFromCenter = EditorGUILayout.Toggle(
|
||||
new GUIContent("Offset From Center", "When enabled, allows scaling the collider outward or inward from the sprite center."),
|
||||
@@ -445,8 +521,24 @@ namespace Editor.Utilities
|
||||
polygonCollider.SetPath(i, paths[i]);
|
||||
}
|
||||
|
||||
// Set the layer on the GameObject if a specific layer is selected
|
||||
SetTargetLayer(targetObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the target layer on the GameObject if a layer is selected
|
||||
/// </summary>
|
||||
/// <param name="targetObject">The GameObject to set the layer on</param>
|
||||
private void SetTargetLayer(GameObject targetObject)
|
||||
{
|
||||
if (targetLayer != 0)
|
||||
{
|
||||
Undo.RecordObject(targetObject, "Set GameObject Layer");
|
||||
targetObject.layer = targetLayer;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Vector2[]> GetSpritePaths(Sprite sprite, float tolerance)
|
||||
{
|
||||
|
||||
3
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
vendored
Normal file
3
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "OptimizedRope"
|
||||
}
|
||||
7
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
vendored
Normal file
7
Assets/External/OptimizedRopesAndCables/OptimizedRope.asmdef.meta
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7c43f01316c63c43a8b70a1dd6bdfac
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -75,8 +75,20 @@ namespace GogoGaga.OptimizedRopesAndCables
|
||||
|
||||
public bool IsPrefab => gameObject.scene.rootCount == 0;
|
||||
|
||||
private void Start()
|
||||
// Track initialization state
|
||||
private bool isInitialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Public method to explicitly initialize the rope.
|
||||
/// Call this after setting up endpoints if creating ropes at runtime.
|
||||
/// </summary>
|
||||
/// <returns>True if initialization was successful, false otherwise</returns>
|
||||
public bool Initialize()
|
||||
{
|
||||
// Skip if already initialized
|
||||
if (isInitialized)
|
||||
return true;
|
||||
|
||||
InitializeLineRenderer();
|
||||
if (AreEndPointsValid())
|
||||
{
|
||||
@@ -84,7 +96,17 @@ namespace GogoGaga.OptimizedRopesAndCables
|
||||
targetValue = currentValue;
|
||||
currentVelocity = Vector3.zero;
|
||||
SetSplinePoint(); // Ensure initial spline point is set correctly
|
||||
isInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Use the same initialization method to avoid code duplication
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
@@ -208,15 +230,62 @@ namespace GogoGaga.OptimizedRopesAndCables
|
||||
return point;
|
||||
}
|
||||
|
||||
public Vector3 GetPointAt(float t)
|
||||
/// <summary>
|
||||
/// Set the start point of the rope
|
||||
/// </summary>
|
||||
public void SetStartPoint(Transform newStartPoint, bool recalculateRope = false)
|
||||
{
|
||||
if (!AreEndPointsValid())
|
||||
{
|
||||
Debug.LogError("StartPoint or EndPoint is not assigned.", gameObject);
|
||||
return Vector3.zero;
|
||||
}
|
||||
startPoint = newStartPoint;
|
||||
if (recalculateRope)
|
||||
RecalculateRope();
|
||||
}
|
||||
|
||||
return GetRationalBezierPoint(startPoint.position, currentValue, endPoint.position, t, StartPointWeight, midPointWeight, EndPointWeight);
|
||||
/// <summary>
|
||||
/// Set the end point of the rope
|
||||
/// </summary>
|
||||
public void SetEndPoint(Transform newEndPoint, bool recalculateRope = false)
|
||||
{
|
||||
endPoint = newEndPoint;
|
||||
if (recalculateRope)
|
||||
RecalculateRope();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the mid point of the rope
|
||||
/// </summary>
|
||||
public void SetMidPoint(Transform newMidPoint, bool recalculateRope = false)
|
||||
{
|
||||
midPoint = newMidPoint;
|
||||
if (recalculateRope)
|
||||
RecalculateRope();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a point along the rope at the specified position (0-1)
|
||||
/// </summary>
|
||||
public Vector3 GetPointAt(float position)
|
||||
{
|
||||
position = Mathf.Clamp01(position);
|
||||
Vector3 mid = GetMidPoint();
|
||||
return GetRationalBezierPoint(startPoint.position, mid, endPoint.position, position, StartPointWeight, midPointWeight, EndPointWeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force recalculation of the rope
|
||||
/// </summary>
|
||||
public void RecalculateRope()
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
if (AreEndPointsValid())
|
||||
{
|
||||
SetSplinePoint();
|
||||
SimulatePhysics();
|
||||
NotifyPointsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
@@ -262,61 +331,6 @@ namespace GogoGaga.OptimizedRopesAndCables
|
||||
// Gizmos.DrawSphere(midPos, 0.2f);
|
||||
}
|
||||
|
||||
// New API methods for setting start and end points
|
||||
// with instantAssign parameter to recalculate the rope immediately, without
|
||||
// animating the rope to the new position.
|
||||
// When newStartPoint or newEndPoint is null, the rope will be recalculated immediately
|
||||
|
||||
public void SetStartPoint(Transform newStartPoint, bool instantAssign = false)
|
||||
{
|
||||
startPoint = newStartPoint;
|
||||
prevStartPointPosition = startPoint == null ? Vector3.zero : startPoint.position;
|
||||
|
||||
if (instantAssign || newStartPoint == null)
|
||||
{
|
||||
RecalculateRope();
|
||||
}
|
||||
|
||||
NotifyPointsChanged();
|
||||
}
|
||||
public void SetMidPoint(Transform newMidPoint, bool instantAssign = false)
|
||||
{
|
||||
midPoint = newMidPoint;
|
||||
prevMidPointPosition = midPoint == null ? 0.5f : midPointPosition;
|
||||
|
||||
if (instantAssign || newMidPoint == null)
|
||||
{
|
||||
RecalculateRope();
|
||||
}
|
||||
NotifyPointsChanged();
|
||||
}
|
||||
|
||||
public void SetEndPoint(Transform newEndPoint, bool instantAssign = false)
|
||||
{
|
||||
endPoint = newEndPoint;
|
||||
prevEndPointPosition = endPoint == null ? Vector3.zero : endPoint.position;
|
||||
|
||||
if (instantAssign || newEndPoint == null)
|
||||
{
|
||||
RecalculateRope();
|
||||
}
|
||||
|
||||
NotifyPointsChanged();
|
||||
}
|
||||
|
||||
public void RecalculateRope()
|
||||
{
|
||||
if (!AreEndPointsValid())
|
||||
{
|
||||
lineRenderer.positionCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
currentValue = GetMidPoint();
|
||||
targetValue = currentValue;
|
||||
currentVelocity = Vector3.zero;
|
||||
SetSplinePoint();
|
||||
}
|
||||
|
||||
private void NotifyPointsChanged()
|
||||
{
|
||||
|
||||
8
Assets/Playables.meta
Normal file
8
Assets/Playables.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c0088270c13b3a4e8ce04a3f672887d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1248
Assets/Playables/SurfacingTimeline.playable
Normal file
1248
Assets/Playables/SurfacingTimeline.playable
Normal file
File diff suppressed because it is too large
Load Diff
8
Assets/Playables/SurfacingTimeline.playable.meta
Normal file
8
Assets/Playables/SurfacingTimeline.playable.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ecd3cfdb172df5439e4522c15c48f75
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,154 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4743746373562280435
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7889589254526244618}
|
||||
- component: {fileID: 2565520060777160406}
|
||||
- component: {fileID: 586678365535466516}
|
||||
- component: {fileID: 3635110434097976059}
|
||||
m_Layer: 11
|
||||
m_Name: FloatingObstacle
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &7889589254526244618
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4743746373562280435}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -0.62358, y: 4.23222, z: 0}
|
||||
m_LocalScale: {x: 5, y: 5, z: 5}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &2565520060777160406
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4743746373562280435}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 32718083aef44be2a4318681fcdf5b2e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
prefabIndex: 0
|
||||
damage: 1
|
||||
moveSpeed: 2
|
||||
enableMovement: 1
|
||||
spawner: {fileID: 0}
|
||||
--- !u!212 &586678365535466516
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4743746373562280435}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Color: {r: 0.9150943, g: 0, b: 0, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 0.16, y: 0.16}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!61 &3635110434097976059
|
||||
BoxCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4743746373562280435}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0.049999997, y: 0.049999997, z: 0.049999997, w: 0.049999997}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 0.16, y: 0.16}
|
||||
newSize: {x: 0.16, y: 0.16}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Size: {x: 0.16, y: 0.16}
|
||||
m_EdgeRadius: 0
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 315a624eb99600444a51bb1d37c51742
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3481232588610935369
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4085125724917306679}
|
||||
- component: {fileID: 3621591697259925837}
|
||||
m_Layer: 0
|
||||
m_Name: MonsterSpawnPoint
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4085125724917306679
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3481232588610935369}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0.86637, y: -0.03259, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &3621591697259925837
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3481232588610935369}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5ddb6d3629fe4b46b1d7ae972a83539c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
gizmoRadius: 0.5
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da700d1636dcd9348bc52deaf44bdfb7
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
140
Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster.prefab
Normal file
140
Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster.prefab
Normal file
@@ -0,0 +1,140 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &2015720985618639356
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6779310478082390115}
|
||||
- component: {fileID: 8447572436637192077}
|
||||
- component: {fileID: 4998672042618199381}
|
||||
- component: {fileID: 3714732064953161914}
|
||||
m_Layer: 12
|
||||
m_Name: QuarryMonster
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &6779310478082390115
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2015720985618639356}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 2.46, y: -1.79, z: 0}
|
||||
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!212 &8447572436637192077
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2015720985618639356}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_Sprite: {fileID: -9125130289615156199, guid: 1021fffcba2a03d40ae5371555089a22, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 2.46, y: 3.45}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!58 &4998672042618199381
|
||||
CircleCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2015720985618639356}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Radius: 3
|
||||
--- !u!114 &3714732064953161914
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2015720985618639356}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e1b1889b120f4259a9fa9b7e415ea58a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
detectionCollider: {fileID: 4998672042618199381}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7754d064d743d1b419acb859c2db6121
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &7921038058497292108
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 2015720985618639356, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: QuarryMonster_monster_head1_1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.46
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.79
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd5c27c38c427524988b8932e7205d81
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &7839076539202245770
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 2015720985618639356, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: QuarryMonster_monster_head2_0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.46
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.79
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8447572436637192077, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Sprite
|
||||
value:
|
||||
objectReference: {fileID: -7812277834941893986, guid: e9ac6c3e349f9b247a0ea03665da57ce, type: 3}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c45910be7187144b8d2af12ff772353
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &4541086625678702007
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 2015720985618639356, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: QuarryMonster_monster_head3_0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.46
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.79
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8447572436637192077, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Sprite
|
||||
value:
|
||||
objectReference: {fileID: 4139348639081821586, guid: 1043ceca06eb2ac48b22c20d281278b0, type: 3}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0d4b6d8a3b9a2447b883a78c568826c
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1001 &1190377006705176201
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 2015720985618639356, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: QuarryMonster_monster_head4_0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.46
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.79
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8447572436637192077, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
propertyPath: m_Sprite
|
||||
value:
|
||||
objectReference: {fileID: -3471612407960728276, guid: c85ce41979ed896429c62330c546d3ce, type: 3}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d23561cb618e86409a2b7ccbf08e37d
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -10,8 +10,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7111145574660306503}
|
||||
- component: {fileID: 3889795708575321074}
|
||||
- component: {fileID: 7249681423942450184}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 8688779957837852254}
|
||||
m_Layer: 6
|
||||
m_Name: Left_Tile2_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -88,7 +88,7 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &7249681423942450184
|
||||
--- !u!60 &8688779957837852254
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -155,8 +155,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1003080013996268193}
|
||||
- component: {fileID: 4856205316150460481}
|
||||
- component: {fileID: 2843103852598642252}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 8615330168962481848}
|
||||
m_Layer: 6
|
||||
m_Name: Right_Tile1_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -233,7 +233,7 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &2843103852598642252
|
||||
--- !u!60 &8615330168962481848
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -282,8 +282,6 @@ PolygonCollider2D:
|
||||
- - {x: -0.48499998, y: 2.5}
|
||||
- {x: -0.49499997, y: 2.19}
|
||||
- {x: 0.035, y: 1.66}
|
||||
- {x: 0.035, y: 1.42}
|
||||
- {x: -0.24499999, y: 1.15}
|
||||
- {x: -0.285, y: 0.90999997}
|
||||
- {x: -0.13499999, y: 0.45999998}
|
||||
- {x: -1.115, y: -0.03}
|
||||
@@ -328,6 +326,8 @@ Transform:
|
||||
m_Children:
|
||||
- {fileID: 7111145574660306503}
|
||||
- {fileID: 1003080013996268193}
|
||||
- {fileID: 7482385467620467196}
|
||||
- {fileID: 3904535660151308887}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &2488201930835981397
|
||||
@@ -343,3 +343,127 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tileIndex: 0
|
||||
--- !u!1001 &1053554571951708000
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.24
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0.71
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &3904535660151308887 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 1053554571951708000}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &6874619227254404299
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -2.31
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -0.69
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &7482385467620467196 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 6874619227254404299}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
||||
@@ -10,7 +10,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7111145574660306503}
|
||||
- component: {fileID: 3889795708575321074}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 8698932925238153222}
|
||||
m_Layer: 6
|
||||
m_Name: Left_Tile2_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -87,6 +88,63 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &8698932925238153222
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 864595161669782950}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.37, y: 5}
|
||||
newSize: {x: 2.37, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: 0.575, y: -1.5}
|
||||
- {x: 0.185, y: -0.63}
|
||||
- {x: 1.145, y: 0.85999995}
|
||||
- {x: 1.185, y: 1.41}
|
||||
- {x: 0.835, y: 1.8499999}
|
||||
- {x: 0.635, y: 2.5}
|
||||
- {x: -1.185, y: 2.5}
|
||||
- {x: -1.185, y: -2.5}
|
||||
- {x: 0.635, y: -2.5}
|
||||
- {x: 0.625, y: -1.64}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2171518497100337372
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -97,7 +155,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1003080013996268193}
|
||||
- component: {fileID: 4856205316150460481}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 1368284191430742655}
|
||||
m_Layer: 6
|
||||
m_Name: Right_Tile1_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -174,6 +233,67 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &1368284191430742655
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2171518497100337372}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.65, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: -0.48499998, y: 2.5}
|
||||
- {x: -0.49499997, y: 2.19}
|
||||
- {x: 0.035, y: 1.66}
|
||||
- {x: -0.285, y: 0.90999997}
|
||||
- {x: -0.13499999, y: 0.45999998}
|
||||
- {x: -1.115, y: -0.03}
|
||||
- {x: -1.3249999, y: -0.35}
|
||||
- {x: -1.2049999, y: -0.84999996}
|
||||
- {x: -0.36499998, y: -1.0699999}
|
||||
- {x: -0.585, y: -1.27}
|
||||
- {x: -0.625, y: -1.65}
|
||||
- {x: -0.48499998, y: -2.5}
|
||||
- {x: 1.3249999, y: -2.5}
|
||||
- {x: 1.3249999, y: 2.5}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2956826569642009690
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -206,6 +326,8 @@ Transform:
|
||||
m_Children:
|
||||
- {fileID: 7111145574660306503}
|
||||
- {fileID: 1003080013996268193}
|
||||
- {fileID: 5183714158540249435}
|
||||
- {fileID: 4427395838151565125}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 180}
|
||||
--- !u!114 &7876353970701168068
|
||||
@@ -221,3 +343,127 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tileIndex: 0
|
||||
--- !u!1001 &414345722529352306
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -2.26
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -0.72
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &4427395838151565125 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 414345722529352306}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &9169619816711310444
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.4
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 1.48
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &5183714158540249435 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 9169619816711310444}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
||||
@@ -10,7 +10,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7111145574660306503}
|
||||
- component: {fileID: 3889795708575321074}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 6919687589473331973}
|
||||
m_Layer: 6
|
||||
m_Name: Left_Tile2_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -87,6 +88,72 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &6919687589473331973
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 864595161669782950}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.37, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: 0.635, y: -1.78}
|
||||
- {x: 0.585, y: -1.27}
|
||||
- {x: 0.36499998, y: -1.14}
|
||||
- {x: 0.415, y: -1.05}
|
||||
- {x: 1.2149999, y: -0.85999995}
|
||||
- {x: 1.3249999, y: -0.7}
|
||||
- {x: 1.3249999, y: -0.35}
|
||||
- {x: 1.145, y: -0.049999997}
|
||||
- {x: 0.13499999, y: 0.45999998}
|
||||
- {x: 0.275, y: 0.87}
|
||||
- {x: 0.265, y: 1.0699999}
|
||||
- {x: -0.044999998, y: 1.41}
|
||||
- {x: -0.035, y: 1.66}
|
||||
- {x: 0.48499998, y: 2.2}
|
||||
- {x: 0.49499997, y: 2.48}
|
||||
- {x: -1.3249999, y: 2.5}
|
||||
- {x: -1.3249999, y: -2.5}
|
||||
- {x: 0.505, y: -2.5}
|
||||
- {x: 0.555, y: -2.12}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2171518497100337372
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -97,7 +164,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1003080013996268193}
|
||||
- component: {fileID: 4856205316150460481}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 1911291775322313535}
|
||||
m_Layer: 6
|
||||
m_Name: Right_Tile1_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -174,6 +242,65 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &1911291775322313535
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2171518497100337372}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.37, y: 5}
|
||||
newSize: {x: 2.65, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: -0.635, y: 2.5}
|
||||
- {x: -0.835, y: 1.8499999}
|
||||
- {x: -1.185, y: 1.42}
|
||||
- {x: -1.185, y: 1.06}
|
||||
- {x: -1.055, y: 0.69}
|
||||
- {x: -0.185, y: -0.65999997}
|
||||
- {x: -0.175, y: -0.78999996}
|
||||
- {x: -0.585, y: -1.49}
|
||||
- {x: -0.675, y: -2.08}
|
||||
- {x: -0.635, y: -2.5}
|
||||
- {x: 1.185, y: -2.5}
|
||||
- {x: 1.185, y: 2.5}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2956826569642009690
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -206,6 +333,8 @@ Transform:
|
||||
m_Children:
|
||||
- {fileID: 7111145574660306503}
|
||||
- {fileID: 1003080013996268193}
|
||||
- {fileID: 779930052227149768}
|
||||
- {fileID: 6717719249848646349}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &2017387953723006367
|
||||
@@ -221,3 +350,127 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tileIndex: 0
|
||||
--- !u!1001 &3630911149016824575
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.27
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -0.7
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &779930052227149768 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 3630911149016824575}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &7317058718762905594
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -1.98
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &6717719249848646349 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 7317058718762905594}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
||||
@@ -10,7 +10,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7111145574660306503}
|
||||
- component: {fileID: 3889795708575321074}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 3320970211105392876}
|
||||
m_Layer: 6
|
||||
m_Name: Left_Tile2_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -87,6 +88,72 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &3320970211105392876
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 864595161669782950}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.37, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: 0.635, y: -1.78}
|
||||
- {x: 0.585, y: -1.27}
|
||||
- {x: 0.36499998, y: -1.14}
|
||||
- {x: 0.415, y: -1.05}
|
||||
- {x: 1.2149999, y: -0.85999995}
|
||||
- {x: 1.3249999, y: -0.7}
|
||||
- {x: 1.3249999, y: -0.35}
|
||||
- {x: 1.145, y: -0.049999997}
|
||||
- {x: 0.13499999, y: 0.45999998}
|
||||
- {x: 0.275, y: 0.87}
|
||||
- {x: 0.265, y: 1.0699999}
|
||||
- {x: -0.044999998, y: 1.41}
|
||||
- {x: -0.035, y: 1.66}
|
||||
- {x: 0.48499998, y: 2.2}
|
||||
- {x: 0.49499997, y: 2.48}
|
||||
- {x: -1.3249999, y: 2.5}
|
||||
- {x: -1.3249999, y: -2.5}
|
||||
- {x: 0.505, y: -2.5}
|
||||
- {x: 0.555, y: -2.12}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2171518497100337372
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -97,7 +164,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1003080013996268193}
|
||||
- component: {fileID: 4856205316150460481}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 3931598674086383704}
|
||||
m_Layer: 6
|
||||
m_Name: Right_Tile1_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -174,6 +242,65 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &3931598674086383704
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2171518497100337372}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.37, y: 5}
|
||||
newSize: {x: 2.65, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: -0.635, y: 2.5}
|
||||
- {x: -0.835, y: 1.8499999}
|
||||
- {x: -1.185, y: 1.42}
|
||||
- {x: -1.185, y: 1.06}
|
||||
- {x: -1.055, y: 0.69}
|
||||
- {x: -0.185, y: -0.65999997}
|
||||
- {x: -0.175, y: -0.78999996}
|
||||
- {x: -0.585, y: -1.49}
|
||||
- {x: -0.675, y: -2.08}
|
||||
- {x: -0.635, y: -2.5}
|
||||
- {x: 1.185, y: -2.5}
|
||||
- {x: 1.185, y: 2.5}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2956826569642009690
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -206,6 +333,8 @@ Transform:
|
||||
m_Children:
|
||||
- {fileID: 7111145574660306503}
|
||||
- {fileID: 1003080013996268193}
|
||||
- {fileID: 3622650182130189122}
|
||||
- {fileID: 6128198891967149402}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 180}
|
||||
--- !u!114 &451715946189956124
|
||||
@@ -221,3 +350,127 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tileIndex: 0
|
||||
--- !u!1001 &790228998383621749
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -2.22
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0.8
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &3622650182130189122 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 790228998383621749}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &7906900786878439533
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 1.77
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 2.28
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &6128198891967149402 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 7906900786878439533}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
||||
@@ -10,7 +10,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7111145574660306503}
|
||||
- component: {fileID: 3889795708575321074}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 1709932086434338450}
|
||||
m_Layer: 6
|
||||
m_Name: Left_Tile2_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -87,6 +88,72 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &1709932086434338450
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 864595161669782950}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.37, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: 0.635, y: -1.78}
|
||||
- {x: 0.585, y: -1.27}
|
||||
- {x: 0.36499998, y: -1.14}
|
||||
- {x: 0.415, y: -1.05}
|
||||
- {x: 1.2149999, y: -0.85999995}
|
||||
- {x: 1.3249999, y: -0.7}
|
||||
- {x: 1.3249999, y: -0.35}
|
||||
- {x: 1.145, y: -0.049999997}
|
||||
- {x: 0.13499999, y: 0.45999998}
|
||||
- {x: 0.275, y: 0.87}
|
||||
- {x: 0.265, y: 1.0699999}
|
||||
- {x: -0.044999998, y: 1.41}
|
||||
- {x: -0.035, y: 1.66}
|
||||
- {x: 0.48499998, y: 2.2}
|
||||
- {x: 0.49499997, y: 2.48}
|
||||
- {x: -1.3249999, y: 2.5}
|
||||
- {x: -1.3249999, y: -2.5}
|
||||
- {x: 0.505, y: -2.5}
|
||||
- {x: 0.555, y: -2.12}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2171518497100337372
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -97,7 +164,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1003080013996268193}
|
||||
- component: {fileID: 4856205316150460481}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 9036823987933958098}
|
||||
m_Layer: 6
|
||||
m_Name: Right_Tile1_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -174,6 +242,70 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &9036823987933958098
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2171518497100337372}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.65, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: -0.48499998, y: 2.5}
|
||||
- {x: -0.49499997, y: 2.19}
|
||||
- {x: 0.035, y: 1.66}
|
||||
- {x: 0.035, y: 1.42}
|
||||
- {x: -0.24499999, y: 1.15}
|
||||
- {x: -0.285, y: 0.90999997}
|
||||
- {x: -0.13499999, y: 0.45999998}
|
||||
- {x: -1.115, y: -0.03}
|
||||
- {x: -1.3249999, y: -0.35}
|
||||
- {x: -1.3249999, y: -0.71}
|
||||
- {x: -1.2049999, y: -0.84999996}
|
||||
- {x: -0.36499998, y: -1.0699999}
|
||||
- {x: -0.585, y: -1.27}
|
||||
- {x: -0.625, y: -1.65}
|
||||
- {x: -0.48499998, y: -2.5}
|
||||
- {x: 1.3249999, y: -2.5}
|
||||
- {x: 1.3249999, y: 2.5}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2956826569642009690
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -206,6 +338,8 @@ Transform:
|
||||
m_Children:
|
||||
- {fileID: 7111145574660306503}
|
||||
- {fileID: 1003080013996268193}
|
||||
- {fileID: 1007295630034795055}
|
||||
- {fileID: 1590951442778015581}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &8822397971507360111
|
||||
@@ -221,3 +355,127 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tileIndex: 0
|
||||
--- !u!1001 &3361226680573907562
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -1.95
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.48
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &1590951442778015581 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 3361226680573907562}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &3840420642436902680
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.27
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -1.58
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &1007295630034795055 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 3840420642436902680}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
||||
@@ -10,7 +10,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 7111145574660306503}
|
||||
- component: {fileID: 3889795708575321074}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 6967660003360049346}
|
||||
m_Layer: 6
|
||||
m_Name: Left_Tile2_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -87,6 +88,72 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &6967660003360049346
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 864595161669782950}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.37, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: 0.635, y: -1.78}
|
||||
- {x: 0.585, y: -1.27}
|
||||
- {x: 0.36499998, y: -1.14}
|
||||
- {x: 0.415, y: -1.05}
|
||||
- {x: 1.2149999, y: -0.85999995}
|
||||
- {x: 1.3249999, y: -0.7}
|
||||
- {x: 1.3249999, y: -0.35}
|
||||
- {x: 1.145, y: -0.049999997}
|
||||
- {x: 0.13499999, y: 0.45999998}
|
||||
- {x: 0.275, y: 0.87}
|
||||
- {x: 0.265, y: 1.0699999}
|
||||
- {x: -0.044999998, y: 1.41}
|
||||
- {x: -0.035, y: 1.66}
|
||||
- {x: 0.48499998, y: 2.2}
|
||||
- {x: 0.49499997, y: 2.48}
|
||||
- {x: -1.3249999, y: 2.5}
|
||||
- {x: -1.3249999, y: -2.5}
|
||||
- {x: 0.505, y: -2.5}
|
||||
- {x: 0.555, y: -2.12}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2171518497100337372
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -97,7 +164,8 @@ GameObject:
|
||||
m_Component:
|
||||
- component: {fileID: 1003080013996268193}
|
||||
- component: {fileID: 4856205316150460481}
|
||||
m_Layer: 0
|
||||
- component: {fileID: 5503039050943823342}
|
||||
m_Layer: 6
|
||||
m_Name: Right_Tile1_0
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
@@ -174,6 +242,70 @@ SpriteRenderer:
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!60 &5503039050943823342
|
||||
PolygonCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2171518497100337372}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 2.65, y: 5}
|
||||
newSize: {x: 2.65, y: 5}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Points:
|
||||
m_Paths:
|
||||
- - {x: -0.48499998, y: 2.5}
|
||||
- {x: -0.49499997, y: 2.19}
|
||||
- {x: 0.035, y: 1.66}
|
||||
- {x: 0.035, y: 1.42}
|
||||
- {x: -0.24499999, y: 1.15}
|
||||
- {x: -0.285, y: 0.90999997}
|
||||
- {x: -0.13499999, y: 0.45999998}
|
||||
- {x: -1.115, y: -0.03}
|
||||
- {x: -1.3249999, y: -0.35}
|
||||
- {x: -1.3249999, y: -0.71}
|
||||
- {x: -1.2049999, y: -0.84999996}
|
||||
- {x: -0.36499998, y: -1.0699999}
|
||||
- {x: -0.585, y: -1.27}
|
||||
- {x: -0.625, y: -1.65}
|
||||
- {x: -0.48499998, y: -2.5}
|
||||
- {x: 1.3249999, y: -2.5}
|
||||
- {x: 1.3249999, y: 2.5}
|
||||
m_UseDelaunayMesh: 0
|
||||
--- !u!1 &2956826569642009690
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -206,6 +338,8 @@ Transform:
|
||||
m_Children:
|
||||
- {fileID: 7111145574660306503}
|
||||
- {fileID: 1003080013996268193}
|
||||
- {fileID: 6011507792702974644}
|
||||
- {fileID: 8778559433790709003}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 180}
|
||||
--- !u!114 &2006557459409230470
|
||||
@@ -221,3 +355,127 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tileIndex: 0
|
||||
--- !u!1001 &4711606854742853692
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint (1)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -2.23
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0.77
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &8778559433790709003 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 4711606854742853692}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &7772195149518225283
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 4925660644986369589}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3481232588610935369, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: MonsterSpawnPoint
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 2.33
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0.77
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
--- !u!4 &6011507792702974644 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 4085125724917306679, guid: da700d1636dcd9348bc52deaf44bdfb7, type: 3}
|
||||
m_PrefabInstance: {fileID: 7772195149518225283}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,8 @@
|
||||
"AstarPathfindingProject",
|
||||
"Unity.ResourceManager",
|
||||
"Unity.InputSystem",
|
||||
"Unity.TextMeshPro"
|
||||
"Unity.TextMeshPro",
|
||||
"OptimizedRope"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using Pooling;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single bubble, handling its movement, wobble effect, scaling, and sprite assignment.
|
||||
/// Uses coroutines for better performance instead of Update() calls.
|
||||
/// </summary>
|
||||
public class Bubble : MonoBehaviour, IPoolableWithReference<BubblePool>
|
||||
{
|
||||
public float speed = 1f;
|
||||
public float wobbleSpeed = 1f;
|
||||
private SpriteRenderer spriteRenderer;
|
||||
private SpriteRenderer bubbleSpriteRenderer; // Renamed from bottleSpriteRenderer
|
||||
private SpriteRenderer bubbleSpriteRenderer;
|
||||
private float timeOffset;
|
||||
private float minScale = 0.2f;
|
||||
private float maxScale = 1.2f;
|
||||
private float baseScale = 1f; // Added to store the initial scale
|
||||
private float baseScale = 1f;
|
||||
|
||||
private Camera mainCamera; // Cache camera reference
|
||||
private BubblePool parentPool; // Reference to the pool this bubble came from
|
||||
private Camera mainCamera;
|
||||
private BubblePool parentPool;
|
||||
|
||||
// Coroutine references
|
||||
private Coroutine _movementCoroutine;
|
||||
private Coroutine _wobbleCoroutine;
|
||||
private Coroutine _offScreenCheckCoroutine;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Cache references and randomize time offset for wobble
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
timeOffset = Random.value * 100f;
|
||||
|
||||
// Find the child named "BubbleSprite" and get its SpriteRenderer
|
||||
Transform bubbleSpriteTransform = transform.Find("BubbleSprite");
|
||||
if (bubbleSpriteTransform != null)
|
||||
@@ -36,20 +44,101 @@ namespace Minigames.DivingForPictures
|
||||
mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
void Update()
|
||||
private void OnEnable()
|
||||
{
|
||||
// Move bubble upward
|
||||
transform.position += Vector3.up * (speed * Time.deltaTime);
|
||||
|
||||
// Wobble effect (smooth oscillation between min and max scale)
|
||||
float t = (Mathf.Sin((Time.time + timeOffset) * wobbleSpeed) + 1f) * 0.5f; // t in [0,1]
|
||||
float wobbleFactor = Mathf.Lerp(minScale, maxScale, t);
|
||||
transform.localScale = Vector3.one * (baseScale * wobbleFactor);
|
||||
|
||||
// Destroy when off screen - using cached camera reference
|
||||
if (mainCamera != null && transform.position.y > mainCamera.orthographicSize + 2f)
|
||||
StartBubbleBehavior();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopBubbleBehavior();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts all bubble behavior coroutines
|
||||
/// </summary>
|
||||
private void StartBubbleBehavior()
|
||||
{
|
||||
_movementCoroutine = StartCoroutine(MovementCoroutine());
|
||||
_wobbleCoroutine = StartCoroutine(WobbleCoroutine());
|
||||
_offScreenCheckCoroutine = StartCoroutine(OffScreenCheckCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops all bubble behavior coroutines
|
||||
/// </summary>
|
||||
private void StopBubbleBehavior()
|
||||
{
|
||||
if (_movementCoroutine != null)
|
||||
{
|
||||
OnBubbleDestroy();
|
||||
StopCoroutine(_movementCoroutine);
|
||||
_movementCoroutine = null;
|
||||
}
|
||||
|
||||
if (_wobbleCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_wobbleCoroutine);
|
||||
_wobbleCoroutine = null;
|
||||
}
|
||||
|
||||
if (_offScreenCheckCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_offScreenCheckCoroutine);
|
||||
_offScreenCheckCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that handles bubble upward movement
|
||||
/// </summary>
|
||||
private IEnumerator MovementCoroutine()
|
||||
{
|
||||
while (enabled && gameObject.activeInHierarchy)
|
||||
{
|
||||
// Move bubble upward
|
||||
transform.position += Vector3.up * (speed * Time.deltaTime);
|
||||
|
||||
// Wait for next frame
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that handles the wobble scaling effect
|
||||
/// </summary>
|
||||
private IEnumerator WobbleCoroutine()
|
||||
{
|
||||
while (enabled && gameObject.activeInHierarchy)
|
||||
{
|
||||
// Wobble effect (smooth oscillation between min and max scale)
|
||||
float t = (Mathf.Sin((Time.time + timeOffset) * wobbleSpeed) + 1f) * 0.5f; // t in [0,1]
|
||||
float wobbleFactor = Mathf.Lerp(minScale, maxScale, t);
|
||||
transform.localScale = Vector3.one * (baseScale * wobbleFactor);
|
||||
|
||||
// Wait for next frame
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that checks if bubble has moved off-screen
|
||||
/// Runs at a lower frequency for better performance
|
||||
/// </summary>
|
||||
private IEnumerator OffScreenCheckCoroutine()
|
||||
{
|
||||
const float checkInterval = 0.1f; // Check every 100ms instead of every frame
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy)
|
||||
{
|
||||
// Check if bubble is off screen
|
||||
if (mainCamera != null && transform.position.y > mainCamera.orthographicSize + 2f)
|
||||
{
|
||||
OnBubbleDestroy();
|
||||
yield break; // Exit coroutine since bubble is being destroyed
|
||||
}
|
||||
|
||||
// Wait for the check interval
|
||||
yield return new WaitForSeconds(checkInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +232,24 @@ namespace Minigames.DivingForPictures
|
||||
minScale = min;
|
||||
maxScale = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the movement speed at runtime
|
||||
/// </summary>
|
||||
/// <param name="newSpeed">New movement speed</param>
|
||||
public void SetSpeed(float newSpeed)
|
||||
{
|
||||
speed = newSpeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the wobble speed at runtime
|
||||
/// </summary>
|
||||
/// <param name="newWobbleSpeed">New wobble speed</param>
|
||||
public void SetWobbleSpeed(float newWobbleSpeed)
|
||||
{
|
||||
wobbleSpeed = newWobbleSpeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the bubble state for reuse from object pool
|
||||
|
||||
@@ -26,10 +26,15 @@ namespace Minigames.DivingForPictures
|
||||
public int initialPoolSize = 10;
|
||||
public int maxPoolSize = 30;
|
||||
|
||||
[Header("Surfacing Settings")]
|
||||
[Tooltip("Factor to multiply bubble speed by when surfacing (0.5 = half speed)")]
|
||||
[SerializeField] private float surfacingSpeedFactor = 0.5f;
|
||||
|
||||
private float _timer;
|
||||
private float _nextSpawnInterval;
|
||||
private BubblePool _bubblePool;
|
||||
private Camera _mainCamera; // Cache camera reference
|
||||
private bool _isSurfacing = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
@@ -98,7 +103,18 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
|
||||
// Randomize bubble properties
|
||||
bubble.speed = Random.Range(speedRange.x, speedRange.y);
|
||||
float baseSpeed = Random.Range(speedRange.x, speedRange.y);
|
||||
|
||||
// Apply surfacing speed reduction if needed
|
||||
if (_isSurfacing)
|
||||
{
|
||||
bubble.speed = baseSpeed * surfacingSpeedFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
bubble.speed = baseSpeed;
|
||||
}
|
||||
|
||||
bubble.wobbleSpeed = Random.Range(wobbleSpeedRange.x, wobbleSpeedRange.y);
|
||||
|
||||
// Set base scale (initial size) for the bubble
|
||||
@@ -119,6 +135,25 @@ namespace Minigames.DivingForPictures
|
||||
bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start surfacing mode - slow down all bubbles
|
||||
/// </summary>
|
||||
public void StartSurfacing()
|
||||
{
|
||||
if (_isSurfacing) return; // Already surfacing
|
||||
|
||||
_isSurfacing = true;
|
||||
|
||||
// Slow down all existing bubbles
|
||||
Bubble[] activeBubbles = FindObjectsOfType<Bubble>();
|
||||
foreach (Bubble bubble in activeBubbles)
|
||||
{
|
||||
bubble.speed *= surfacingSpeedFactor;
|
||||
}
|
||||
|
||||
Debug.Log($"[BubbleSpawner] Started surfacing mode. Bubbles slowed to {surfacingSpeedFactor * 100}% speed.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the current pool statistics for debugging
|
||||
/// </summary>
|
||||
|
||||
619
Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs
Normal file
619
Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs
Normal file
@@ -0,0 +1,619 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
public class DivingGameManager : MonoBehaviour
|
||||
{
|
||||
[Header("Monster Prefabs")]
|
||||
[Tooltip("Array of monster prefabs to spawn randomly")]
|
||||
[SerializeField] private GameObject[] monsterPrefabs;
|
||||
|
||||
[Header("Spawn Probability")]
|
||||
[Tooltip("Base chance (0-1) of spawning a monster on each tile")]
|
||||
[SerializeField] private float baseSpawnProbability = 0.2f;
|
||||
[Tooltip("Maximum chance (0-1) of spawning a monster")]
|
||||
[SerializeField] private float maxSpawnProbability = 0.5f;
|
||||
[Tooltip("How fast the probability increases per second")]
|
||||
[SerializeField] private float probabilityIncreaseRate = 0.01f;
|
||||
|
||||
[Header("Spawn Timing")]
|
||||
[Tooltip("Force a spawn after this many seconds without spawns")]
|
||||
[SerializeField] private float guaranteedSpawnTime = 30f;
|
||||
[Tooltip("Minimum time between monster spawns")]
|
||||
[SerializeField] private float spawnCooldown = 5f;
|
||||
|
||||
[Header("Scoring")]
|
||||
[Tooltip("Base points for taking a picture")]
|
||||
[SerializeField] private int basePoints = 100;
|
||||
[Tooltip("Additional points per depth unit")]
|
||||
[SerializeField] private int depthMultiplier = 10;
|
||||
|
||||
[Header("Rope Damage System")]
|
||||
[Tooltip("Ropes that will break one by one as player takes damage")]
|
||||
[SerializeField] private RopeBreaker[] playerRopes;
|
||||
|
||||
[Header("Surfacing Settings")]
|
||||
[Tooltip("Duration in seconds for speed transition when surfacing")]
|
||||
[SerializeField] private float speedTransitionDuration = 2.0f;
|
||||
[Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")]
|
||||
[SerializeField] private float surfacingSpeedFactor = 3.0f;
|
||||
[Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")]
|
||||
[SerializeField] private float surfacingSpawnDelay = 5.0f;
|
||||
[Tooltip("Reference to the PlayableDirector that will play the surfacing timeline")]
|
||||
[SerializeField] private PlayableDirector surfacingTimeline;
|
||||
|
||||
// Private state variables
|
||||
private int playerScore = 0;
|
||||
private float currentSpawnProbability;
|
||||
private float lastSpawnTime = -100f;
|
||||
private float timeSinceLastSpawn = 0f;
|
||||
private List<Monster> activeMonsters = new List<Monster>();
|
||||
|
||||
// Velocity management
|
||||
// Velocity state tracking
|
||||
private float _currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed
|
||||
private Coroutine _velocityTransitionCoroutine;
|
||||
private Coroutine _surfacingSequenceCoroutine;
|
||||
|
||||
// Public properties
|
||||
public int PlayerScore => playerScore;
|
||||
public float CurrentVelocityFactor => _currentVelocityFactor;
|
||||
|
||||
// Events
|
||||
public event Action<int> OnScoreChanged;
|
||||
public event Action<Monster> OnMonsterSpawned;
|
||||
public event Action<Monster, int> OnPictureTaken;
|
||||
public event Action<float> OnSpawnProbabilityChanged;
|
||||
public event Action OnGameOver;
|
||||
public event Action<int> OnRopeBroken; // Passes remaining ropes count
|
||||
public event Action<float> OnVelocityFactorChanged;
|
||||
|
||||
// Private state variables for rope system
|
||||
private int currentRopeIndex = 0;
|
||||
private bool isGameOver = false;
|
||||
private bool _isSurfacing = false;
|
||||
|
||||
// Used to track if we're currently surfacing
|
||||
public bool IsSurfacing => _isSurfacing;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
currentSpawnProbability = baseSpawnProbability;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Subscribe to tile spawned event
|
||||
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
||||
if (tileSpawner != null)
|
||||
{
|
||||
tileSpawner.onTileSpawned.AddListener(OnTileSpawned);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("No TrenchTileSpawner found in scene. Monster spawning won't work.");
|
||||
}
|
||||
|
||||
// Subscribe to player damage events
|
||||
PlayerCollisionBehavior.OnDamageTaken += OnPlayerDamageTaken;
|
||||
|
||||
// Validate rope references
|
||||
ValidateRopeReferences();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// Unsubscribe from events when the manager is destroyed
|
||||
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
timeSinceLastSpawn += Time.deltaTime;
|
||||
|
||||
// Gradually increase spawn probability over time
|
||||
float previousProbability = currentSpawnProbability;
|
||||
if (currentSpawnProbability < maxSpawnProbability)
|
||||
{
|
||||
currentSpawnProbability += probabilityIncreaseRate * Time.deltaTime;
|
||||
currentSpawnProbability = Mathf.Min(currentSpawnProbability, maxSpawnProbability);
|
||||
|
||||
// Only fire event if probability changed significantly
|
||||
if (Mathf.Abs(currentSpawnProbability - previousProbability) > 0.01f)
|
||||
{
|
||||
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTileSpawned(GameObject tile)
|
||||
{
|
||||
// Check for spawn points in the new tile
|
||||
MonsterSpawnPoint[] spawnPoints = tile.GetComponentsInChildren<MonsterSpawnPoint>();
|
||||
|
||||
if (spawnPoints.Length == 0) return;
|
||||
|
||||
// If we're surfacing, don't spawn new monsters
|
||||
if (_isSurfacing) return;
|
||||
|
||||
bool forceSpawn = timeSinceLastSpawn >= guaranteedSpawnTime;
|
||||
bool onCooldown = timeSinceLastSpawn < spawnCooldown;
|
||||
|
||||
// Don't spawn if on cooldown, unless forced
|
||||
if (onCooldown && !forceSpawn) return;
|
||||
|
||||
// Check probability or forced spawn
|
||||
if (forceSpawn || UnityEngine.Random.value <= currentSpawnProbability)
|
||||
{
|
||||
// Pick a random spawn point from this tile
|
||||
MonsterSpawnPoint spawnPoint = spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)];
|
||||
|
||||
// Spawn the monster at the spawn point and parent it
|
||||
SpawnMonster(spawnPoint.transform);
|
||||
|
||||
// Reset timer and adjust probability
|
||||
lastSpawnTime = Time.time;
|
||||
timeSinceLastSpawn = 0f;
|
||||
currentSpawnProbability = baseSpawnProbability;
|
||||
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnMonster(Transform spawnPoint)
|
||||
{
|
||||
if (monsterPrefabs.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("No monster prefabs assigned to DivingGameManager.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Select random monster prefab
|
||||
GameObject prefab = monsterPrefabs[UnityEngine.Random.Range(0, monsterPrefabs.Length)];
|
||||
|
||||
// Instantiate monster at spawn point position
|
||||
GameObject monsterObj = Instantiate(prefab, spawnPoint.position, Quaternion.identity);
|
||||
Monster monster = monsterObj.GetComponent<Monster>();
|
||||
|
||||
if (monster != null)
|
||||
{
|
||||
// Parent the monster to the spawn point so it moves with the tile
|
||||
monsterObj.transform.SetParent(spawnPoint);
|
||||
|
||||
// Subscribe to monster events
|
||||
monster.OnPictureTaken += OnMonsterPictureTaken;
|
||||
monster.OnMonsterDespawned += OnMonsterDespawned;
|
||||
|
||||
// Add to active monsters list
|
||||
activeMonsters.Add(monster);
|
||||
|
||||
// Fire event
|
||||
OnMonsterSpawned?.Invoke(monster);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Monster prefab {prefab.name} does not have a Monster component!");
|
||||
Destroy(monsterObj);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMonsterPictureTaken(Monster monster)
|
||||
{
|
||||
// Calculate points based on depth
|
||||
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * depthMultiplier);
|
||||
int pointsAwarded = basePoints + depthBonus;
|
||||
|
||||
// Add score
|
||||
playerScore += pointsAwarded;
|
||||
|
||||
// Fire events
|
||||
OnScoreChanged?.Invoke(playerScore);
|
||||
OnPictureTaken?.Invoke(monster, pointsAwarded);
|
||||
}
|
||||
|
||||
private void OnMonsterDespawned(Monster monster)
|
||||
{
|
||||
// Remove from active list
|
||||
activeMonsters.Remove(monster);
|
||||
|
||||
// Unsubscribe from events
|
||||
monster.OnPictureTaken -= OnMonsterPictureTaken;
|
||||
monster.OnMonsterDespawned -= OnMonsterDespawned;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the player takes damage from any collision
|
||||
/// </summary>
|
||||
private void OnPlayerDamageTaken()
|
||||
{
|
||||
if (isGameOver) return;
|
||||
|
||||
// Break the next rope in sequence
|
||||
BreakNextRope();
|
||||
|
||||
// Check if all ropes are broken
|
||||
if (currentRopeIndex >= playerRopes.Length)
|
||||
{
|
||||
TriggerGameOver();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Notify listeners about rope break and remaining ropes
|
||||
int remainingRopes = playerRopes.Length - currentRopeIndex;
|
||||
OnRopeBroken?.Invoke(remainingRopes);
|
||||
|
||||
Debug.Log($"[DivingGameManager] Rope broken! {remainingRopes} ropes remaining.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Breaks the next available rope in the sequence
|
||||
/// </summary>
|
||||
private void BreakNextRope()
|
||||
{
|
||||
if (currentRopeIndex < playerRopes.Length)
|
||||
{
|
||||
RopeBreaker ropeToBreak = playerRopes[currentRopeIndex];
|
||||
|
||||
if (ropeToBreak != null)
|
||||
{
|
||||
// Let the RopeBreaker component handle the breaking, effects, and sounds
|
||||
ropeToBreak.BreakRope();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[DivingGameManager] Rope at index {currentRopeIndex} is null!");
|
||||
}
|
||||
|
||||
// Move to the next rope regardless if current was null
|
||||
currentRopeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually break a rope (for testing or external events)
|
||||
/// </summary>
|
||||
public void ForceBreakRope()
|
||||
{
|
||||
if (!isGameOver)
|
||||
{
|
||||
OnPlayerDamageTaken();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers game over state when all ropes are broken
|
||||
/// </summary>
|
||||
private void TriggerGameOver()
|
||||
{
|
||||
if (isGameOver) return;
|
||||
|
||||
isGameOver = true;
|
||||
Debug.Log("[DivingGameManager] Game Over! All ropes broken. Starting surfacing sequence...");
|
||||
|
||||
// Fire game over event
|
||||
OnGameOver?.Invoke();
|
||||
|
||||
// Start surfacing instead of directly ending the game
|
||||
StartSurfacing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates rope references and logs warnings if any are missing
|
||||
/// </summary>
|
||||
private void ValidateRopeReferences()
|
||||
{
|
||||
if (playerRopes == null || playerRopes.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("[DivingGameManager] No ropes assigned to break! Damage system won't work properly.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < playerRopes.Length; i++)
|
||||
{
|
||||
if (playerRopes[i] == null)
|
||||
{
|
||||
Debug.LogWarning($"[DivingGameManager] Rope at index {i} is null!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the rope system for a new game
|
||||
/// </summary>
|
||||
public void ResetRopeSystem()
|
||||
{
|
||||
// Reset rope state
|
||||
currentRopeIndex = 0;
|
||||
isGameOver = false;
|
||||
|
||||
// Restore all broken ropes
|
||||
if (playerRopes != null)
|
||||
{
|
||||
foreach (var rope in playerRopes)
|
||||
{
|
||||
if (rope != null)
|
||||
{
|
||||
rope.RestoreRope();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("[DivingGameManager] Rope system reset.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the surfacing mode - reverses trench direction and adjusts all spawned entities
|
||||
/// </summary>
|
||||
public void StartSurfacing()
|
||||
{
|
||||
if (_isSurfacing) return; // Already surfacing
|
||||
|
||||
_isSurfacing = true;
|
||||
|
||||
// 1. Initiate smooth velocity transition to surfacing speed
|
||||
float targetVelocityFactor = -1.0f * surfacingSpeedFactor;
|
||||
SetVelocityFactor(targetVelocityFactor);
|
||||
|
||||
// 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic)
|
||||
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
||||
if (tileSpawner != null)
|
||||
{
|
||||
// Subscribe to velocity changes if not already subscribed
|
||||
OnVelocityFactorChanged -= tileSpawner.OnVelocityFactorChanged;
|
||||
OnVelocityFactorChanged += tileSpawner.OnVelocityFactorChanged;
|
||||
|
||||
// Subscribe to the last tile event
|
||||
tileSpawner.onLastTileLeft.RemoveListener(OnLastTileLeft);
|
||||
tileSpawner.onLastTileLeft.AddListener(OnLastTileLeft);
|
||||
|
||||
// Tell spawner to reverse spawn/despawn logic
|
||||
tileSpawner.StartSurfacing();
|
||||
|
||||
// Immediately send current velocity factor
|
||||
tileSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
|
||||
}
|
||||
|
||||
// Handle the Rock object - disable components and animate it falling offscreen
|
||||
GameObject rockObject = GameObject.FindGameObjectWithTag("Rock");
|
||||
if (rockObject != null)
|
||||
{
|
||||
// Disable all components except Transform on the rock object (not its children)
|
||||
foreach (Component component in rockObject.GetComponents<Component>())
|
||||
{
|
||||
if (!(component is Transform))
|
||||
{
|
||||
if (component is Behaviour behaviour)
|
||||
{
|
||||
behaviour.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start coroutine to animate the rock falling offscreen
|
||||
StartCoroutine(MoveRockOffscreen(rockObject.transform));
|
||||
|
||||
Debug.Log("[DivingGameManager] Disabled rock components and animating it offscreen");
|
||||
}
|
||||
|
||||
// Handle the Player object - disable components and reset X position
|
||||
GameObject playerObject = GameObject.FindGameObjectWithTag("Player");
|
||||
if (playerObject != null)
|
||||
{
|
||||
// Disable all components except Transform and Animator on the player object (not its children)
|
||||
foreach (Component component in playerObject.GetComponents<Component>())
|
||||
{
|
||||
if (!(component is Transform) && !(component is Animator))
|
||||
{
|
||||
if (component is Behaviour behaviour)
|
||||
{
|
||||
behaviour.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start coroutine to reset X position to 0 over 1 second
|
||||
StartCoroutine(ResetPlayerPosition(playerObject.transform));
|
||||
|
||||
Debug.Log("[DivingGameManager] Disabled player components (keeping Animator) and resetting position");
|
||||
}
|
||||
|
||||
// 3. Find bubble spawner and slow down existing bubbles (no velocity management needed)
|
||||
BubbleSpawner bubbleSpawner = FindFirstObjectByType<BubbleSpawner>();
|
||||
if (bubbleSpawner != null)
|
||||
{
|
||||
bubbleSpawner.StartSurfacing();
|
||||
}
|
||||
|
||||
// 4. Find obstacle spawner and set up for velocity changes
|
||||
ObstacleSpawner obstacleSpawner = FindFirstObjectByType<ObstacleSpawner>();
|
||||
if (obstacleSpawner != null)
|
||||
{
|
||||
// Subscribe to velocity changes
|
||||
OnVelocityFactorChanged -= obstacleSpawner.OnVelocityFactorChanged;
|
||||
OnVelocityFactorChanged += obstacleSpawner.OnVelocityFactorChanged;
|
||||
|
||||
// Tell spawner to reverse spawn/despawn logic
|
||||
obstacleSpawner.StartSurfacing();
|
||||
|
||||
// Immediately send current velocity factor
|
||||
obstacleSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
|
||||
}
|
||||
|
||||
// Start the surfacing sequence coroutine
|
||||
if (_surfacingSequenceCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_surfacingSequenceCoroutine);
|
||||
}
|
||||
_surfacingSequenceCoroutine = StartCoroutine(SurfacingSequence());
|
||||
|
||||
Debug.Log($"[DivingGameManager] Started surfacing with target velocity factor: {targetVelocityFactor}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine to animate the rock falling below the screen
|
||||
/// </summary>
|
||||
private IEnumerator MoveRockOffscreen(Transform rockTransform)
|
||||
{
|
||||
Vector3 startPosition = rockTransform.position;
|
||||
|
||||
// Calculate position below the screen
|
||||
Camera mainCamera = Camera.main;
|
||||
if (mainCamera == null)
|
||||
{
|
||||
Debug.LogWarning("[DivingGameManager] Cannot find main camera to calculate offscreen position");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Get a position below the bottom of the screen
|
||||
Vector3 offscreenPosition = mainCamera.ViewportToWorldPoint(new Vector3(0.5f, -0.2f, mainCamera.nearClipPlane));
|
||||
Vector3 targetPosition = new Vector3(startPosition.x, offscreenPosition.y, startPosition.z);
|
||||
|
||||
float duration = 2.0f; // Animation duration in seconds
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
// Use an easing function that accelerates to simulate falling
|
||||
float easedT = t * t; // Quadratic easing
|
||||
|
||||
rockTransform.position = Vector3.Lerp(startPosition, targetPosition, easedT);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Ensure final position is exactly at target
|
||||
rockTransform.position = targetPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine to reset the player's X position to 0 over time
|
||||
/// </summary>
|
||||
private IEnumerator ResetPlayerPosition(Transform playerTransform)
|
||||
{
|
||||
Vector3 startPosition = playerTransform.position;
|
||||
Vector3 targetPosition = new Vector3(0f, startPosition.y, startPosition.z);
|
||||
|
||||
float duration = 1.0f; // Reset duration in seconds (as requested)
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
|
||||
// Use smooth step for more natural movement
|
||||
float smoothT = Mathf.SmoothStep(0f, 1f, t);
|
||||
|
||||
playerTransform.position = Vector3.Lerp(startPosition, targetPosition, smoothT);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Ensure final position is exactly at target
|
||||
playerTransform.position = targetPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine to handle the surfacing sequence timing
|
||||
/// </summary>
|
||||
private IEnumerator SurfacingSequence()
|
||||
{
|
||||
// Wait for the configured delay
|
||||
yield return new WaitForSeconds(surfacingSpawnDelay);
|
||||
|
||||
// Find tile spawner and tell it to stop spawning
|
||||
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
||||
if (tileSpawner != null)
|
||||
{
|
||||
// Tell it to stop spawning new tiles
|
||||
tileSpawner.StopSpawning();
|
||||
Debug.Log("[DivingGameManager] Stopped spawning new tiles after delay");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the last tile leaves the screen
|
||||
/// </summary>
|
||||
private void OnLastTileLeft()
|
||||
{
|
||||
// Play the timeline
|
||||
if (surfacingTimeline != null)
|
||||
{
|
||||
surfacingTimeline.Play();
|
||||
Debug.Log("[DivingGameManager] Last tile left the screen, playing timeline");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[DivingGameManager] No surfacing timeline assigned!");
|
||||
}
|
||||
}
|
||||
|
||||
// Call this when the game ends
|
||||
public void EndGame()
|
||||
{
|
||||
// Clean up active monsters
|
||||
foreach (var monster in activeMonsters.ToArray())
|
||||
{
|
||||
if (monster != null)
|
||||
{
|
||||
monster.DespawnMonster();
|
||||
}
|
||||
}
|
||||
|
||||
activeMonsters.Clear();
|
||||
|
||||
// Final score could be saved to player prefs or other persistence
|
||||
Debug.Log($"Final Score: {playerScore}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a smooth transition to the new velocity factor
|
||||
/// </summary>
|
||||
/// <param name="targetFactor">Target velocity factor (e.g., -1.0 for surfacing speed)</param>
|
||||
public void SetVelocityFactor(float targetFactor)
|
||||
{
|
||||
if (_velocityTransitionCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_velocityTransitionCoroutine);
|
||||
}
|
||||
|
||||
_velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine to smoothly transition the velocity factor over time
|
||||
/// </summary>
|
||||
private IEnumerator<WaitForEndOfFrame> TransitionVelocityFactor(float targetFactor)
|
||||
{
|
||||
float startFactor = _currentVelocityFactor;
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < speedTransitionDuration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / speedTransitionDuration);
|
||||
|
||||
// Smooth step interpolation
|
||||
float smoothStep = t * t * (3f - 2f * t);
|
||||
|
||||
_currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep);
|
||||
|
||||
// Notify listeners about the velocity factor change
|
||||
OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
_currentVelocityFactor = targetFactor;
|
||||
|
||||
// Final assignment to ensure exact target value
|
||||
OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b2b072821054504b03fc4014b063153
|
||||
timeCreated: 1758273243
|
||||
75
Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs
Normal file
75
Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
public class DivingScoreUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI scoreText;
|
||||
[SerializeField] private GameObject scorePopupPrefab;
|
||||
[SerializeField] private Transform popupParent;
|
||||
|
||||
private DivingGameManager gameManager;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
gameManager = FindFirstObjectByType<DivingGameManager>();
|
||||
|
||||
if (gameManager != null)
|
||||
{
|
||||
// Subscribe to events
|
||||
gameManager.OnScoreChanged += UpdateScoreDisplay;
|
||||
gameManager.OnPictureTaken += ShowScorePopup;
|
||||
|
||||
// Initialize display
|
||||
UpdateScoreDisplay(gameManager.PlayerScore);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("No DivingGameManager found in scene.");
|
||||
}
|
||||
|
||||
// Create popup parent if needed
|
||||
if (popupParent == null)
|
||||
{
|
||||
popupParent = transform;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (gameManager != null)
|
||||
{
|
||||
// Unsubscribe from events
|
||||
gameManager.OnScoreChanged -= UpdateScoreDisplay;
|
||||
gameManager.OnPictureTaken -= ShowScorePopup;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateScoreDisplay(int score)
|
||||
{
|
||||
if (scoreText != null)
|
||||
{
|
||||
scoreText.text = $"Score: {score}";
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowScorePopup(Monster monster, int points)
|
||||
{
|
||||
if (scorePopupPrefab == null) return;
|
||||
|
||||
// Create popup at monster position
|
||||
GameObject popup = Instantiate(scorePopupPrefab, monster.transform.position, Quaternion.identity, popupParent);
|
||||
|
||||
// Find text component and set value
|
||||
TextMeshProUGUI popupText = popup.GetComponentInChildren<TextMeshProUGUI>();
|
||||
if (popupText != null)
|
||||
{
|
||||
popupText.text = $"+{points}";
|
||||
}
|
||||
|
||||
// Auto-destroy after delay
|
||||
Destroy(popup, 2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5ec365b02ab496d8fa1d5f7d41a33e9
|
||||
timeCreated: 1758273243
|
||||
339
Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs
Normal file
339
Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs
Normal file
@@ -0,0 +1,339 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using Pooling;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Complete floating obstacle component that handles movement and pooling.
|
||||
/// Obstacles move upward toward the surface. Collision detection is handled by the player.
|
||||
/// Once an obstacle hits the player, its collider is disabled to prevent further collisions.
|
||||
/// Uses coroutines for better performance instead of Update() calls.
|
||||
/// </summary>
|
||||
public class FloatingObstacle : MonoBehaviour, IPoolable
|
||||
{
|
||||
[Header("Obstacle Properties")]
|
||||
[Tooltip("Index of the prefab this obstacle was created from")]
|
||||
[SerializeField] private int prefabIndex;
|
||||
|
||||
[Tooltip("Movement speed of this obstacle")]
|
||||
[SerializeField] private float moveSpeed = 2f;
|
||||
|
||||
[Header("Movement")]
|
||||
[Tooltip("Whether this obstacle moves (can be disabled for static obstacles)")]
|
||||
[SerializeField] private bool enableMovement = true;
|
||||
|
||||
[Header("References")]
|
||||
[Tooltip("Reference to the spawner that created this obstacle")]
|
||||
[SerializeField] private ObstacleSpawner spawner;
|
||||
|
||||
// Public properties
|
||||
public int PrefabIndex
|
||||
{
|
||||
get => prefabIndex;
|
||||
set => prefabIndex = value;
|
||||
}
|
||||
|
||||
public float MoveSpeed
|
||||
{
|
||||
get => moveSpeed;
|
||||
set => moveSpeed = value;
|
||||
}
|
||||
|
||||
// Private fields
|
||||
private Collider2D _collider;
|
||||
private Camera _mainCamera;
|
||||
private float _screenTop;
|
||||
private float _screenBottom; // Added to track bottom of screen
|
||||
private Coroutine _movementCoroutine;
|
||||
private Coroutine _offScreenCheckCoroutine;
|
||||
private bool _isSurfacing = false; // Flag to track surfacing state
|
||||
private float _velocityFactor = 1.0f; // Current velocity factor from game manager
|
||||
private float _baseMoveSpeed; // Original move speed before velocity factor is applied
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_collider = GetComponent<Collider2D>();
|
||||
|
||||
if (_collider == null)
|
||||
{
|
||||
_collider = GetComponentInChildren<Collider2D>();
|
||||
}
|
||||
|
||||
if (_collider == null)
|
||||
{
|
||||
Debug.LogError($"[FloatingObstacle] No Collider2D found on {gameObject.name}!");
|
||||
}
|
||||
|
||||
_mainCamera = Camera.main;
|
||||
_baseMoveSpeed = moveSpeed; // Store original speed
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
StartObstacleBehavior();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopObstacleBehavior();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the obstacle behavior coroutines
|
||||
/// </summary>
|
||||
private void StartObstacleBehavior()
|
||||
{
|
||||
if (enableMovement)
|
||||
{
|
||||
_movementCoroutine = StartCoroutine(MovementCoroutine());
|
||||
}
|
||||
|
||||
_offScreenCheckCoroutine = StartCoroutine(OffScreenCheckCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops all obstacle behavior coroutines
|
||||
/// </summary>
|
||||
private void StopObstacleBehavior()
|
||||
{
|
||||
if (_movementCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_movementCoroutine);
|
||||
_movementCoroutine = null;
|
||||
}
|
||||
|
||||
if (_offScreenCheckCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_offScreenCheckCoroutine);
|
||||
_offScreenCheckCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the velocity factor changes from the DivingGameManager via ObstacleSpawner
|
||||
/// </summary>
|
||||
public void OnVelocityFactorChanged(float velocityFactor)
|
||||
{
|
||||
_velocityFactor = velocityFactor;
|
||||
|
||||
// Update actual move speed based on velocity factor and base speed
|
||||
// We use Abs for magnitude and Sign for direction
|
||||
moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor);
|
||||
|
||||
// Restart movement with new speed if needed
|
||||
if (enableMovement && gameObject.activeInHierarchy)
|
||||
{
|
||||
if (_movementCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_movementCoroutine);
|
||||
}
|
||||
_movementCoroutine = StartCoroutine(MovementCoroutine());
|
||||
}
|
||||
|
||||
Debug.Log($"[FloatingObstacle] {gameObject.name} velocity factor updated to {_velocityFactor:F2}, speed: {moveSpeed:F2}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that handles obstacle movement
|
||||
/// </summary>
|
||||
private IEnumerator MovementCoroutine()
|
||||
{
|
||||
while (enabled && gameObject.activeInHierarchy)
|
||||
{
|
||||
// Use velocity factor sign to determine direction
|
||||
Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor);
|
||||
float speed = moveSpeed * Time.deltaTime;
|
||||
|
||||
// Apply movement in correct direction
|
||||
transform.position += direction * speed;
|
||||
|
||||
// Wait for next frame
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that checks if obstacle has moved off-screen
|
||||
/// Runs at a lower frequency than movement for better performance
|
||||
/// </summary>
|
||||
private IEnumerator OffScreenCheckCoroutine()
|
||||
{
|
||||
const float checkInterval = 0.2f; // Check every 200ms instead of every frame
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy)
|
||||
{
|
||||
CheckIfOffScreen();
|
||||
|
||||
// Wait for the check interval
|
||||
yield return new WaitForSeconds(checkInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the collider after hitting the player to prevent further collisions
|
||||
/// This is more performant than tracking hit state
|
||||
/// </summary>
|
||||
public void MarkDamageDealt()
|
||||
{
|
||||
if (_collider != null && _collider.enabled)
|
||||
{
|
||||
_collider.enabled = false;
|
||||
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} hit player - collider disabled");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the obstacle has moved off-screen and should be despawned
|
||||
/// </summary>
|
||||
private void CheckIfOffScreen()
|
||||
{
|
||||
if (_mainCamera == null)
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
if (_mainCamera == null) return;
|
||||
}
|
||||
|
||||
// Always recalculate screen bounds to ensure accuracy
|
||||
Vector3 topWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 1f, _mainCamera.transform.position.z));
|
||||
_screenTop = topWorldPoint.y;
|
||||
|
||||
Vector3 bottomWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 0f, _mainCamera.transform.position.z));
|
||||
_screenBottom = bottomWorldPoint.y;
|
||||
|
||||
// Check if obstacle is significantly above screen top (obstacles move upward)
|
||||
// Use a larger buffer to ensure obstacles are truly off-screen before returning to pool
|
||||
if (transform.position.y > _screenTop + 5f)
|
||||
{
|
||||
Debug.Log($"[FloatingObstacle] {gameObject.name} off-screen at Y:{transform.position.y:F2}, screen top:{_screenTop:F2}");
|
||||
ReturnToPool();
|
||||
}
|
||||
else if (transform.position.y < _screenBottom - 5f) // Added check for bottom screen edge
|
||||
{
|
||||
Debug.Log($"[FloatingObstacle] {gameObject.name} below screen at Y:{transform.position.y:F2}, screen bottom:{_screenBottom:F2}");
|
||||
ReturnToPool();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this obstacle to the spawner's pool
|
||||
/// </summary>
|
||||
private void ReturnToPool()
|
||||
{
|
||||
// CRITICAL: Stop all behavior first to prevent race conditions
|
||||
// This ensures no more off-screen checks or movement happen during pool return
|
||||
StopObstacleBehavior();
|
||||
|
||||
if (spawner != null)
|
||||
{
|
||||
spawner.ReturnObstacleToPool(gameObject, prefabIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to find the spawner instead of destroying the object
|
||||
ObstacleSpawner foundSpawner = FindFirstObjectByType<ObstacleSpawner>();
|
||||
if (foundSpawner != null)
|
||||
{
|
||||
Debug.LogWarning($"[FloatingObstacle] Obstacle {gameObject.name} lost spawner reference, found replacement spawner");
|
||||
spawner = foundSpawner;
|
||||
spawner.ReturnObstacleToPool(gameObject, prefabIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No spawner found - just deactivate the object instead of destroying it
|
||||
Debug.LogWarning($"[FloatingObstacle] No spawner found for {gameObject.name}, deactivating safely");
|
||||
gameObject.SetActive(false);
|
||||
|
||||
// Move to a safe location to avoid interference
|
||||
transform.position = new Vector3(1000f, 1000f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the spawner reference for this obstacle
|
||||
/// </summary>
|
||||
/// <param name="obstacleSpawner">The spawner that created this obstacle</param>
|
||||
public void SetSpawner(ObstacleSpawner obstacleSpawner)
|
||||
{
|
||||
spawner = obstacleSpawner;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the obstacle is retrieved from the pool
|
||||
/// </summary>
|
||||
public void OnSpawn()
|
||||
{
|
||||
// Reset all state first
|
||||
_screenTop = 0f; // Reset cached screen bounds
|
||||
_mainCamera = Camera.main; // Refresh camera reference
|
||||
|
||||
// Re-enable the collider for reuse
|
||||
if (_collider != null)
|
||||
{
|
||||
_collider.enabled = true;
|
||||
}
|
||||
|
||||
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} spawned from pool");
|
||||
|
||||
// Note: Don't start coroutines here - OnEnable() will handle that when SetActive(true) is called
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the obstacle is returned to the pool
|
||||
/// </summary>
|
||||
public void OnDespawn()
|
||||
{
|
||||
// Stop all coroutines before returning to pool
|
||||
StopObstacleBehavior();
|
||||
|
||||
// Re-enable collider for next use (in case it was disabled)
|
||||
if (_collider != null)
|
||||
{
|
||||
_collider.enabled = true;
|
||||
}
|
||||
|
||||
Debug.Log($"[FloatingObstacle] Obstacle {gameObject.name} despawned to pool");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to manually trigger return to pool (for external systems)
|
||||
/// </summary>
|
||||
public void ForceReturnToPool()
|
||||
{
|
||||
ReturnToPool();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to enable/disable movement at runtime
|
||||
/// </summary>
|
||||
public void SetMovementEnabled(bool enabled)
|
||||
{
|
||||
if (enableMovement == enabled) return;
|
||||
|
||||
enableMovement = enabled;
|
||||
|
||||
// Restart coroutines to apply movement change
|
||||
if (gameObject.activeInHierarchy)
|
||||
{
|
||||
StopObstacleBehavior();
|
||||
StartObstacleBehavior();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets surfacing mode, which reverses obstacle movement direction
|
||||
/// </summary>
|
||||
public void StartSurfacing()
|
||||
{
|
||||
if (_isSurfacing) return; // Already surfacing
|
||||
|
||||
_isSurfacing = true;
|
||||
|
||||
// Reverse movement speed (already handled by ObstacleSpawner, but this ensures consistency)
|
||||
moveSpeed *= -1;
|
||||
|
||||
Debug.Log($"[FloatingObstacle] {gameObject.name} started surfacing with speed: {moveSpeed}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32718083aef44be2a4318681fcdf5b2e
|
||||
timeCreated: 1758117709
|
||||
133
Assets/Scripts/Minigames/DivingForPictures/Monster.cs
Normal file
133
Assets/Scripts/Minigames/DivingForPictures/Monster.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
public class Monster : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
[SerializeField] private CircleCollider2D detectionCollider;
|
||||
|
||||
private bool pictureAlreadyTaken = false;
|
||||
private Camera mainCamera;
|
||||
|
||||
// Events
|
||||
public event Action<Monster> OnPictureTaken;
|
||||
public event Action<Monster> OnMonsterSpawned;
|
||||
public event Action<Monster> OnMonsterDespawned;
|
||||
|
||||
// Properties
|
||||
public float PictureRadius => detectionCollider != null ? detectionCollider.radius : 0f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (detectionCollider == null)
|
||||
detectionCollider = GetComponent<CircleCollider2D>();
|
||||
|
||||
mainCamera = Camera.main;
|
||||
|
||||
// Start checking if monster is off-screen
|
||||
StartCoroutine(CheckIfOffScreen());
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
pictureAlreadyTaken = false;
|
||||
OnMonsterSpawned?.Invoke(this);
|
||||
}
|
||||
|
||||
private IEnumerator CheckIfOffScreen()
|
||||
{
|
||||
WaitForSeconds wait = new WaitForSeconds(0.5f);
|
||||
|
||||
while (true)
|
||||
{
|
||||
yield return wait;
|
||||
|
||||
if (!IsVisibleToCamera())
|
||||
{
|
||||
DespawnMonster();
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsVisibleToCamera()
|
||||
{
|
||||
if (mainCamera == null)
|
||||
mainCamera = Camera.main;
|
||||
|
||||
if (mainCamera == null)
|
||||
return false;
|
||||
|
||||
// Get the world position (will account for parent movement)
|
||||
Vector3 worldPosition = transform.position;
|
||||
Vector3 viewportPoint = mainCamera.WorldToViewportPoint(worldPosition);
|
||||
|
||||
// Adjust buffer to be larger below the screen to account for downward movement
|
||||
float bufferSides = 0.2f;
|
||||
float bufferTop = 0.2f;
|
||||
float bufferBottom = 0.5f; // Larger buffer below the screen
|
||||
|
||||
return viewportPoint.x > -bufferSides &&
|
||||
viewportPoint.x < 1 + bufferSides &&
|
||||
viewportPoint.y > -bufferBottom &&
|
||||
viewportPoint.y < 1 + bufferTop;
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
// Check if it's the player
|
||||
if (other.CompareTag("Player") && !pictureAlreadyTaken)
|
||||
{
|
||||
TakePicture();
|
||||
}
|
||||
}
|
||||
|
||||
// Called when a picture is taken of this monster
|
||||
public void TakePicture()
|
||||
{
|
||||
if (pictureAlreadyTaken) return;
|
||||
|
||||
pictureAlreadyTaken = true;
|
||||
OnPictureTaken?.Invoke(this);
|
||||
|
||||
DespawnMonster();
|
||||
}
|
||||
|
||||
// Public method to despawn this monster
|
||||
public void DespawnMonster()
|
||||
{
|
||||
if (gameObject.activeSelf)
|
||||
{
|
||||
OnMonsterDespawned?.Invoke(this);
|
||||
gameObject.SetActive(false);
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Visualization for the picture radius in editor
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
// Get the collider in edit mode
|
||||
if (detectionCollider == null)
|
||||
detectionCollider = GetComponent<CircleCollider2D>();
|
||||
|
||||
if (detectionCollider != null)
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(transform.position, detectionCollider.radius / 2);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Update collider radius in editor
|
||||
private void OnValidate()
|
||||
{
|
||||
if (detectionCollider == null)
|
||||
detectionCollider = GetComponent<CircleCollider2D>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1b1889b120f4259a9fa9b7e415ea58a
|
||||
timeCreated: 1758273243
|
||||
@@ -0,0 +1,25 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
public class MonsterSpawnPoint : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Visual radius for spawn point in editor")]
|
||||
public float gizmoRadius = 0.5f;
|
||||
|
||||
// Visual indicator for editor only
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(transform.position, gizmoRadius);
|
||||
|
||||
// Draw a cross in the center for better visibility
|
||||
Gizmos.DrawLine(
|
||||
transform.position + Vector3.left * gizmoRadius * 0.5f,
|
||||
transform.position + Vector3.right * gizmoRadius * 0.5f);
|
||||
Gizmos.DrawLine(
|
||||
transform.position + Vector3.up * gizmoRadius * 0.5f,
|
||||
transform.position + Vector3.down * gizmoRadius * 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ddb6d3629fe4b46b1d7ae972a83539c
|
||||
timeCreated: 1758273243
|
||||
@@ -0,0 +1,44 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Collision behavior that handles damage from mobile obstacles.
|
||||
/// Uses trigger-based collision detection with shared immunity state.
|
||||
/// </summary>
|
||||
public class ObstacleCollision : PlayerCollisionBehavior
|
||||
{
|
||||
protected override void HandleCollisionResponse(Collider2D obstacle)
|
||||
{
|
||||
// Mark the obstacle as having dealt damage to prevent multiple hits
|
||||
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
||||
if (obstacleComponent != null)
|
||||
{
|
||||
obstacleComponent.MarkDamageDealt();
|
||||
}
|
||||
|
||||
Debug.Log($"[ObstacleCollision] Player hit by obstacle {obstacle.gameObject.name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to prevent input blocking during damage immunity
|
||||
/// Since obstacles pass through the player, we don't want to block input
|
||||
/// </summary>
|
||||
protected override void OnImmunityStart()
|
||||
{
|
||||
Debug.Log($"[ObstacleCollision] Damage immunity started for {damageImmunityDuration} seconds");
|
||||
|
||||
// Don't block input for obstacle damage - let player keep moving
|
||||
// The shared immunity system will handle the collision prevention
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to handle immunity end
|
||||
/// </summary>
|
||||
protected override void OnImmunityEnd()
|
||||
{
|
||||
Debug.Log($"[ObstacleCollision] Damage immunity ended");
|
||||
// No special handling needed - shared immunity system handles collider re-enabling
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9c18dbd013d42ae8c221e6205e4d49c
|
||||
timeCreated: 1758116850
|
||||
54
Assets/Scripts/Minigames/DivingForPictures/ObstaclePool.cs
Normal file
54
Assets/Scripts/Minigames/DivingForPictures/ObstaclePool.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
using Pooling;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages a pool of floating obstacle objects to reduce garbage collection overhead.
|
||||
/// Optimized for handling a large number of different obstacle prefab types.
|
||||
/// </summary>
|
||||
public class ObstaclePool : MultiPrefabPool<FloatingObstacle>
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns an obstacle to the pool
|
||||
/// </summary>
|
||||
/// <param name="obstacle">The obstacle to return to the pool</param>
|
||||
/// <param name="prefabIndex">The index of the prefab this obstacle was created from</param>
|
||||
public void ReturnObstacle(GameObject obstacle, int prefabIndex)
|
||||
{
|
||||
if (obstacle != null)
|
||||
{
|
||||
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
||||
if (obstacleComponent != null)
|
||||
{
|
||||
Debug.Log($"[ObstaclePool] Returning obstacle {obstacle.name} to pool");
|
||||
Return(obstacleComponent, prefabIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Attempted to return a GameObject without a FloatingObstacle component: {obstacle.name}");
|
||||
Destroy(obstacle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an obstacle from the pool, or creates a new one if the pool is empty
|
||||
/// </summary>
|
||||
/// <returns>An obstacle instance ready to use</returns>
|
||||
public GameObject GetObstacle(int prefabIndex)
|
||||
{
|
||||
Debug.Log($"[ObstaclePool] GetObstacle called for prefab index {prefabIndex}");
|
||||
FloatingObstacle obstacleComponent = Get(prefabIndex);
|
||||
|
||||
if (obstacleComponent == null)
|
||||
{
|
||||
Debug.LogError($"[ObstaclePool] Get() returned null for prefab index {prefabIndex}");
|
||||
return null;
|
||||
}
|
||||
|
||||
Debug.Log($"[ObstaclePool] Get() returned obstacle {obstacleComponent.name}, active state: {obstacleComponent.gameObject.activeInHierarchy}");
|
||||
return obstacleComponent.gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a53ba79246a94dc4a71d2fb0d7214cfb
|
||||
timeCreated: 1758116804
|
||||
568
Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs
Normal file
568
Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs
Normal file
@@ -0,0 +1,568 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using Pooling;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Spawns and manages mobile obstacles for the diving minigame.
|
||||
/// Uses object pooling and validates spawn positions to avoid colliding with tiles.
|
||||
/// </summary>
|
||||
public class ObstacleSpawner : MonoBehaviour
|
||||
{
|
||||
[Header("Obstacle Prefabs")]
|
||||
[Tooltip("List of possible obstacle prefabs to spawn")]
|
||||
[SerializeField] private List<GameObject> obstaclePrefabs;
|
||||
|
||||
[Header("Spawn Settings")]
|
||||
[Tooltip("Time interval between spawn attempts (in seconds)")]
|
||||
[SerializeField] private float spawnInterval = 2f;
|
||||
|
||||
[Tooltip("Random variation in spawn timing (+/- seconds)")]
|
||||
[SerializeField] private float spawnIntervalVariation = 0.5f;
|
||||
|
||||
[Tooltip("Maximum number of spawn position attempts before skipping")]
|
||||
[SerializeField] private int maxSpawnAttempts = 10;
|
||||
|
||||
[Tooltip("Radius around spawn point to check for tile collisions")]
|
||||
[SerializeField] private float spawnCollisionRadius = 1f;
|
||||
|
||||
[Header("Spawn Position")]
|
||||
[Tooltip("How far below screen to spawn obstacles")]
|
||||
[SerializeField] private float spawnDistanceBelowScreen = 2f;
|
||||
|
||||
[Tooltip("Horizontal spawn range (distance from center)")]
|
||||
[SerializeField] private float spawnRangeX = 8f;
|
||||
|
||||
[Header("Obstacle Properties Randomization")]
|
||||
[Tooltip("Minimum movement speed for spawned obstacles")]
|
||||
[SerializeField] private float minMoveSpeed = 1f;
|
||||
|
||||
[Tooltip("Maximum movement speed for spawned obstacles")]
|
||||
[SerializeField] private float maxMoveSpeed = 4f;
|
||||
|
||||
[Header("Object Pooling")]
|
||||
[Tooltip("Whether to use object pooling for obstacles")]
|
||||
[SerializeField] private bool useObjectPooling = true;
|
||||
|
||||
[Tooltip("Maximum objects per prefab type in pool")]
|
||||
[SerializeField] private int maxPerPrefabPoolSize = 3;
|
||||
|
||||
[Tooltip("Total maximum pool size across all prefab types")]
|
||||
[SerializeField] private int totalMaxPoolSize = 15;
|
||||
|
||||
[Header("Layer Settings")]
|
||||
[Tooltip("Layer mask for tile collision detection during spawn position validation")]
|
||||
[SerializeField] private LayerMask tileLayerMask = -1; // Let user configure which layers to avoid
|
||||
|
||||
[Tooltip("Target layer for spawned obstacles - obstacles will be placed on this layer")]
|
||||
[SerializeField] private int obstacleLayer = 11; // Default to layer 11, but configurable
|
||||
|
||||
[Header("Events")]
|
||||
[Tooltip("Called when an obstacle is spawned")]
|
||||
public UnityEvent<GameObject> onObstacleSpawned;
|
||||
|
||||
[Tooltip("Called when an obstacle is returned to pool")]
|
||||
public UnityEvent<GameObject> onObstacleDestroyed;
|
||||
|
||||
// Private fields
|
||||
private ObstaclePool _obstaclePool;
|
||||
private Camera _mainCamera;
|
||||
private float _screenBottom;
|
||||
private float _spawnRangeX;
|
||||
private Coroutine _spawnCoroutine;
|
||||
private readonly List<GameObject> _activeObstacles = new List<GameObject>();
|
||||
private int _obstacleCounter = 0; // Counter for unique obstacle naming
|
||||
private bool _isSurfacing = false; // Flag to track surfacing state
|
||||
private float _velocityFactor = 1.0f; // Current velocity factor from the game manager
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
|
||||
// Validate obstacle prefabs
|
||||
ValidateObstaclePrefabs();
|
||||
|
||||
if (useObjectPooling)
|
||||
{
|
||||
InitializeObjectPool();
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
CalculateScreenBounds();
|
||||
StartSpawning();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
StopSpawning();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that all prefabs have required components
|
||||
/// </summary>
|
||||
private void ValidateObstaclePrefabs()
|
||||
{
|
||||
for (int i = 0; i < obstaclePrefabs.Count; i++)
|
||||
{
|
||||
if (obstaclePrefabs[i] == null) continue;
|
||||
|
||||
// Check if the prefab has a FloatingObstacle component
|
||||
if (obstaclePrefabs[i].GetComponent<FloatingObstacle>() == null)
|
||||
{
|
||||
Debug.LogWarning($"Obstacle prefab {obstaclePrefabs[i].name} does not have a FloatingObstacle component. Adding one automatically.");
|
||||
obstaclePrefabs[i].AddComponent<FloatingObstacle>();
|
||||
}
|
||||
|
||||
// Ensure the prefab is on the correct layer (using configurable obstacleLayer)
|
||||
if (obstaclePrefabs[i].layer != obstacleLayer)
|
||||
{
|
||||
Debug.LogWarning($"Obstacle prefab {obstaclePrefabs[i].name} is not on the configured obstacle layer ({obstacleLayer}). Setting layer automatically.");
|
||||
SetLayerRecursively(obstaclePrefabs[i], obstacleLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the layer of a GameObject and all its children
|
||||
/// </summary>
|
||||
private void SetLayerRecursively(GameObject obj, int layer)
|
||||
{
|
||||
obj.layer = layer;
|
||||
foreach (Transform child in obj.transform)
|
||||
{
|
||||
SetLayerRecursively(child.gameObject, layer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the object pool system
|
||||
/// </summary>
|
||||
private void InitializeObjectPool()
|
||||
{
|
||||
GameObject poolGO = new GameObject("ObstaclePool");
|
||||
poolGO.transform.SetParent(transform);
|
||||
_obstaclePool = poolGO.AddComponent<ObstaclePool>();
|
||||
|
||||
// Set up pool configuration
|
||||
_obstaclePool.maxPerPrefabPoolSize = maxPerPrefabPoolSize;
|
||||
_obstaclePool.totalMaxPoolSize = totalMaxPoolSize;
|
||||
|
||||
// Convert GameObject list to FloatingObstacle list
|
||||
List<FloatingObstacle> prefabObstacles = new List<FloatingObstacle>(obstaclePrefabs.Count);
|
||||
foreach (var prefab in obstaclePrefabs)
|
||||
{
|
||||
if (prefab != null)
|
||||
{
|
||||
FloatingObstacle obstacleComponent = prefab.GetComponent<FloatingObstacle>();
|
||||
if (obstacleComponent != null)
|
||||
{
|
||||
prefabObstacles.Add(obstacleComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Obstacle prefab {prefab.name} is missing a FloatingObstacle component!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the pool
|
||||
_obstaclePool.Initialize(prefabObstacles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate screen bounds in world space dynamically
|
||||
/// </summary>
|
||||
private void CalculateScreenBounds()
|
||||
{
|
||||
if (_mainCamera == null)
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
if (_mainCamera == null)
|
||||
{
|
||||
Debug.LogError("[ObstacleSpawner] No main camera found!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate screen bottom (Y spawn position will be 2 units below this)
|
||||
Vector3 bottomWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0.5f, 0f, _mainCamera.nearClipPlane));
|
||||
_screenBottom = bottomWorldPoint.y;
|
||||
|
||||
// Calculate screen width in world units
|
||||
Vector3 leftWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(0f, 0.5f, _mainCamera.nearClipPlane));
|
||||
Vector3 rightWorldPoint = _mainCamera.ViewportToWorldPoint(new Vector3(1f, 0.5f, _mainCamera.nearClipPlane));
|
||||
float screenWidth = rightWorldPoint.x - leftWorldPoint.x;
|
||||
|
||||
// Calculate spawn range based on 80% of screen width (40% on each side from center)
|
||||
_spawnRangeX = (screenWidth * 0.8f) / 2f;
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] Screen calculated - Width: {screenWidth:F2}, Bottom: {_screenBottom:F2}, Spawn Range X: ±{_spawnRangeX:F2}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the obstacle spawning coroutine
|
||||
/// </summary>
|
||||
public void StartSpawning()
|
||||
{
|
||||
if (_spawnCoroutine == null)
|
||||
{
|
||||
_spawnCoroutine = StartCoroutine(SpawnObstaclesCoroutine());
|
||||
Debug.Log("[ObstacleSpawner] Started spawning obstacles");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the obstacle spawning coroutine
|
||||
/// </summary>
|
||||
public void StopSpawning()
|
||||
{
|
||||
if (_spawnCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_spawnCoroutine);
|
||||
_spawnCoroutine = null;
|
||||
Debug.Log("[ObstacleSpawner] Stopped spawning obstacles");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main spawning coroutine that runs continuously
|
||||
/// </summary>
|
||||
private IEnumerator SpawnObstaclesCoroutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Calculate next spawn time with variation
|
||||
float nextSpawnTime = spawnInterval + Random.Range(-spawnIntervalVariation, spawnIntervalVariation);
|
||||
nextSpawnTime = Mathf.Max(0.1f, nextSpawnTime); // Ensure minimum interval
|
||||
|
||||
yield return new WaitForSeconds(nextSpawnTime);
|
||||
|
||||
// Attempt to spawn an obstacle
|
||||
TrySpawnObstacle();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to spawn an obstacle at a valid position
|
||||
/// </summary>
|
||||
private void TrySpawnObstacle()
|
||||
{
|
||||
// Don't spawn new obstacles when surfacing
|
||||
if (_isSurfacing)
|
||||
{
|
||||
Debug.Log("[ObstacleSpawner] Skipping obstacle spawn - currently surfacing");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] TrySpawnObstacle called at {Time.time:F2}");
|
||||
|
||||
if (obstaclePrefabs == null || obstaclePrefabs.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("[ObstacleSpawner] No obstacle prefabs available for spawning!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 spawnPosition;
|
||||
bool foundValidPosition = false;
|
||||
|
||||
// Try to find a valid spawn position
|
||||
for (int attempts = 0; attempts < maxSpawnAttempts; attempts++)
|
||||
{
|
||||
spawnPosition = GetRandomSpawnPosition();
|
||||
|
||||
if (IsValidSpawnPosition(spawnPosition))
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] Found valid position at {spawnPosition} after {attempts + 1} attempts");
|
||||
SpawnObstacleAt(spawnPosition);
|
||||
foundValidPosition = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] Position {spawnPosition} invalid (attempt {attempts + 1}/{maxSpawnAttempts})");
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundValidPosition)
|
||||
{
|
||||
Debug.LogWarning($"[ObstacleSpawner] SPAWN MISSED: Could not find valid spawn position after {maxSpawnAttempts} attempts at {Time.time:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random spawn position below the screen
|
||||
/// </summary>
|
||||
private Vector3 GetRandomSpawnPosition()
|
||||
{
|
||||
// Use dynamically calculated spawn range (80% of screen width)
|
||||
float randomX = Random.Range(-_spawnRangeX, _spawnRangeX);
|
||||
// Spawn 2 units below screen bottom
|
||||
float spawnY = _screenBottom - 2f;
|
||||
|
||||
return new Vector3(randomX, spawnY, 0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a spawn position is valid (not colliding with tiles)
|
||||
/// </summary>
|
||||
private bool IsValidSpawnPosition(Vector3 position)
|
||||
{
|
||||
// Use OverlapCircle to check for collisions with tiles
|
||||
Collider2D collision = Physics2D.OverlapCircle(position, spawnCollisionRadius, tileLayerMask);
|
||||
return collision == null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns an obstacle at the specified position
|
||||
/// </summary>
|
||||
private void SpawnObstacleAt(Vector3 position)
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] SpawnObstacleAt called for position {position}");
|
||||
|
||||
// Select random prefab
|
||||
int prefabIndex = Random.Range(0, obstaclePrefabs.Count);
|
||||
GameObject prefab = obstaclePrefabs[prefabIndex];
|
||||
|
||||
if (prefab == null)
|
||||
{
|
||||
Debug.LogError($"[ObstacleSpawner] SPAWN FAILED: Obstacle prefab at index {prefabIndex} is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject obstacle;
|
||||
|
||||
// Spawn using pool or instantiate directly
|
||||
if (useObjectPooling && _obstaclePool != null)
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] Requesting obstacle from pool (prefab index {prefabIndex})");
|
||||
obstacle = _obstaclePool.GetObstacle(prefabIndex);
|
||||
if (obstacle == null)
|
||||
{
|
||||
Debug.LogError($"[ObstacleSpawner] SPAWN FAILED: Failed to get obstacle from pool for prefab index {prefabIndex}!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Important: Set position/parent/rotation BEFORE activation to avoid visual glitches
|
||||
obstacle.transform.position = position;
|
||||
obstacle.transform.rotation = prefab.transform.rotation;
|
||||
obstacle.transform.SetParent(transform);
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] Got obstacle {obstacle.name} from pool, active state: {obstacle.activeInHierarchy}");
|
||||
|
||||
// ENHANCED FORCE ACTIVATION - more robust approach
|
||||
if (!obstacle.activeInHierarchy)
|
||||
{
|
||||
Debug.LogWarning($"[ObstacleSpawner] Pool returned inactive object {obstacle.name}, force activating!");
|
||||
|
||||
// Configure obstacle BEFORE activation
|
||||
ConfigureObstacle(obstacle, prefabIndex);
|
||||
|
||||
// Force activate the obstacle
|
||||
obstacle.SetActive(true);
|
||||
|
||||
// Double-check activation status
|
||||
if (!obstacle.activeInHierarchy)
|
||||
{
|
||||
Debug.LogError($"[ObstacleSpawner] CRITICAL ERROR: Failed to activate {obstacle.name} after multiple attempts!");
|
||||
|
||||
// Last resort: try to instantiate a new one instead
|
||||
GameObject newObstacle = Instantiate(prefab, position, prefab.transform.rotation, transform);
|
||||
if (newObstacle != null)
|
||||
{
|
||||
obstacle = newObstacle;
|
||||
ConfigureObstacle(obstacle, prefabIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] After force activation, {obstacle.name} active state: {obstacle.activeInHierarchy}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Still configure if already active
|
||||
ConfigureObstacle(obstacle, prefabIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] Instantiating new obstacle (pooling disabled)");
|
||||
obstacle = Instantiate(prefab, position, prefab.transform.rotation, transform);
|
||||
|
||||
// Configure the newly instantiated obstacle
|
||||
ConfigureObstacle(obstacle, prefabIndex);
|
||||
}
|
||||
|
||||
// Assign unique name with counter
|
||||
_obstacleCounter++;
|
||||
string oldName = obstacle.name;
|
||||
obstacle.name = $"Obstacle{_obstacleCounter:D3}";
|
||||
Debug.Log($"[ObstacleSpawner] Renamed obstacle from '{oldName}' to '{obstacle.name}', active state: {obstacle.activeInHierarchy}");
|
||||
|
||||
// Track active obstacles
|
||||
_activeObstacles.Add(obstacle);
|
||||
|
||||
// Invoke events
|
||||
onObstacleSpawned?.Invoke(obstacle);
|
||||
Debug.Log($"[ObstacleSpawner] After events, obstacle {obstacle.name} active state: {obstacle.activeInHierarchy}");
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] Successfully spawned obstacle {obstacle.name} at {position}. Active count: {_activeObstacles.Count}, Final active state: {obstacle.activeInHierarchy}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures an obstacle with randomized properties
|
||||
/// </summary>
|
||||
private void ConfigureObstacle(GameObject obstacle, int prefabIndex)
|
||||
{
|
||||
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
||||
if (obstacleComponent != null)
|
||||
{
|
||||
// Set prefab index
|
||||
obstacleComponent.PrefabIndex = prefabIndex;
|
||||
|
||||
// Randomize properties
|
||||
obstacleComponent.MoveSpeed = Random.Range(minMoveSpeed, maxMoveSpeed);
|
||||
|
||||
// Set spawner reference (since FloatingObstacle has this built-in now)
|
||||
obstacleComponent.SetSpawner(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an obstacle to the pool (called by FloatingObstacle)
|
||||
/// </summary>
|
||||
public void ReturnObstacleToPool(GameObject obstacle, int prefabIndex)
|
||||
{
|
||||
if (obstacle == null) return;
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] ReturnObstacleToPool called for {obstacle.name}, active state: {obstacle.activeInHierarchy}");
|
||||
|
||||
// Remove from active list
|
||||
_activeObstacles.Remove(obstacle);
|
||||
|
||||
// Invoke events
|
||||
onObstacleDestroyed?.Invoke(obstacle);
|
||||
|
||||
// Return to pool or destroy
|
||||
if (useObjectPooling && _obstaclePool != null)
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] Returning {obstacle.name} to pool");
|
||||
_obstaclePool.ReturnObstacle(obstacle, prefabIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"[ObstacleSpawner] Destroying {obstacle.name} (pooling disabled)");
|
||||
Destroy(obstacle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change spawn interval at runtime
|
||||
/// </summary>
|
||||
public void SetSpawnInterval(float interval)
|
||||
{
|
||||
spawnInterval = interval;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change spawn range at runtime
|
||||
/// </summary>
|
||||
public void SetSpawnRange(float range)
|
||||
{
|
||||
spawnRangeX = range;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to set speed range at runtime
|
||||
/// </summary>
|
||||
public void SetSpeedRange(float min, float max)
|
||||
{
|
||||
minMoveSpeed = min;
|
||||
maxMoveSpeed = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to recalculate screen bounds (useful if camera changes)
|
||||
/// </summary>
|
||||
public void RecalculateScreenBounds()
|
||||
{
|
||||
CalculateScreenBounds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the velocity factor changes from the DivingGameManager
|
||||
/// </summary>
|
||||
public void OnVelocityFactorChanged(float velocityFactor)
|
||||
{
|
||||
_velocityFactor = velocityFactor;
|
||||
|
||||
// Update all active obstacles with the new velocity factor
|
||||
foreach (GameObject obstacle in _activeObstacles)
|
||||
{
|
||||
if (obstacle != null)
|
||||
{
|
||||
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
||||
if (obstacleComponent != null)
|
||||
{
|
||||
obstacleComponent.OnVelocityFactorChanged(velocityFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] Velocity factor updated to {_velocityFactor:F2}, propagated to {_activeObstacles.Count} active obstacles");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start surfacing mode - reverse direction of existing obstacles and stop spawning new ones
|
||||
/// </summary>
|
||||
public void StartSurfacing()
|
||||
{
|
||||
if (_isSurfacing) return; // Already surfacing
|
||||
|
||||
_isSurfacing = true;
|
||||
|
||||
// Notify obstacles about surfacing state (for direction-based logic)
|
||||
foreach (GameObject obstacle in _activeObstacles)
|
||||
{
|
||||
if (obstacle != null)
|
||||
{
|
||||
FloatingObstacle obstacleComponent = obstacle.GetComponent<FloatingObstacle>();
|
||||
if (obstacleComponent != null)
|
||||
{
|
||||
// Call StartSurfacing on the obstacle component itself
|
||||
obstacleComponent.StartSurfacing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[ObstacleSpawner] Started surfacing mode for {_activeObstacles.Count} active obstacles");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of currently active obstacles
|
||||
/// </summary>
|
||||
public int ActiveObstacleCount => _activeObstacles.Count;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
// Only draw if screen bounds have been calculated
|
||||
if (_spawnRangeX > 0f)
|
||||
{
|
||||
// Draw spawn area using dynamic calculations
|
||||
Gizmos.color = Color.yellow;
|
||||
Vector3 center = new Vector3(0f, _screenBottom - 2f, 0f);
|
||||
Vector3 size = new Vector3(_spawnRangeX * 2f, 1f, 1f);
|
||||
Gizmos.DrawWireCube(center, size);
|
||||
|
||||
// Draw collision radius at spawn point
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(center, spawnCollisionRadius);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49ec62157fd945fab730193e9ea0bff7
|
||||
timeCreated: 1758116903
|
||||
@@ -0,0 +1,242 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles visual feedback for player damage by making the sprite renderer blink red.
|
||||
/// Automatically subscribes to damage events from PlayerCollisionBehavior components.
|
||||
/// </summary>
|
||||
public class PlayerBlinkBehavior : MonoBehaviour
|
||||
{
|
||||
[Header("Blink Settings")]
|
||||
[Tooltip("Color to blink to when taking damage (typically red for damage indication)")]
|
||||
[SerializeField] private Color damageBlinkColor = Color.red;
|
||||
|
||||
[Tooltip("How fast to blink between normal and damage colors (seconds between color changes)")]
|
||||
[SerializeField] private float blinkRate = 0.15f;
|
||||
|
||||
[Tooltip("Alpha value for the damage color (0 = transparent, 1 = opaque)")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] private float damageColorAlpha = 0.7f;
|
||||
|
||||
[Header("References")]
|
||||
[Tooltip("The SpriteRenderer to apply blink effects to (auto-assigned if empty)")]
|
||||
[SerializeField] private SpriteRenderer targetSpriteRenderer;
|
||||
|
||||
private bool _isBlinking;
|
||||
private bool _isShowingDamageColor;
|
||||
private Coroutine _blinkCoroutine;
|
||||
private Color _originalColor; // Missing field declaration
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Auto-assign sprite renderer if not set
|
||||
if (targetSpriteRenderer == null)
|
||||
{
|
||||
targetSpriteRenderer = GetComponent<SpriteRenderer>();
|
||||
if (targetSpriteRenderer == null)
|
||||
{
|
||||
targetSpriteRenderer = GetComponentInChildren<SpriteRenderer>();
|
||||
if (targetSpriteRenderer != null)
|
||||
{
|
||||
Debug.Log($"[PlayerBlinkBehavior] Found SpriteRenderer on child object: {targetSpriteRenderer.gameObject.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetSpriteRenderer == null)
|
||||
{
|
||||
Debug.LogError("[PlayerBlinkBehavior] No SpriteRenderer found on this GameObject or its children!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Store original color
|
||||
_originalColor = targetSpriteRenderer.color;
|
||||
|
||||
// Ensure damage color has the correct alpha
|
||||
damageBlinkColor.a = damageColorAlpha;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Subscribe to immunity events (renamed from damage events)
|
||||
PlayerCollisionBehavior.OnImmunityStarted += StartBlinking;
|
||||
PlayerCollisionBehavior.OnImmunityEnded += StopBlinking;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// Unsubscribe from immunity events
|
||||
PlayerCollisionBehavior.OnImmunityStarted -= StartBlinking;
|
||||
PlayerCollisionBehavior.OnImmunityEnded -= StopBlinking;
|
||||
|
||||
// Stop any ongoing blink effect
|
||||
if (_blinkCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_blinkCoroutine);
|
||||
_blinkCoroutine = null;
|
||||
}
|
||||
|
||||
// Restore original color
|
||||
RestoreOriginalColor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the red blinking effect when damage begins
|
||||
/// </summary>
|
||||
private void StartBlinking()
|
||||
{
|
||||
if (targetSpriteRenderer == null) return;
|
||||
|
||||
Debug.Log("[PlayerBlinkBehavior] Starting damage blink effect");
|
||||
|
||||
// Stop any existing blink coroutine
|
||||
if (_blinkCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_blinkCoroutine);
|
||||
}
|
||||
|
||||
_isBlinking = true;
|
||||
_isShowingDamageColor = false;
|
||||
|
||||
// Start the blink coroutine
|
||||
_blinkCoroutine = StartCoroutine(BlinkCoroutine());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the blinking effect when damage ends
|
||||
/// </summary>
|
||||
private void StopBlinking()
|
||||
{
|
||||
Debug.Log("[PlayerBlinkBehavior] Stopping damage blink effect");
|
||||
|
||||
_isBlinking = false;
|
||||
|
||||
// Stop the blink coroutine
|
||||
if (_blinkCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_blinkCoroutine);
|
||||
_blinkCoroutine = null;
|
||||
}
|
||||
|
||||
// Restore original color
|
||||
RestoreOriginalColor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that handles the blinking animation
|
||||
/// </summary>
|
||||
private IEnumerator BlinkCoroutine()
|
||||
{
|
||||
while (_isBlinking && targetSpriteRenderer != null)
|
||||
{
|
||||
// Toggle between original and damage colors
|
||||
if (_isShowingDamageColor)
|
||||
{
|
||||
targetSpriteRenderer.color = _originalColor;
|
||||
_isShowingDamageColor = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetSpriteRenderer.color = damageBlinkColor;
|
||||
_isShowingDamageColor = true;
|
||||
}
|
||||
|
||||
// Wait for blink interval
|
||||
yield return new WaitForSeconds(blinkRate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores the sprite renderer to its original color
|
||||
/// </summary>
|
||||
private void RestoreOriginalColor()
|
||||
{
|
||||
if (targetSpriteRenderer != null)
|
||||
{
|
||||
targetSpriteRenderer.color = _originalColor;
|
||||
_isShowingDamageColor = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the original color reference (useful if sprite color changes during gameplay)
|
||||
/// </summary>
|
||||
public void UpdateOriginalColor()
|
||||
{
|
||||
if (targetSpriteRenderer != null && !_isBlinking)
|
||||
{
|
||||
_originalColor = targetSpriteRenderer.color;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change blink color at runtime
|
||||
/// </summary>
|
||||
public void SetDamageBlinkColor(Color newColor)
|
||||
{
|
||||
damageBlinkColor = newColor;
|
||||
damageBlinkColor.a = damageColorAlpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change blink rate at runtime
|
||||
/// </summary>
|
||||
public void SetBlinkRate(float rate)
|
||||
{
|
||||
blinkRate = rate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if currently blinking
|
||||
/// </summary>
|
||||
public bool IsBlinking => _isBlinking;
|
||||
|
||||
/// <summary>
|
||||
/// Manually trigger blink effect (useful for testing or other damage sources)
|
||||
/// </summary>
|
||||
public void TriggerBlink(float duration)
|
||||
{
|
||||
if (_blinkCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_blinkCoroutine);
|
||||
}
|
||||
|
||||
StartCoroutine(ManualBlinkCoroutine(duration));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine for manually triggered blink effects
|
||||
/// </summary>
|
||||
private IEnumerator ManualBlinkCoroutine(float duration)
|
||||
{
|
||||
_isBlinking = true;
|
||||
_isShowingDamageColor = false;
|
||||
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration && targetSpriteRenderer != null)
|
||||
{
|
||||
// Toggle between original and damage colors
|
||||
if (_isShowingDamageColor)
|
||||
{
|
||||
targetSpriteRenderer.color = _originalColor;
|
||||
_isShowingDamageColor = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetSpriteRenderer.color = damageBlinkColor;
|
||||
_isShowingDamageColor = true;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(blinkRate);
|
||||
elapsed += blinkRate;
|
||||
}
|
||||
|
||||
// Ensure we end with original color
|
||||
RestoreOriginalColor();
|
||||
_isBlinking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8ea29cc80524de8affe17b930cd75c1
|
||||
timeCreated: 1758114229
|
||||
@@ -0,0 +1,371 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for handling player collisions with world obstacles.
|
||||
/// Uses trigger-based collision detection with shared immunity state across all collision behaviors.
|
||||
/// </summary>
|
||||
public abstract class PlayerCollisionBehavior : MonoBehaviour
|
||||
{
|
||||
[Header("Collision Settings")]
|
||||
[Tooltip("Duration in seconds of damage immunity after being hit")]
|
||||
[SerializeField] protected float damageImmunityDuration = 1.0f;
|
||||
|
||||
[Tooltip("Layer mask for obstacle detection - configure which layers contain obstacles")]
|
||||
[SerializeField] protected LayerMask obstacleLayerMask = -1;
|
||||
|
||||
[Header("Input Blocking")]
|
||||
[Tooltip("Whether to block player input during damage immunity period")]
|
||||
[SerializeField] protected bool blockInputDuringImmunity;
|
||||
|
||||
[Header("References")]
|
||||
[Tooltip("The player character GameObject (auto-assigned if empty)")]
|
||||
[SerializeField] protected GameObject playerCharacter;
|
||||
|
||||
[Tooltip("Reference to the PlayerController component (auto-assigned if empty)")]
|
||||
[SerializeField] protected PlayerController playerController;
|
||||
|
||||
// Static shared immunity state across all collision behaviors
|
||||
private static bool _isGloballyImmune;
|
||||
private static Coroutine _globalImmunityCoroutine;
|
||||
private static MonoBehaviour _coroutineRunner;
|
||||
private static Collider2D _sharedPlayerCollider;
|
||||
|
||||
// Events for immunity and damage state changes
|
||||
public static event Action OnImmunityStarted;
|
||||
public static event Action OnImmunityEnded;
|
||||
public static event Action OnDamageTaken;
|
||||
|
||||
// Instance tracking for shared state management
|
||||
private static readonly System.Collections.Generic.HashSet<PlayerCollisionBehavior> _allInstances =
|
||||
new System.Collections.Generic.HashSet<PlayerCollisionBehavior>();
|
||||
|
||||
/// <summary>
|
||||
/// Public static method to trigger immunity start event from external classes
|
||||
/// </summary>
|
||||
public static void TriggerImmunityStarted()
|
||||
{
|
||||
OnImmunityStarted?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public static method to trigger immunity end event from external classes
|
||||
/// </summary>
|
||||
public static void TriggerImmunityEnded()
|
||||
{
|
||||
OnImmunityEnded?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public static method to trigger damage taken event from external classes
|
||||
/// </summary>
|
||||
public static void TriggerDamageTaken()
|
||||
{
|
||||
OnDamageTaken?.Invoke();
|
||||
}
|
||||
|
||||
protected bool wasInputBlocked;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
// Auto-assign if not set in inspector
|
||||
if (playerCharacter == null)
|
||||
playerCharacter = gameObject;
|
||||
|
||||
if (playerController == null)
|
||||
playerController = GetComponent<PlayerController>();
|
||||
|
||||
// Set up shared collider reference (only once)
|
||||
if (_sharedPlayerCollider == null)
|
||||
{
|
||||
_sharedPlayerCollider = GetComponent<Collider2D>();
|
||||
if (_sharedPlayerCollider == null)
|
||||
{
|
||||
_sharedPlayerCollider = GetComponentInChildren<Collider2D>();
|
||||
if (_sharedPlayerCollider != null)
|
||||
{
|
||||
Debug.Log($"[PlayerCollisionBehavior] Found collider on child object: {_sharedPlayerCollider.gameObject.name}");
|
||||
}
|
||||
}
|
||||
|
||||
if (_sharedPlayerCollider == null)
|
||||
{
|
||||
Debug.LogError($"[PlayerCollisionBehavior] No Collider2D found on this GameObject or its children!");
|
||||
}
|
||||
}
|
||||
|
||||
// Set up coroutine runner (use first instance)
|
||||
if (_coroutineRunner == null)
|
||||
{
|
||||
_coroutineRunner = this;
|
||||
}
|
||||
|
||||
// Register this instance
|
||||
_allInstances.Add(this);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
// Unregister this instance
|
||||
_allInstances.Remove(this);
|
||||
|
||||
// Clean up static references if this was the coroutine runner
|
||||
if (_coroutineRunner == this)
|
||||
{
|
||||
if (_globalImmunityCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_globalImmunityCoroutine);
|
||||
_globalImmunityCoroutine = null;
|
||||
}
|
||||
_coroutineRunner = null;
|
||||
|
||||
// Find a new coroutine runner if there are other instances
|
||||
foreach (var instance in _allInstances)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
_coroutineRunner = instance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when another collider enters this trigger collider
|
||||
/// </summary>
|
||||
/// <param name="other">The other collider that entered the trigger</param>
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
Debug.Log($"[{GetType().Name}] OnTriggerEnter2D called with collider: {other.gameObject.name} on layer: {other.gameObject.layer}");
|
||||
|
||||
// Check if the other collider is on one of our obstacle layers and we're not immune
|
||||
if (IsObstacleLayer(other.gameObject.layer) && !_isGloballyImmune)
|
||||
{
|
||||
OnCollisionDetected(other);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a collision with an obstacle is detected
|
||||
/// </summary>
|
||||
/// <param name="obstacle">The obstacle collider that was hit</param>
|
||||
protected virtual void OnCollisionDetected(Collider2D obstacle)
|
||||
{
|
||||
if (_isGloballyImmune) return;
|
||||
|
||||
// Trigger damage taken event first
|
||||
OnDamageTaken?.Invoke();
|
||||
|
||||
// Start shared immunity period
|
||||
StartGlobalImmunity();
|
||||
|
||||
// Call the specific collision response
|
||||
HandleCollisionResponse(obstacle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the shared immunity period across all collision behaviors
|
||||
/// </summary>
|
||||
private void StartGlobalImmunity()
|
||||
{
|
||||
if (_isGloballyImmune) return; // Already immune
|
||||
|
||||
_isGloballyImmune = true;
|
||||
|
||||
// Disable the shared collider to prevent further collisions
|
||||
if (_sharedPlayerCollider != null)
|
||||
{
|
||||
_sharedPlayerCollider.enabled = false;
|
||||
}
|
||||
|
||||
// Stop any existing immunity coroutine
|
||||
if (_globalImmunityCoroutine != null && _coroutineRunner != null)
|
||||
{
|
||||
_coroutineRunner.StopCoroutine(_globalImmunityCoroutine);
|
||||
}
|
||||
|
||||
// Start new immunity coroutine
|
||||
if (_coroutineRunner != null)
|
||||
{
|
||||
_globalImmunityCoroutine = _coroutineRunner.StartCoroutine(ImmunityCoroutine());
|
||||
}
|
||||
|
||||
// Notify all instances about immunity start
|
||||
foreach (var instance in _allInstances)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
instance.OnImmunityStart();
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast immunity start event
|
||||
OnImmunityStarted?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that handles the immunity timer
|
||||
/// </summary>
|
||||
private IEnumerator ImmunityCoroutine()
|
||||
{
|
||||
Debug.Log($"[PlayerCollisionBehavior] Starting immunity coroutine for {damageImmunityDuration} seconds");
|
||||
|
||||
yield return new WaitForSeconds(damageImmunityDuration);
|
||||
|
||||
Debug.Log($"[PlayerCollisionBehavior] Immunity period ended");
|
||||
|
||||
// End immunity
|
||||
_isGloballyImmune = false;
|
||||
_globalImmunityCoroutine = null;
|
||||
|
||||
// Re-enable the shared collider
|
||||
if (_sharedPlayerCollider != null)
|
||||
{
|
||||
_sharedPlayerCollider.enabled = true;
|
||||
}
|
||||
|
||||
// Notify all instances about immunity end
|
||||
foreach (var instance in _allInstances)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
instance.OnImmunityEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast immunity end event
|
||||
OnImmunityEnded?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this method to implement specific collision response behavior
|
||||
/// </summary>
|
||||
/// <param name="obstacle">The obstacle that was collided with</param>
|
||||
protected abstract void HandleCollisionResponse(Collider2D obstacle);
|
||||
|
||||
/// <summary>
|
||||
/// Called when damage immunity starts (called on all instances)
|
||||
/// </summary>
|
||||
protected virtual void OnImmunityStart()
|
||||
{
|
||||
Debug.Log($"[{GetType().Name}] Damage immunity started for {damageImmunityDuration} seconds");
|
||||
|
||||
// Block input if specified
|
||||
if (blockInputDuringImmunity)
|
||||
{
|
||||
BlockPlayerInput();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when damage immunity ends (called on all instances)
|
||||
/// </summary>
|
||||
protected virtual void OnImmunityEnd()
|
||||
{
|
||||
Debug.Log($"[{GetType().Name}] Damage immunity ended");
|
||||
|
||||
// Restore input if it was blocked
|
||||
if (wasInputBlocked)
|
||||
{
|
||||
RestorePlayerInput();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores player input after immunity
|
||||
/// </summary>
|
||||
protected virtual void RestorePlayerInput()
|
||||
{
|
||||
if (playerController != null && wasInputBlocked)
|
||||
{
|
||||
playerController.enabled = true;
|
||||
wasInputBlocked = false;
|
||||
|
||||
// Update the controller's target position to current position to prevent snapping
|
||||
UpdateControllerTarget();
|
||||
|
||||
Debug.Log($"[{GetType().Name}] Player input restored after immunity");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blocks player input during immunity
|
||||
/// </summary>
|
||||
protected virtual void BlockPlayerInput()
|
||||
{
|
||||
if (playerController != null && playerController.enabled)
|
||||
{
|
||||
playerController.enabled = false;
|
||||
wasInputBlocked = true;
|
||||
Debug.Log($"[{GetType().Name}] Player input blocked during immunity");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the PlayerController's internal target to match current position
|
||||
/// </summary>
|
||||
protected virtual void UpdateControllerTarget()
|
||||
{
|
||||
if (playerController != null && playerCharacter != null)
|
||||
{
|
||||
// Use reflection to update the private _targetFingerX field
|
||||
var targetField = typeof(PlayerController)
|
||||
.GetField("_targetFingerX", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
if (targetField != null)
|
||||
{
|
||||
targetField.SetValue(playerController, playerCharacter.transform.position.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given layer is included in our obstacle layer mask
|
||||
/// </summary>
|
||||
/// <param name="layer">The layer to check</param>
|
||||
/// <returns>True if the layer is included in the obstacle layer mask</returns>
|
||||
private bool IsObstacleLayer(int layer)
|
||||
{
|
||||
return (obstacleLayerMask.value & (1 << layer)) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public property to check if player is currently immune (shared across all instances)
|
||||
/// </summary>
|
||||
public static bool IsImmune => _isGloballyImmune;
|
||||
|
||||
/// <summary>
|
||||
/// Public method to manually end immunity (affects all collision behaviors)
|
||||
/// </summary>
|
||||
public static void EndImmunity()
|
||||
{
|
||||
if (_isGloballyImmune && _globalImmunityCoroutine != null && _coroutineRunner != null)
|
||||
{
|
||||
_coroutineRunner.StopCoroutine(_globalImmunityCoroutine);
|
||||
_globalImmunityCoroutine = null;
|
||||
_isGloballyImmune = false;
|
||||
|
||||
// Re-enable the shared collider
|
||||
if (_sharedPlayerCollider != null)
|
||||
{
|
||||
_sharedPlayerCollider.enabled = true;
|
||||
}
|
||||
|
||||
// Notify all instances
|
||||
foreach (var instance in _allInstances)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
instance.OnImmunityEnd();
|
||||
}
|
||||
}
|
||||
|
||||
OnImmunityEnded?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6c959bca2e24e72bf22e92439580d79
|
||||
timeCreated: 1758109598
|
||||
@@ -31,7 +31,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void OnTap(Vector2 worldPosition)
|
||||
{
|
||||
Debug.Log($"[EndlessDescenderController] OnTap at {worldPosition}");
|
||||
// Debug.Log($"[EndlessDescenderController] OnTap at {worldPosition}");
|
||||
_targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
||||
_isTouchActive = true;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void OnHoldStart(Vector2 worldPosition)
|
||||
{
|
||||
Debug.Log($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
|
||||
// Debug.Log($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
|
||||
_targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
||||
_isTouchActive = true;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void OnHoldMove(Vector2 worldPosition)
|
||||
{
|
||||
Debug.Log($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
|
||||
// Debug.Log($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
|
||||
_targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void OnHoldEnd(Vector2 worldPosition)
|
||||
{
|
||||
Debug.Log($"[EndlessDescenderController] OnHoldEnd at {worldPosition}");
|
||||
// Debug.Log($"[EndlessDescenderController] OnHoldEnd at {worldPosition}");
|
||||
_isTouchActive = false;
|
||||
}
|
||||
|
||||
|
||||
331
Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
Normal file
331
Assets/Scripts/Minigames/DivingForPictures/RopeBreaker.cs
Normal file
@@ -0,0 +1,331 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using GogoGaga.OptimizedRopesAndCables;
|
||||
|
||||
/// <summary>
|
||||
/// Component that allows breaking a rope in half.
|
||||
/// Attach this to the same GameObject that has a Rope and LineRenderer component.
|
||||
/// </summary>
|
||||
public class RopeBreaker : MonoBehaviour
|
||||
{
|
||||
[Header("Break Settings")]
|
||||
[Tooltip("Position along rope where break occurs (0-1)")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] private float breakPosition = 0.5f;
|
||||
|
||||
[Tooltip("Effect to spawn at break point (optional)")]
|
||||
[SerializeField] private GameObject breakEffect;
|
||||
|
||||
[Tooltip("Sound to play when rope breaks (optional)")]
|
||||
[SerializeField] private AudioClip breakSound;
|
||||
|
||||
[Header("Physics Settings")]
|
||||
[Tooltip("Follow speed for the rope physics simulation")]
|
||||
[SerializeField] private float ropeFollowSpeed = 5f;
|
||||
|
||||
[Tooltip("Trailing amount for the rope physics simulation")]
|
||||
[SerializeField] private float ropeTrailing = 0.2f;
|
||||
|
||||
[Tooltip("Gravity strength applied to hanging rope end")]
|
||||
[SerializeField] private float ropeGravityStrength = 9.8f;
|
||||
|
||||
[Tooltip("How strongly the rope tries to hang vertically")]
|
||||
[SerializeField] private float ropeVerticalHangStrength = 2f;
|
||||
|
||||
[Tooltip("Damping for physics movement (higher = less bouncy)")]
|
||||
[SerializeField] private float ropeDamping = 0.3f;
|
||||
|
||||
[Tooltip("Initial separation distance between rope ends when broken")]
|
||||
[SerializeField] private float initialSeparationDistance = 0.1f;
|
||||
|
||||
[Tooltip("Initial downward impulse for falling rope end")]
|
||||
[SerializeField] private float initialFallImpulse = 2.0f;
|
||||
|
||||
// Private references
|
||||
private Rope originalRope;
|
||||
private LineRenderer originalLineRenderer;
|
||||
private GameObject firstHalfRope;
|
||||
private GameObject secondHalfRope;
|
||||
private Rope firstHalfRopeComponent;
|
||||
private Rope secondHalfRopeComponent;
|
||||
private Transform breakPointTransform;
|
||||
private Transform secondBreakTransform;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Get references to the required components
|
||||
originalRope = GetComponent<Rope>();
|
||||
originalLineRenderer = GetComponent<LineRenderer>();
|
||||
|
||||
if (originalRope == null || originalLineRenderer == null)
|
||||
{
|
||||
Debug.LogError("RopeBreaker requires both Rope and LineRenderer components on the same GameObject");
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Breaks the rope at the specified position.
|
||||
/// </summary>
|
||||
/// <param name="breakPositionOverride">Optional override for break position (0-1)</param>
|
||||
/// <returns>True if rope was broken successfully, false otherwise</returns>
|
||||
public bool BreakRope(float? breakPositionOverride = null)
|
||||
{
|
||||
if (originalRope == null || !originalRope.StartPoint || !originalRope.EndPoint)
|
||||
{
|
||||
Debug.LogError("Cannot break rope: Missing rope component or endpoints");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use override position if provided
|
||||
float breakPos = breakPositionOverride ?? breakPosition;
|
||||
breakPos = Mathf.Clamp01(breakPos);
|
||||
|
||||
// Get the world position at the break point
|
||||
Vector3 breakPointPosition = originalRope.GetPointAt(breakPos);
|
||||
|
||||
// Create a transform at the break point to use as an anchor
|
||||
CreateBreakPointTransform(breakPointPosition);
|
||||
|
||||
// Create two new rope GameObjects
|
||||
CreateRopeSegments(breakPointPosition);
|
||||
|
||||
// Hide the original rope
|
||||
originalLineRenderer.enabled = false;
|
||||
|
||||
// Play effects
|
||||
PlayBreakEffects(breakPointPosition);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a transform at the break point to use as an anchor
|
||||
/// </summary>
|
||||
private void CreateBreakPointTransform(Vector3 breakPointPosition)
|
||||
{
|
||||
// Store references to the original rope endpoints
|
||||
Transform originalStartPoint = originalRope.StartPoint;
|
||||
Transform originalEndPoint = originalRope.EndPoint;
|
||||
|
||||
// Create a new GameObject for the break point (attached to Player)
|
||||
GameObject breakPointObj = new GameObject("RopeBreakPoint");
|
||||
breakPointTransform = breakPointObj.transform;
|
||||
breakPointTransform.position = breakPointPosition;
|
||||
breakPointTransform.SetParent(transform.parent); // Parent to the same parent as the rope
|
||||
|
||||
// Add the physics follower component to the break point
|
||||
RopeEndPhysicsFollower follower = breakPointObj.AddComponent<RopeEndPhysicsFollower>();
|
||||
|
||||
// Set specific transform to follow instead of using tag
|
||||
follower.SetTargetTransform(originalStartPoint);
|
||||
follower.canFall = false; // Player rope end doesn't fall
|
||||
follower.followSpeed = ropeFollowSpeed;
|
||||
follower.trailing = ropeTrailing;
|
||||
|
||||
// Create second break point (for the rock-attached end)
|
||||
GameObject secondBreakObj = new GameObject("RopeBreakPoint_Second");
|
||||
secondBreakTransform = secondBreakObj.transform;
|
||||
secondBreakTransform.position = breakPointPosition;
|
||||
secondBreakTransform.SetParent(transform.parent);
|
||||
|
||||
// Add physics behavior to second break point
|
||||
RopeEndPhysicsFollower secondFollower = secondBreakObj.AddComponent<RopeEndPhysicsFollower>();
|
||||
|
||||
// Set specific transform to follow instead of using tag
|
||||
secondFollower.SetTargetTransform(originalEndPoint);
|
||||
secondFollower.canFall = true; // Rock end can fall
|
||||
secondFollower.followSpeed = ropeFollowSpeed;
|
||||
secondFollower.trailing = ropeTrailing;
|
||||
secondFollower.gravityStrength = ropeGravityStrength;
|
||||
secondFollower.verticalHangStrength = ropeVerticalHangStrength;
|
||||
secondFollower.damping = ropeDamping;
|
||||
secondFollower.initialFallImpulse = initialFallImpulse;
|
||||
|
||||
// Create initial separation
|
||||
Vector3 direction = (originalEndPoint.position - breakPointPosition).normalized;
|
||||
if (direction.magnitude < 0.01f) direction = Vector3.down;
|
||||
|
||||
breakPointTransform.position -= direction * initialSeparationDistance * 0.5f;
|
||||
secondBreakTransform.position += direction * initialSeparationDistance * 0.5f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates two new rope GameObjects for the broken segments
|
||||
/// </summary>
|
||||
private void CreateRopeSegments(Vector3 breakPointPosition)
|
||||
{
|
||||
// Create the first half rope (from start to break point)
|
||||
firstHalfRope = new GameObject("Rope_FirstHalf");
|
||||
firstHalfRope.transform.position = transform.position;
|
||||
firstHalfRope.transform.rotation = transform.rotation;
|
||||
firstHalfRope.transform.SetParent(transform.parent);
|
||||
|
||||
// Add Rope component which automatically adds LineRenderer due to RequireComponent
|
||||
firstHalfRopeComponent = firstHalfRope.AddComponent<Rope>();
|
||||
|
||||
// Get the LineRenderer that was automatically added
|
||||
LineRenderer firstLineRenderer = firstHalfRope.GetComponent<LineRenderer>();
|
||||
if (firstLineRenderer == null)
|
||||
{
|
||||
// Only add if somehow not created (shouldn't happen, but safety check)
|
||||
firstLineRenderer = firstHalfRope.AddComponent<LineRenderer>();
|
||||
}
|
||||
CopyLineRendererProperties(originalLineRenderer, firstLineRenderer);
|
||||
|
||||
// Create the second half rope (from break point to end)
|
||||
secondHalfRope = new GameObject("Rope_SecondHalf");
|
||||
secondHalfRope.transform.position = transform.position;
|
||||
secondHalfRope.transform.rotation = transform.rotation;
|
||||
secondHalfRope.transform.SetParent(transform.parent);
|
||||
|
||||
// Add Rope component which automatically adds LineRenderer due to RequireComponent
|
||||
secondHalfRopeComponent = secondHalfRope.AddComponent<Rope>();
|
||||
|
||||
// Get the LineRenderer that was automatically added
|
||||
LineRenderer secondLineRenderer = secondHalfRope.GetComponent<LineRenderer>();
|
||||
if (secondLineRenderer == null)
|
||||
{
|
||||
// Only add if somehow not created (shouldn't happen, but safety check)
|
||||
secondLineRenderer = secondHalfRope.AddComponent<LineRenderer>();
|
||||
}
|
||||
CopyLineRendererProperties(originalLineRenderer, secondLineRenderer);
|
||||
|
||||
// Configure the first half rope
|
||||
firstHalfRopeComponent.SetStartPoint(originalRope.StartPoint);
|
||||
firstHalfRopeComponent.SetEndPoint(breakPointTransform, false); // Don't recalculate yet
|
||||
|
||||
// Copy properties from original rope
|
||||
CopyRopeProperties(originalRope, firstHalfRopeComponent);
|
||||
|
||||
// Explicitly initialize the rope
|
||||
firstHalfRopeComponent.Initialize();
|
||||
|
||||
// Now force recalculation after initialization
|
||||
firstHalfRopeComponent.RecalculateRope();
|
||||
|
||||
// Configure the second half rope - REVERSED: Rock (End) is now Start, Break point is now End
|
||||
secondHalfRopeComponent.SetStartPoint(originalRope.EndPoint);
|
||||
secondHalfRopeComponent.SetEndPoint(secondBreakTransform, false); // Don't recalculate yet
|
||||
|
||||
// Copy properties from original rope
|
||||
CopyRopeProperties(originalRope, secondHalfRopeComponent);
|
||||
|
||||
// Explicitly initialize the rope
|
||||
secondHalfRopeComponent.Initialize();
|
||||
|
||||
// Now force recalculation after initialization
|
||||
secondHalfRopeComponent.RecalculateRope();
|
||||
|
||||
// Set explicit rope length constraints on the physics followers
|
||||
// This needs to be done after the rope segments are created so we have the correct rope lengths
|
||||
RopeEndPhysicsFollower playerFollower = breakPointTransform.GetComponent<RopeEndPhysicsFollower>();
|
||||
if (playerFollower != null)
|
||||
{
|
||||
playerFollower.SetMaxDistance(firstHalfRopeComponent.ropeLength);
|
||||
}
|
||||
|
||||
RopeEndPhysicsFollower rockFollower = secondBreakTransform.GetComponent<RopeEndPhysicsFollower>();
|
||||
if (rockFollower != null)
|
||||
{
|
||||
rockFollower.SetMaxDistance(secondHalfRopeComponent.ropeLength);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies properties from one LineRenderer to another
|
||||
/// </summary>
|
||||
private void CopyLineRendererProperties(LineRenderer source, LineRenderer destination)
|
||||
{
|
||||
// Copy material
|
||||
destination.material = source.material;
|
||||
|
||||
// Copy colors
|
||||
destination.startColor = source.startColor;
|
||||
destination.endColor = source.endColor;
|
||||
|
||||
// Copy width
|
||||
destination.startWidth = source.startWidth;
|
||||
destination.endWidth = source.endWidth;
|
||||
|
||||
// Copy other properties
|
||||
destination.numCornerVertices = source.numCornerVertices;
|
||||
destination.numCapVertices = source.numCapVertices;
|
||||
destination.alignment = source.alignment;
|
||||
destination.textureMode = source.textureMode;
|
||||
destination.generateLightingData = source.generateLightingData;
|
||||
destination.useWorldSpace = source.useWorldSpace;
|
||||
destination.loop = source.loop;
|
||||
destination.sortingLayerID = source.sortingLayerID;
|
||||
destination.sortingOrder = source.sortingOrder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies properties from one Rope to another
|
||||
/// </summary>
|
||||
private void CopyRopeProperties(Rope source, Rope destination)
|
||||
{
|
||||
destination.linePoints = source.linePoints;
|
||||
destination.stiffness = source.stiffness;
|
||||
destination.damping = source.damping;
|
||||
destination.ropeLength = source.ropeLength / 2f; // Halve the rope length for each segment
|
||||
destination.ropeWidth = source.ropeWidth;
|
||||
destination.midPointWeight = source.midPointWeight;
|
||||
destination.midPointPosition = source.midPointPosition;
|
||||
|
||||
// Recalculate the rope to update its appearance
|
||||
destination.RecalculateRope();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays visual and audio effects at the break point
|
||||
/// </summary>
|
||||
private void PlayBreakEffects(Vector3 breakPointPosition)
|
||||
{
|
||||
// Spawn break effect if assigned
|
||||
if (breakEffect != null)
|
||||
{
|
||||
Instantiate(breakEffect, breakPointPosition, Quaternion.identity);
|
||||
}
|
||||
|
||||
// Play break sound if assigned
|
||||
if (breakSound != null)
|
||||
{
|
||||
AudioSource.PlayClipAtPoint(breakSound, breakPointPosition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores the original rope and cleans up the broken pieces
|
||||
/// </summary>
|
||||
public void RestoreRope()
|
||||
{
|
||||
// Re-enable the original rope
|
||||
if (originalLineRenderer != null)
|
||||
{
|
||||
originalLineRenderer.enabled = true;
|
||||
}
|
||||
|
||||
// Clean up the broken rope pieces
|
||||
if (firstHalfRope != null)
|
||||
{
|
||||
Destroy(firstHalfRope);
|
||||
}
|
||||
|
||||
if (secondHalfRope != null)
|
||||
{
|
||||
Destroy(secondHalfRope);
|
||||
}
|
||||
|
||||
// Clean up both break points
|
||||
if (breakPointTransform != null)
|
||||
{
|
||||
Destroy(breakPointTransform.gameObject);
|
||||
}
|
||||
|
||||
if (secondBreakTransform != null)
|
||||
{
|
||||
Destroy(secondBreakTransform.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30919200017f4879867c3b6289429924
|
||||
timeCreated: 1758466190
|
||||
@@ -0,0 +1,306 @@
|
||||
using GogoGaga.OptimizedRopesAndCables;
|
||||
using UnityEngine;
|
||||
|
||||
public class RopeEndPhysicsFollower : MonoBehaviour
|
||||
{
|
||||
[Header("Target Settings")]
|
||||
[Tooltip("Transform this endpoint should follow")]
|
||||
public Transform targetTransform;
|
||||
[Tooltip("Tag of the object this endpoint should follow (only used if targetTransform is not set)")]
|
||||
public string targetTag;
|
||||
[Tooltip("How quickly the endpoint follows the target when not using physics")]
|
||||
public float followSpeed = 5f;
|
||||
[Tooltip("How much trailing (0 = instant, 1 = very slow)")]
|
||||
public float trailing = 0.2f;
|
||||
|
||||
[Header("Physics Simulation")]
|
||||
[Tooltip("Gravity strength")]
|
||||
public float gravityStrength = 9.8f;
|
||||
[Tooltip("How strongly the rope attempts to hang vertically")]
|
||||
public float verticalHangStrength = 2f;
|
||||
[Tooltip("Damping for physics movement (higher = less bouncy)")]
|
||||
public float damping = 0.3f;
|
||||
[Tooltip("Initial downward impulse when enabled")]
|
||||
public float initialFallImpulse = 2.0f;
|
||||
[Tooltip("Whether this end can fall with gravity (false for player-attached ends)")]
|
||||
public bool canFall = true;
|
||||
|
||||
// Private variables
|
||||
private Transform target;
|
||||
private Vector2 physicsVelocity;
|
||||
private Vector2 offset;
|
||||
private Vector3 lastTargetPosition;
|
||||
private bool initialized = false;
|
||||
private bool debugLog = true;
|
||||
|
||||
// Rope reference to get the actual rope length
|
||||
private Rope attachedRope;
|
||||
private float maxDistance;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Find the Rope component to determine the maximum distance
|
||||
FindAttachedRope();
|
||||
|
||||
// Use targetTransform if set, otherwise try to find by tag
|
||||
if (targetTransform != null)
|
||||
{
|
||||
target = targetTransform;
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Using assigned target transform: {target.name}");
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(targetTag))
|
||||
{
|
||||
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
||||
if (found)
|
||||
{
|
||||
target = found.transform;
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Found target by tag '{targetTag}': {target.name}");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize offset and velocities
|
||||
if (target)
|
||||
{
|
||||
// Only store horizontal offset, not vertical for physics simulation
|
||||
Vector2 offsetVec = transform.position - target.position;
|
||||
offset.x = offsetVec.x;
|
||||
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
||||
lastTargetPosition = target.position;
|
||||
|
||||
// Apply initial falling impulse if this end can fall
|
||||
if (canFall)
|
||||
{
|
||||
physicsVelocity = new Vector2(0, -initialFallImpulse);
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Initialized with target: {target.name}, initial Y velocity: {physicsVelocity.y}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = Vector2.zero;
|
||||
lastTargetPosition = transform.position;
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] No target found");
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!target) return;
|
||||
|
||||
// Calculate deltaTime for physics stability
|
||||
float deltaTime = Time.deltaTime;
|
||||
|
||||
// Get target velocity
|
||||
Vector3 targetVelocity = (target.position - lastTargetPosition) / deltaTime;
|
||||
lastTargetPosition = target.position;
|
||||
|
||||
// Current position relative to target
|
||||
Vector2 relativePos = new Vector2(
|
||||
transform.position.x - target.position.x,
|
||||
transform.position.y - target.position.y
|
||||
);
|
||||
|
||||
// Get the straight-line distance between target and this transform
|
||||
float currentDistance = relativePos.magnitude;
|
||||
|
||||
// Normalized direction from target to this transform
|
||||
Vector2 directionToTarget = relativePos.normalized;
|
||||
|
||||
// Apply forces based on whether this end can fall
|
||||
if (canFall)
|
||||
{
|
||||
// 1. Gravity - always pulls down
|
||||
physicsVelocity.y -= gravityStrength * deltaTime;
|
||||
}
|
||||
|
||||
// 2. Vertical hanging force - try to align X with target when stationary
|
||||
if (Mathf.Abs(targetVelocity.x) < 0.1f)
|
||||
{
|
||||
// Use the actual X position of the target as the desired X position
|
||||
float xOffset = transform.position.x - target.position.x;
|
||||
physicsVelocity.x -= xOffset * verticalHangStrength * deltaTime;
|
||||
|
||||
// Debug log to track vertical hanging behavior
|
||||
if (debugLog && Time.frameCount % 120 == 0)
|
||||
{
|
||||
Debug.Log($"[RopeEndPhysicsFollower] Vertical hanging: target X={target.position.x}, my X={transform.position.x}, offset={xOffset}");
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Rope length constraint - apply a force toward the target if we're exceeding the rope length
|
||||
if (currentDistance > maxDistance)
|
||||
{
|
||||
// Calculate constraint force proportional to how much we're exceeding the rope length
|
||||
float exceededDistance = currentDistance - maxDistance;
|
||||
|
||||
// Apply a stronger constraint force the more we exceed the max distance
|
||||
Vector2 constraintForce = -directionToTarget * exceededDistance * 10f;
|
||||
|
||||
// Apply to velocity
|
||||
physicsVelocity += constraintForce * deltaTime;
|
||||
|
||||
if (debugLog && Time.frameCount % 60 == 0)
|
||||
{
|
||||
Debug.Log($"[RopeEndPhysicsFollower] Exceeding max distance: {exceededDistance}, applying constraint");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply damping to physics velocity
|
||||
physicsVelocity *= (1f - damping * deltaTime);
|
||||
|
||||
// Log physics state periodically for debugging
|
||||
if (debugLog && Time.frameCount % 60 == 0)
|
||||
{
|
||||
Debug.Log($"[RopeEndPhysicsFollower] Y position: {transform.position.y}, Y velocity: {physicsVelocity.y}, Distance: {currentDistance}/{maxDistance}");
|
||||
}
|
||||
|
||||
// Apply physics velocity to position
|
||||
Vector3 newPos = transform.position;
|
||||
newPos.x += physicsVelocity.x * deltaTime;
|
||||
|
||||
// Only apply vertical movement if this end can fall
|
||||
if (canFall)
|
||||
{
|
||||
newPos.y += physicsVelocity.y * deltaTime;
|
||||
}
|
||||
|
||||
transform.position = newPos;
|
||||
|
||||
// Final distance check - hard constraint to ensure we never exceed the rope length
|
||||
// This prevents numerical instability from causing the rope to stretch
|
||||
float finalDistance = Vector2.Distance(
|
||||
new Vector2(transform.position.x, transform.position.y),
|
||||
new Vector2(target.position.x, target.position.y)
|
||||
);
|
||||
|
||||
if (finalDistance > maxDistance)
|
||||
{
|
||||
// Calculate the direction from target to this transform
|
||||
Vector2 direction = new Vector2(
|
||||
transform.position.x - target.position.x,
|
||||
transform.position.y - target.position.y
|
||||
).normalized;
|
||||
|
||||
// Set position to be exactly at the maximum distance
|
||||
Vector3 constrainedPos = new Vector3(
|
||||
target.position.x + direction.x * maxDistance,
|
||||
target.position.y + direction.y * maxDistance,
|
||||
transform.position.z
|
||||
);
|
||||
|
||||
transform.position = constrainedPos;
|
||||
}
|
||||
}
|
||||
|
||||
private void FindAttachedRope()
|
||||
{
|
||||
// Find the Rope component on the same GameObject or parent
|
||||
attachedRope = GetComponent<Rope>();
|
||||
if (attachedRope == null)
|
||||
{
|
||||
attachedRope = GetComponentInParent<Rope>();
|
||||
}
|
||||
|
||||
// If we still couldn't find it, look for it on a child GameObject
|
||||
if (attachedRope == null)
|
||||
{
|
||||
attachedRope = GetComponentInChildren<Rope>();
|
||||
}
|
||||
|
||||
// Look for a rope attached to this endpoint
|
||||
if (attachedRope == null)
|
||||
{
|
||||
// Find any rope that has this transform as an endpoint
|
||||
Rope[] allRopes = FindObjectsOfType<Rope>();
|
||||
foreach (var rope in allRopes)
|
||||
{
|
||||
if (rope.EndPoint == transform || rope.StartPoint == transform)
|
||||
{
|
||||
attachedRope = rope;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set max distance based on rope length if we found a rope
|
||||
if (attachedRope != null)
|
||||
{
|
||||
maxDistance = attachedRope.ropeLength;
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Found attached rope with length: {maxDistance}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default fallback value if no rope is found
|
||||
maxDistance = 2f;
|
||||
if (debugLog) Debug.Log("[RopeEndPhysicsFollower] No attached rope found, using default max distance");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTargetTransform(Transform newTarget)
|
||||
{
|
||||
targetTransform = newTarget;
|
||||
target = newTarget;
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
lastTargetPosition = target.position;
|
||||
|
||||
// Only update horizontal offset to maintain current vertical position
|
||||
if (initialized)
|
||||
{
|
||||
Vector2 newOffset = transform.position - target.position;
|
||||
offset.x = newOffset.x;
|
||||
// Don't update offset.y to allow gravity to work
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 newOffset = transform.position - target.position;
|
||||
offset.x = newOffset.x;
|
||||
offset.y = 0; // Don't preserve vertical offset for gravity simulation
|
||||
}
|
||||
|
||||
// Apply initial falling impulse if this end can fall
|
||||
if (canFall)
|
||||
{
|
||||
physicsVelocity = new Vector2(physicsVelocity.x, -initialFallImpulse);
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Reset Y velocity to {physicsVelocity.y} after target change to {target.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Original tag-based method kept for backward compatibility
|
||||
public void SetTargetTag(string tag)
|
||||
{
|
||||
targetTag = tag;
|
||||
GameObject found = GameObject.FindGameObjectWithTag(targetTag);
|
||||
if (found)
|
||||
{
|
||||
SetTargetTransform(found.transform);
|
||||
}
|
||||
}
|
||||
|
||||
// Debug method to force reset the physics
|
||||
public void ForceResetPhysics()
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
// Reset velocity with a strong downward impulse
|
||||
physicsVelocity = new Vector2(0, -initialFallImpulse * 2f);
|
||||
|
||||
// Reset position to be at the same level as the target
|
||||
Vector3 pos = transform.position;
|
||||
pos.y = target.position.y;
|
||||
transform.position = pos;
|
||||
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Physics forcibly reset, new Y velocity: {physicsVelocity.y}");
|
||||
}
|
||||
}
|
||||
|
||||
// Method to manually set the maximum distance
|
||||
public void SetMaxDistance(float distance)
|
||||
{
|
||||
maxDistance = distance;
|
||||
if (debugLog) Debug.Log($"[RopeEndPhysicsFollower] Max distance manually set to: {maxDistance}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc5a0e35b5e74474b4241fae08971e7a
|
||||
timeCreated: 1758485385
|
||||
294
Assets/Scripts/Minigames/DivingForPictures/TileBumpCollision.cs
Normal file
294
Assets/Scripts/Minigames/DivingForPictures/TileBumpCollision.cs
Normal file
@@ -0,0 +1,294 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Minigames.DivingForPictures
|
||||
{
|
||||
/// <summary>
|
||||
/// Collision behavior that bumps the player toward the center of the trench.
|
||||
/// Uses trigger-based collision detection with coroutine-based bump timing.
|
||||
/// </summary>
|
||||
public class TileBumpCollision : PlayerCollisionBehavior
|
||||
{
|
||||
[Header("Bump Settings")]
|
||||
[Tooltip("Type of bump response: Impulse pushes with force, SmoothToCenter moves directly to center")]
|
||||
[SerializeField] private BumpMode bumpMode = BumpMode.Impulse;
|
||||
|
||||
[Tooltip("Force strength for impulse bumps - higher values push further toward center")]
|
||||
[SerializeField] private float bumpForce = 5.0f;
|
||||
|
||||
[Tooltip("Speed for smooth movement to center (units per second)")]
|
||||
[SerializeField] private float smoothMoveSpeed = 8.0f;
|
||||
|
||||
[Tooltip("Animation curve controlling bump movement over time")]
|
||||
[SerializeField] private AnimationCurve bumpCurve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 2f), new Keyframe(1f, 1f, 0f, 0f));
|
||||
|
||||
[Tooltip("Whether to block player input during bump movement")]
|
||||
[SerializeField] private bool blockInputDuringBump = true;
|
||||
|
||||
public enum BumpMode
|
||||
{
|
||||
Impulse, // Force-based push toward center (distance depends on force)
|
||||
SmoothToCenter // Smooth movement to center with configurable speed
|
||||
}
|
||||
|
||||
private bool _isBumping;
|
||||
private Coroutine _bumpCoroutine;
|
||||
private bool _bumpInputBlocked; // Tracks bump-specific input blocking
|
||||
|
||||
protected override void HandleCollisionResponse(Collider2D obstacle)
|
||||
{
|
||||
switch (bumpMode)
|
||||
{
|
||||
case BumpMode.Impulse:
|
||||
StartImpulseBump();
|
||||
break;
|
||||
|
||||
case BumpMode.SmoothToCenter:
|
||||
StartSmoothMoveToCenter();
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.Log($"[TileBumpCollision] Collision handled with {bumpMode} mode");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts an impulse bump toward the center with force-based distance
|
||||
/// </summary>
|
||||
private void StartImpulseBump()
|
||||
{
|
||||
if (playerCharacter == null) return;
|
||||
|
||||
float currentX = playerCharacter.transform.position.x;
|
||||
|
||||
// Calculate bump distance based on force and current position
|
||||
float directionToCenter = currentX > 0 ? -1f : 1f; // Direction toward center
|
||||
|
||||
// Calculate target position - closer to center based on bump force
|
||||
float bumpDistance = bumpForce * 0.2f; // Scale factor for distance
|
||||
float targetX = currentX + (directionToCenter * bumpDistance);
|
||||
|
||||
// Clamp to center if we would overshoot
|
||||
if ((currentX > 0 && targetX < 0) || (currentX < 0 && targetX > 0))
|
||||
{
|
||||
targetX = 0f;
|
||||
}
|
||||
|
||||
float bumpDuration = 0.5f; // Fixed duration for impulse
|
||||
|
||||
StartBump(currentX, targetX, bumpDuration);
|
||||
|
||||
Debug.Log($"[TileBumpCollision] Starting impulse bump from X={currentX} to X={targetX} (force={bumpForce})");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts smooth movement to the center
|
||||
/// </summary>
|
||||
private void StartSmoothMoveToCenter()
|
||||
{
|
||||
if (playerCharacter == null) return;
|
||||
|
||||
float currentX = playerCharacter.transform.position.x;
|
||||
float distanceToCenter = Mathf.Abs(currentX);
|
||||
|
||||
float targetX = 0f; // Always move to center
|
||||
float bumpDuration = distanceToCenter / smoothMoveSpeed; // Duration based on distance and speed
|
||||
|
||||
StartBump(currentX, targetX, bumpDuration);
|
||||
|
||||
Debug.Log($"[TileBumpCollision] Starting smooth move to center from X={currentX} (speed={smoothMoveSpeed}, duration={bumpDuration:F2}s)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Common bump initialization using coroutines
|
||||
/// </summary>
|
||||
private void StartBump(float startX, float targetX, float duration)
|
||||
{
|
||||
// Stop any existing bump
|
||||
if (_bumpCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_bumpCoroutine);
|
||||
_bumpCoroutine = null;
|
||||
}
|
||||
|
||||
_isBumping = true;
|
||||
|
||||
// Block player input if enabled (use bump-specific blocking)
|
||||
if (blockInputDuringBump && playerController != null && playerController.enabled)
|
||||
{
|
||||
playerController.enabled = false;
|
||||
_bumpInputBlocked = true;
|
||||
Debug.Log("[TileBumpCollision] Player input blocked during bump");
|
||||
}
|
||||
|
||||
// Start bump coroutine
|
||||
_bumpCoroutine = StartCoroutine(BumpCoroutine(startX, targetX, duration));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that handles the bump movement over time
|
||||
/// </summary>
|
||||
private IEnumerator BumpCoroutine(float startX, float targetX, float duration)
|
||||
{
|
||||
float elapsedTime = 0f;
|
||||
|
||||
while (elapsedTime < duration)
|
||||
{
|
||||
elapsedTime += Time.deltaTime;
|
||||
|
||||
// Calculate progress and apply curve
|
||||
float progress = elapsedTime / duration;
|
||||
float curveValue = bumpCurve.Evaluate(progress);
|
||||
|
||||
// Interpolate position
|
||||
float currentX = Mathf.Lerp(startX, targetX, curveValue);
|
||||
|
||||
// Apply the position to the player character
|
||||
if (playerCharacter != null)
|
||||
{
|
||||
Vector3 currentPos = playerCharacter.transform.position;
|
||||
playerCharacter.transform.position = new Vector3(currentX, currentPos.y, currentPos.z);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Ensure we end exactly at target
|
||||
if (playerCharacter != null)
|
||||
{
|
||||
Vector3 currentPos = playerCharacter.transform.position;
|
||||
playerCharacter.transform.position = new Vector3(targetX, currentPos.y, currentPos.z);
|
||||
}
|
||||
|
||||
// Bump finished
|
||||
_isBumping = false;
|
||||
_bumpCoroutine = null;
|
||||
|
||||
if (_bumpInputBlocked)
|
||||
{
|
||||
RestoreBumpInput();
|
||||
}
|
||||
|
||||
Debug.Log("[TileBumpCollision] Bump movement completed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores player input after bump movement
|
||||
/// </summary>
|
||||
private void RestoreBumpInput()
|
||||
{
|
||||
if (_bumpInputBlocked && playerController != null)
|
||||
{
|
||||
playerController.enabled = true;
|
||||
_bumpInputBlocked = false;
|
||||
|
||||
// Update the controller's target position to current position to prevent snapping
|
||||
UpdateControllerTarget();
|
||||
|
||||
Debug.Log("[TileBumpCollision] Player input restored after bump");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to handle bump-specific input blocking during immunity
|
||||
/// </summary>
|
||||
protected override void OnImmunityStart()
|
||||
{
|
||||
Debug.Log($"[TileBumpCollision] Damage immunity started for {damageImmunityDuration} seconds");
|
||||
|
||||
// Block input if specified (in addition to any bump input blocking)
|
||||
if (blockInputDuringImmunity && !_bumpInputBlocked)
|
||||
{
|
||||
BlockPlayerInput();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to handle immunity end and bump cleanup
|
||||
/// </summary>
|
||||
protected override void OnImmunityEnd()
|
||||
{
|
||||
base.OnImmunityEnd();
|
||||
|
||||
// Stop any ongoing bump if immunity ends
|
||||
if (_isBumping && _bumpCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_bumpCoroutine);
|
||||
_bumpCoroutine = null;
|
||||
_isBumping = false;
|
||||
|
||||
if (_bumpInputBlocked)
|
||||
{
|
||||
RestoreBumpInput();
|
||||
}
|
||||
|
||||
Debug.Log("[TileBumpCollision] Bump interrupted by immunity end");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when component is destroyed - cleanup coroutines
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_bumpCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_bumpCoroutine);
|
||||
_bumpCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change bump mode at runtime
|
||||
/// </summary>
|
||||
public void SetBumpMode(BumpMode mode)
|
||||
{
|
||||
bumpMode = mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change bump force at runtime
|
||||
/// </summary>
|
||||
public void SetBumpForce(float force)
|
||||
{
|
||||
bumpForce = force;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to change smooth move speed at runtime
|
||||
/// </summary>
|
||||
public void SetSmoothMoveSpeed(float speed)
|
||||
{
|
||||
smoothMoveSpeed = speed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if player is currently being bumped
|
||||
/// </summary>
|
||||
public bool IsBumping => _isBumping;
|
||||
|
||||
/// <summary>
|
||||
/// Check if input is currently blocked by bump
|
||||
/// </summary>
|
||||
public bool IsBumpInputBlocked => _bumpInputBlocked;
|
||||
|
||||
/// <summary>
|
||||
/// Public method to manually stop bump movement
|
||||
/// </summary>
|
||||
public void StopBump()
|
||||
{
|
||||
if (_isBumping && _bumpCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_bumpCoroutine);
|
||||
_bumpCoroutine = null;
|
||||
_isBumping = false;
|
||||
|
||||
if (_bumpInputBlocked)
|
||||
{
|
||||
RestoreBumpInput();
|
||||
}
|
||||
|
||||
Debug.Log("[TileBumpCollision] Bump manually stopped");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8222f0e3aeeb4fc4975aaead6cf7afbe
|
||||
timeCreated: 1758109619
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Serialization;
|
||||
@@ -48,13 +49,31 @@ namespace Minigames.DivingForPictures
|
||||
private float _screenBottom;
|
||||
private float _screenTop;
|
||||
private TrenchTilePool _tilePool;
|
||||
|
||||
// Current velocity for tile movement
|
||||
private float _currentVelocity;
|
||||
|
||||
// Interval for velocity calculations (seconds)
|
||||
[SerializeField] private float velocityCalculationInterval = 0.5f;
|
||||
|
||||
private const float TileSpawnZ = -1f;
|
||||
private const float DefaultTileHeight = 5f;
|
||||
|
||||
// Direction state
|
||||
private bool _isSurfacing = false;
|
||||
private bool _stopSpawning = false;
|
||||
|
||||
// Event triggered when the last tile leaves the screen after stopping spawning
|
||||
public UnityEvent onLastTileLeft = new UnityEvent();
|
||||
|
||||
// Velocity management
|
||||
private float _baseMoveSpeed;
|
||||
private float _velocityFactor = 1.0f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
_baseMoveSpeed = moveSpeed; // Store the original base speed
|
||||
|
||||
// Calculate tile heights for each prefab
|
||||
CalculateTileHeights();
|
||||
@@ -89,15 +108,57 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
CalculateScreenBounds();
|
||||
SpawnInitialTiles();
|
||||
|
||||
// Initialize velocity and start the velocity calculation coroutine
|
||||
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
||||
StartCoroutine(VelocityCalculationRoutine());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
MoveTiles();
|
||||
HandleMovement();
|
||||
HandleTileDestruction();
|
||||
HandleTileSpawning();
|
||||
HandleSpeedRamping();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current velocity of the tiles
|
||||
/// </summary>
|
||||
/// <returns>The current upward velocity of the tiles</returns>
|
||||
public float GetCurrentVelocity()
|
||||
{
|
||||
return _currentVelocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a custom velocity, overriding the calculated one
|
||||
/// </summary>
|
||||
/// <param name="velocity">The new velocity value</param>
|
||||
public void SetVelocity(float velocity)
|
||||
{
|
||||
_currentVelocity = velocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that periodically calculates the velocity based on game state
|
||||
/// </summary>
|
||||
private IEnumerator VelocityCalculationRoutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
CalculateVelocity();
|
||||
yield return new WaitForSeconds(velocityCalculationInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the current velocity based on move speed
|
||||
/// </summary>
|
||||
private void CalculateVelocity()
|
||||
{
|
||||
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate height values for all tile prefabs
|
||||
@@ -170,9 +231,25 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void SpawnInitialTiles()
|
||||
{
|
||||
// Calculate starting Y position - moved 2 tiles up from the bottom of the screen
|
||||
float startingY = _screenBottom;
|
||||
|
||||
// If we have prefab tiles with known heights, use their average height for offset calculation
|
||||
float tileHeightEstimate = DefaultTileHeight;
|
||||
if (tilePrefabs != null && tilePrefabs.Count > 0 && tilePrefabs[0] != null)
|
||||
{
|
||||
if (_tileHeights.TryGetValue(tilePrefabs[0], out float height))
|
||||
{
|
||||
tileHeightEstimate = height;
|
||||
}
|
||||
}
|
||||
|
||||
// Move starting position up by 2 tile heights
|
||||
startingY += tileHeightEstimate * 2;
|
||||
|
||||
for (int i = 0; i < initialTileCount; i++)
|
||||
{
|
||||
float y = _screenBottom;
|
||||
float y = startingY;
|
||||
// Calculate proper Y position based on previous tiles
|
||||
if (i > 0 && _activeTiles.Count > 0)
|
||||
{
|
||||
@@ -206,16 +283,61 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move all active tiles upward
|
||||
/// Called when the velocity factor changes from the DivingGameManager
|
||||
/// </summary>
|
||||
private void MoveTiles()
|
||||
public void OnVelocityFactorChanged(float velocityFactor)
|
||||
{
|
||||
_velocityFactor = velocityFactor;
|
||||
|
||||
// Update the actual move speed based on the velocity factor
|
||||
// This keeps the original move speed intact for game logic
|
||||
moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor);
|
||||
|
||||
// Recalculate velocity immediately
|
||||
CalculateVelocity();
|
||||
|
||||
Debug.Log($"[TrenchTileSpawner] Velocity factor updated to {_velocityFactor:F2}, moveSpeed: {moveSpeed:F2}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverses direction to start surfacing
|
||||
/// </summary>
|
||||
public void StartSurfacing()
|
||||
{
|
||||
if (_isSurfacing) return; // Already surfacing
|
||||
|
||||
// Set surfacing flag for spawn/despawn logic
|
||||
_isSurfacing = true;
|
||||
|
||||
// Reverse the active tiles array to maintain consistent indexing logic
|
||||
_activeTiles.Reverse();
|
||||
|
||||
Debug.Log("[TrenchTileSpawner] Started surfacing - reversed array order");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops spawning new tiles
|
||||
/// </summary>
|
||||
public void StopSpawning()
|
||||
{
|
||||
_stopSpawning = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the movement of all active tiles based on the current velocity
|
||||
/// </summary>
|
||||
private void HandleMovement()
|
||||
{
|
||||
float moveDelta = moveSpeed * Time.deltaTime;
|
||||
foreach (var tile in _activeTiles)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
tile.transform.position += Vector3.up * moveDelta;
|
||||
// Use velocity factor to determine direction
|
||||
Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor);
|
||||
float speed = _currentVelocity;
|
||||
|
||||
// Apply movement
|
||||
tile.transform.position += direction * speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +357,20 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
|
||||
float tileHeight = GetTileHeight(topTile);
|
||||
if (topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer)
|
||||
|
||||
bool shouldDestroy;
|
||||
if (_isSurfacing)
|
||||
{
|
||||
// When surfacing, destroy tiles at the bottom
|
||||
shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When descending, destroy tiles at the top
|
||||
shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
|
||||
}
|
||||
|
||||
if (shouldDestroy)
|
||||
{
|
||||
_activeTiles.RemoveAt(0);
|
||||
onTileDestroyed?.Invoke(topTile);
|
||||
@@ -265,7 +400,15 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void HandleTileSpawning()
|
||||
{
|
||||
if (_activeTiles.Count == 0) return;
|
||||
if (_activeTiles.Count == 0)
|
||||
{
|
||||
// If we have no active tiles and spawning is stopped, trigger the event
|
||||
if (_stopSpawning)
|
||||
{
|
||||
onLastTileLeft.Invoke();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject bottomTile = _activeTiles[^1];
|
||||
if (bottomTile == null)
|
||||
@@ -274,15 +417,60 @@ namespace Minigames.DivingForPictures
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the tile height once to use in all calculations
|
||||
float tileHeight = GetTileHeight(bottomTile);
|
||||
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
||||
if (bottomEdge > _screenBottom - tileSpawnBuffer)
|
||||
|
||||
// If we're in stop spawning mode, don't spawn new tiles
|
||||
if (_stopSpawning)
|
||||
{
|
||||
// Check if this is the last tile, and if it's about to leave the screen
|
||||
if (_activeTiles.Count == 1)
|
||||
{
|
||||
bool isLastTileLeaving;
|
||||
|
||||
if (_isSurfacing)
|
||||
{
|
||||
// When surfacing, check if the bottom of the tile is above the top of the screen
|
||||
isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When descending, check if the top of the tile is below the bottom of the screen
|
||||
isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
|
||||
}
|
||||
|
||||
if (isLastTileLeaving)
|
||||
{
|
||||
onLastTileLeft.Invoke();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldSpawn;
|
||||
float newY;
|
||||
|
||||
if (_isSurfacing)
|
||||
{
|
||||
// When surfacing, spawn new tiles at the top
|
||||
float topEdge = bottomTile.transform.position.y + tileHeight / 2;
|
||||
shouldSpawn = topEdge < _screenTop + tileSpawnBuffer;
|
||||
newY = bottomTile.transform.position.y + tileHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When descending, spawn new tiles at the bottom
|
||||
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
||||
shouldSpawn = bottomEdge > _screenBottom - tileSpawnBuffer;
|
||||
newY = bottomTile.transform.position.y - tileHeight;
|
||||
}
|
||||
|
||||
if (shouldSpawn)
|
||||
{
|
||||
float newY = bottomTile.transform.position.y - tileHeight;
|
||||
SpawnTileAtY(newY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handle increasing the movement speed over time
|
||||
/// </summary>
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Pooling
|
||||
/// <returns>An object ready to use</returns>
|
||||
public virtual T Get(int prefabIndex)
|
||||
{
|
||||
T obj;
|
||||
T obj = null;
|
||||
|
||||
// Track usage frequency
|
||||
if (prefabUsageCount.ContainsKey(prefabIndex))
|
||||
@@ -112,27 +112,71 @@ namespace Pooling
|
||||
prefabUsageCount[prefabIndex] = 1;
|
||||
}
|
||||
|
||||
// Try to get a valid object from the pool, cleaning up any destroyed objects
|
||||
if (pooledObjects.ContainsKey(prefabIndex) && pooledObjects[prefabIndex].Count > 0)
|
||||
{
|
||||
obj = pooledObjects[prefabIndex].Pop();
|
||||
totalPooledCount--;
|
||||
Debug.Log($"[{GetType().Name}] Found {pooledObjects[prefabIndex].Count} objects in pool for prefab index {prefabIndex}");
|
||||
|
||||
// Keep trying until we find a valid object or the pool is empty
|
||||
while (pooledObjects[prefabIndex].Count > 0)
|
||||
{
|
||||
obj = pooledObjects[prefabIndex].Pop();
|
||||
totalPooledCount--;
|
||||
|
||||
// Check if the object is still valid (not destroyed)
|
||||
if (obj != null && obj.gameObject != null)
|
||||
{
|
||||
Debug.Log($"[{GetType().Name}] Retrieved valid object {obj.name} from pool, current active state: {obj.gameObject.activeInHierarchy}");
|
||||
break; // Found a valid object
|
||||
}
|
||||
else
|
||||
{
|
||||
// Object was destroyed, continue looking
|
||||
Debug.LogWarning($"[{GetType().Name}] Found destroyed object in pool, removing it");
|
||||
obj = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create new object without adding to pool
|
||||
T prefab = prefabs[prefabIndex];
|
||||
obj = Instantiate(prefab, transform);
|
||||
Debug.Log($"[{GetType().Name}] No objects in pool for prefab index {prefabIndex}, creating new one");
|
||||
}
|
||||
|
||||
// If we couldn't find a valid object in the pool, create a new one
|
||||
if (obj == null)
|
||||
{
|
||||
T prefab = prefabs[prefabIndex];
|
||||
obj = Instantiate(prefab, transform);
|
||||
Debug.Log($"[{GetType().Name}] Created new object {obj.name} from prefab, active state: {obj.gameObject.activeInHierarchy}");
|
||||
}
|
||||
|
||||
// Ensure the object is valid before proceeding
|
||||
if (obj == null || obj.gameObject == null)
|
||||
{
|
||||
Debug.LogError($"[{GetType().Name}] Failed to create valid object for prefab index {prefabIndex}");
|
||||
return null;
|
||||
}
|
||||
|
||||
// CRITICAL FIX: Reset position to safe location BEFORE activation
|
||||
// This prevents off-screen checks from triggering during spawn process
|
||||
Vector3 originalPosition = obj.transform.position;
|
||||
obj.transform.position = new Vector3(0f, -1000f, 0f);
|
||||
Debug.Log($"[{GetType().Name}] Moved object {obj.name} from {originalPosition} to safe position before activation");
|
||||
|
||||
Debug.Log($"[{GetType().Name}] About to activate object {obj.name}, current state: {obj.gameObject.activeInHierarchy}");
|
||||
obj.gameObject.SetActive(true);
|
||||
Debug.Log($"[{GetType().Name}] After SetActive(true), object {obj.name} state: {obj.gameObject.activeInHierarchy}");
|
||||
|
||||
// Call OnSpawn for IPoolable components
|
||||
IPoolable poolable = obj.GetComponent<IPoolable>();
|
||||
if (poolable != null)
|
||||
{
|
||||
Debug.Log($"[{GetType().Name}] Calling OnSpawn for object {obj.name}");
|
||||
poolable.OnSpawn();
|
||||
Debug.Log($"[{GetType().Name}] After OnSpawn, object {obj.name} state: {obj.gameObject.activeInHierarchy}");
|
||||
}
|
||||
|
||||
Debug.Log($"[{GetType().Name}] Returning object {obj.name} with final state: {obj.gameObject.activeInHierarchy}");
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -152,33 +196,61 @@ namespace Pooling
|
||||
poolable.OnDespawn();
|
||||
}
|
||||
|
||||
// Check if we're under the maximum pool size for this prefab type
|
||||
bool keepObject = totalPooledCount < totalMaxPoolSize;
|
||||
// Always deactivate and parent the object
|
||||
obj.gameObject.SetActive(false);
|
||||
obj.transform.SetParent(transform);
|
||||
|
||||
// Additional constraint: don't keep too many of any single prefab type
|
||||
if (pooledObjects.ContainsKey(prefabIndex) &&
|
||||
pooledObjects[prefabIndex].Count >= maxPerPrefabPoolSize)
|
||||
// Initialize stack if it doesn't exist
|
||||
if (!pooledObjects.ContainsKey(prefabIndex))
|
||||
{
|
||||
keepObject = false;
|
||||
pooledObjects[prefabIndex] = new Stack<T>();
|
||||
}
|
||||
|
||||
if (keepObject)
|
||||
// Check if we need to trim this specific prefab type's pool
|
||||
if (pooledObjects[prefabIndex].Count >= maxPerPrefabPoolSize)
|
||||
{
|
||||
obj.gameObject.SetActive(false);
|
||||
obj.transform.SetParent(transform);
|
||||
|
||||
if (!pooledObjects.ContainsKey(prefabIndex))
|
||||
// Remove the oldest object from this prefab's pool to make room
|
||||
if (pooledObjects[prefabIndex].Count > 0)
|
||||
{
|
||||
pooledObjects[prefabIndex] = new Stack<T>();
|
||||
T oldestObj = pooledObjects[prefabIndex].Pop();
|
||||
if (oldestObj != null && oldestObj.gameObject != null)
|
||||
{
|
||||
Destroy(oldestObj.gameObject);
|
||||
totalPooledCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check global pool limit
|
||||
if (totalPooledCount >= totalMaxPoolSize)
|
||||
{
|
||||
// Find the prefab type with the most pooled objects and remove one
|
||||
int maxCount = 0;
|
||||
int prefabToTrim = -1;
|
||||
|
||||
foreach (var kvp in pooledObjects)
|
||||
{
|
||||
if (kvp.Value.Count > maxCount)
|
||||
{
|
||||
maxCount = kvp.Value.Count;
|
||||
prefabToTrim = kvp.Key;
|
||||
}
|
||||
}
|
||||
|
||||
pooledObjects[prefabIndex].Push(obj);
|
||||
totalPooledCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(obj.gameObject);
|
||||
if (prefabToTrim >= 0 && pooledObjects[prefabToTrim].Count > 0)
|
||||
{
|
||||
T oldestObj = pooledObjects[prefabToTrim].Pop();
|
||||
if (oldestObj != null && oldestObj.gameObject != null)
|
||||
{
|
||||
Destroy(oldestObj.gameObject);
|
||||
totalPooledCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the current object to the pool
|
||||
pooledObjects[prefabIndex].Push(obj);
|
||||
totalPooledCount++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@ TagManager:
|
||||
tags:
|
||||
- CharacterArt
|
||||
- Pulver
|
||||
- Rock
|
||||
layers:
|
||||
- Default
|
||||
- TransparentFX
|
||||
@@ -18,8 +19,8 @@ TagManager:
|
||||
- Pulver
|
||||
- WorldBoundary
|
||||
- Interactable
|
||||
-
|
||||
-
|
||||
- QuarryObstacle
|
||||
- QuarryMonster
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user