auto: 2026-11-10 23:22 · scene: Lobby · 64 files

This commit is contained in:
깃 관리자 2026-11-10 23:22:51 +09:00
parent dd10b1f8bd
commit 49f65339aa
64 changed files with 3721 additions and 83 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fa75e2ac0f9004042beb1fd0e63db5b7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!221 &22100000
AnimatorOverrideController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Hero2
m_Controller: {fileID: 9100000, guid: b09e60546065cf9448b36ebb7f759a91, type: 2}
m_Clips:
- m_OriginalClip: {fileID: 7400000, guid: 712f4510fc9b249348d4d8e97b12dc45, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 337bb548869a6b445b5613c7dfb922da, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: 56811a918221743d69fe84599f43c740, type: 2}
m_OverrideClip: {fileID: 7400000, guid: c75d6c9ba53c4a544b2994a888fb6357, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: 1d7e02f8cf5ba47a78bc1e19cc378478, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 5664346396fe1d84a9dec390673543b9, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: e0e8baec160e44e1bb74ca8e08777453, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 337bb548869a6b445b5613c7dfb922da, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: c8d7e5a1f9b24e63a7f5d2c8e1b9a4f7, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 34f88233ac11b9149acad25af534d4cc, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: a1b2c3d4e5f6789012345678abcdef01, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 337bb548869a6b445b5613c7dfb922da, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: b2c3d4e5f6789012345678abcdef0102, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 0fb79f0ef462be243aa5a4d2b6aa4f89, type: 2}
- m_OriginalClip: {fileID: 7400000, guid: c3d4e5f6789012345678abcdef010203, type: 2}
m_OverrideClip: {fileID: 7400000, guid: 337bb548869a6b445b5613c7dfb922da, type: 2}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7dc53f5b013ff8d49a65bc6d14f88cbf
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 22100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Hero2_Attack
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 21300000, guid: 13af56d1c9bf3004c9addcdecece8d5c, type: 3}
- time: 0.08
value: {fileID: 21300000, guid: b28a21fabdc7f264fa4b7b80bacb2af5, type: 3}
- time: 0.18
value: {fileID: 21300000, guid: a44382e766c8c5e4c92f95f4bd151c0d, type: 3}
- time: 0.32
value: {fileID: 21300000, guid: a44382e766c8c5e4c92f95f4bd151c0d, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 21300000, guid: 13af56d1c9bf3004c9addcdecece8d5c, type: 3}
- {fileID: 21300000, guid: b28a21fabdc7f264fa4b7b80bacb2af5, type: 3}
- {fileID: 21300000, guid: a44382e766c8c5e4c92f95f4bd151c0d, type: 3}
- {fileID: 21300000, guid: a44382e766c8c5e4c92f95f4bd151c0d, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.33666667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 34f88233ac11b9149acad25af534d4cc
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,75 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Hero2_Hit
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 21300000, guid: 558d57f72e084f04aae4c0f5b58512fb, type: 3}
- time: 0.2
value: {fileID: 21300000, guid: 558d57f72e084f04aae4c0f5b58512fb, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 21300000, guid: 558d57f72e084f04aae4c0f5b58512fb, type: 3}
- {fileID: 21300000, guid: 558d57f72e084f04aae4c0f5b58512fb, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.21666667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0fb79f0ef462be243aa5a4d2b6aa4f89
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,75 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Hero2_Jump
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 21300000, guid: 64d67bc6c8db2674bb3b0c8df377bcdf, type: 3}
- time: 0.083233334
value: {fileID: 21300000, guid: 64d67bc6c8db2674bb3b0c8df377bcdf, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 21300000, guid: 64d67bc6c8db2674bb3b0c8df377bcdf, type: 3}
- {fileID: 21300000, guid: 64d67bc6c8db2674bb3b0c8df377bcdf, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.0999
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5664346396fe1d84a9dec390673543b9
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,90 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Hero2_Run
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
- time: 0.083333336
value: {fileID: 21300000, guid: 558d57f72e084f04aae4c0f5b58512fb, type: 3}
- time: 0.16666667
value: {fileID: 21300000, guid: a463912fc4688394aab70774bae5ef40, type: 3}
- time: 0.25
value: {fileID: 21300000, guid: 64d67bc6c8db2674bb3b0c8df377bcdf, type: 3}
- time: 0.33333334
value: {fileID: 21300000, guid: dd92421615ecd394b91c5558f6d7c833, type: 3}
- time: 0.4166667
value: {fileID: 21300000, guid: 52fc79783d2c1e241b0b9e2444ea9579, type: 3}
- time: 0.4999
value: {fileID: 21300000, guid: 52fc79783d2c1e241b0b9e2444ea9579, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
- {fileID: 21300000, guid: 558d57f72e084f04aae4c0f5b58512fb, type: 3}
- {fileID: 21300000, guid: a463912fc4688394aab70774bae5ef40, type: 3}
- {fileID: 21300000, guid: 64d67bc6c8db2674bb3b0c8df377bcdf, type: 3}
- {fileID: 21300000, guid: dd92421615ecd394b91c5558f6d7c833, type: 3}
- {fileID: 21300000, guid: 52fc79783d2c1e241b0b9e2444ea9579, type: 3}
- {fileID: 21300000, guid: 52fc79783d2c1e241b0b9e2444ea9579, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.5165667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c75d6c9ba53c4a544b2994a888fb6357
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,75 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Hero2_Still
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
- time: 0.1
value: {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
- {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0.11666667
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 337bb548869a6b445b5613c7dfb922da
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: baa8597614350e84f9176635e9f6c8a8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: 13af56d1c9bf3004c9addcdecece8d5c
TextureImporter:
internalIDToNameTable:
- first:
213: 6135626975730281620
second: hero2_attack_01_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_attack_01_0
rect:
serializedVersion: 2
x: 53
y: 7
width: 162
height: 215
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 49c25baf930262550800000000000000
internalID: 6135626975730281620
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_attack_01_0: 6135626975730281620
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: b28a21fabdc7f264fa4b7b80bacb2af5
TextureImporter:
internalIDToNameTable:
- first:
213: -4555075445918632043
second: hero2_attack_02_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_attack_02_0
rect:
serializedVersion: 2
x: 41
y: 7
width: 193
height: 210
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 5977ae8040f19c0c0800000000000000
internalID: -4555075445918632043
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_attack_02_0: -4555075445918632043
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: a44382e766c8c5e4c92f95f4bd151c0d
TextureImporter:
internalIDToNameTable:
- first:
213: -6164578762513089740
second: hero2_attack_03_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_attack_03_0
rect:
serializedVersion: 2
x: 4
y: 7
width: 215
height: 208
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 43b7d7ed644037aa0800000000000000
internalID: -6164578762513089740
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_attack_03_0: -6164578762513089740
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,50 @@
{
"note": "Hero2 import SOT — finalize_frames.py 산출 (2026-11-10)",
"canvas": [
254,
234
],
"anchor_px_from_top_left": [
129.8,
225.0
],
"ppu": 205,
"old_visible_height_px": 313.5,
"old_ppu": 300.0,
"new_visible_height_px": 214.0,
"clips": {
"run": {
"frames": [
"hero2_run_01",
"hero2_run_02",
"hero2_run_03",
"hero2_run_04",
"hero2_run_05",
"hero2_run_06"
],
"fps": 12,
"loop": true
},
"attack": {
"frames": [
"hero2_attack_01",
"hero2_attack_02",
"hero2_attack_03"
],
"times": [
0.0,
0.08,
0.18
],
"length": 0.32,
"loop": false
},
"jump": {
"frames": [
"hero2_run_04"
],
"fps": 12,
"loop": true
}
}
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2a10a7a14aaaf234296ef8cef13288f4
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: d0ef15db1d7cfe942833a436e709d5de
TextureImporter:
internalIDToNameTable:
- first:
213: 4594355425956087001
second: hero2_run_01_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_run_01_0
rect:
serializedVersion: 2
x: 34
y: 5
width: 197
height: 224
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 9d440000bed62cf30800000000000000
internalID: 4594355425956087001
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_run_01_0: 4594355425956087001
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: 558d57f72e084f04aae4c0f5b58512fb
TextureImporter:
internalIDToNameTable:
- first:
213: -8171492585566603228
second: hero2_run_02_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_run_02_0
rect:
serializedVersion: 2
x: 30
y: 7
width: 214
height: 216
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 4287090b9c6099e80800000000000000
internalID: -8171492585566603228
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_run_02_0: -8171492585566603228
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: a463912fc4688394aab70774bae5ef40
TextureImporter:
internalIDToNameTable:
- first:
213: -7297110809570715322
second: hero2_run_03_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_run_03_0
rect:
serializedVersion: 2
x: 30
y: 7
width: 214
height: 216
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 649dfd461647bba90800000000000000
internalID: -7297110809570715322
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_run_03_0: -7297110809570715322
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: 64d67bc6c8db2674bb3b0c8df377bcdf
TextureImporter:
internalIDToNameTable:
- first:
213: 4643626016116899493
second: hero2_run_04_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_run_04_0
rect:
serializedVersion: 2
x: 28
y: 13
width: 221
height: 216
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 5aef8683249717040800000000000000
internalID: 4643626016116899493
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_run_04_0: 4643626016116899493
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: dd92421615ecd394b91c5558f6d7c833
TextureImporter:
internalIDToNameTable:
- first:
213: -4788721669207052375
second: hero2_run_05_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_run_05_0
rect:
serializedVersion: 2
x: 31
y: 7
width: 203
height: 214
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 9afa2ba730b0b8db0800000000000000
internalID: -4788721669207052375
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_run_05_0: -4788721669207052375
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: 52fc79783d2c1e241b0b9e2444ea9579
TextureImporter:
internalIDToNameTable:
- first:
213: 2364528057764446928
second: hero2_run_06_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: 1
spriteExtrude: 1
spriteMeshType: 0
alignment: 9
spritePivot: {x: 0.51102364, y: 0.3984499}
spritePixelsToUnits: 205
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: 2
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: 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: hero2_run_06_0
rect:
serializedVersion: 2
x: 33
y: 5
width: 198
height: 219
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 0d28e70adbd70d020800000000000000
internalID: 2364528057764446928
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
hero2_run_06_0: 2364528057764446928
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 59d58f08c16a66b459625dd4537d0251
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,138 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using EerieVillage.Background;
using Unity.Cinemachine;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
/// <summary>
/// 리뉴얼 2026-11-10 (PD 지시) — ComfyUI 로 만든 이음매 없는 마을 배경(2층)을 Ingame 씬에 무한 스크롤로 깐다.
/// 층 정보 SOT = Assets/Environment/Backdrop/backdrop_layers.json (make_layers.py 산출 · 파일 · 높이 px · 발 디딤선 · 시차 · 정렬).
/// 배율(px/월드)은 씬의 실제 땅 높이 · 카메라 범위에서 계산한다(값 중복 없음).
/// </summary>
public static class BackdropRenewalSetup
{
const string Dir = "Assets/Environment/Backdrop";
const string ScenePath = "Assets/Scenes/Ingame.unity";
const string RootName = "Backdrop_EerieVillage";
[System.Serializable] class Layer { public string file; public float height_px; public float walk_v; public float parallax; public int sorting_order; }
[System.Serializable] class Layers { public Layer far, ground; }
[System.Serializable] class Cfg { public float tile_width_px; public Layers layers; public float camera_margin_world; }
static Cfg LoadCfg() => JsonUtility.FromJson<Cfg>(File.ReadAllText(Path.Combine(Dir, "backdrop_layers.json")));
[MenuItem("Tools/Renewal/4. Backdrop Import Settings")]
public static string ImportTexture()
{
var cfg = LoadCfg();
var log = new List<string>();
foreach (var l in new[] { cfg.layers.far, cfg.layers.ground })
{
string path = $"{Dir}/{l.file}";
var ti = (TextureImporter)AssetImporter.GetAtPath(path);
ti.textureType = TextureImporterType.Sprite;
ti.spriteImportMode = SpriteImportMode.Single;
var s = new TextureImporterSettings();
ti.ReadTextureSettings(s);
s.spriteAlignment = (int)SpriteAlignment.Center;
s.spriteMeshType = SpriteMeshType.FullRect;
s.mipmapEnabled = false;
s.wrapMode = TextureWrapMode.Clamp;
s.filterMode = FilterMode.Bilinear;
s.alphaIsTransparency = true;
ti.SetTextureSettings(s);
ti.maxTextureSize = 4096;
ti.textureCompression = TextureImporterCompression.CompressedHQ;
ti.SaveAndReimport();
var sp = AssetDatabase.LoadAssetAtPath<Sprite>(path);
log.Add($"{l.file} {sp?.rect.width}x{sp?.rect.height}");
}
return string.Join(" | ", log);
}
/// <summary>현재 열린 씬의 기존 배경 후보(무한 배경·패럴랙스·이름에 Background) 목록.</summary>
public static string ListOldBackgrounds()
{
var rows = new List<string>();
foreach (var go in Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None).Select(t => t.gameObject))
{
bool hit = go.GetComponent<InfiniteHorizontalBackground>() || go.GetComponent<InfiniteHorizontalGround>() || go.GetComponent<CameraBackgroundLimit>()
|| go.GetComponent("ParallaxLayer") || go.name.ToLower().Contains("background") || go.name.ToLower().Contains("bg");
if (!hit) continue;
var sr = go.GetComponent<Renderer>();
string comps = string.Join(",", go.GetComponents<Component>().Where(c => c != null && !(c is Transform)).Select(c => c.GetType().Name));
rows.Add($"{GetPath(go.transform)} [{(go.activeInHierarchy ? "on" : "off")}] {comps}" +
(sr ? $" layer={sr.sortingLayerName}/{sr.sortingOrder}" : ""));
}
return string.Join("\n", rows);
}
static string GetPath(Transform t) => t.parent == null ? t.name : GetPath(t.parent) + "/" + t.name;
/// <summary>
/// 배경 2층을 만들고(있으면 갱신) 지정한 기존 배경 오브젝트는 끈다. 씬 저장까지.
/// 배율 = 먼 층 위 끝이 카메라 최고 높이를, 흙길 층 아래 끝이 카메라 최저 높이를 덮는 가장 작은 배경 크기.
/// </summary>
public static string SetupScene(string[] disablePaths)
{
var scene = EditorSceneManager.GetActiveScene();
if (scene.path != ScenePath) scene = EditorSceneManager.OpenScene(ScenePath);
var cfg = LoadCfg();
var log = new List<string>();
foreach (var p in disablePaths)
{
var go = Object.FindObjectsByType<Transform>(FindObjectsInactive.Include, FindObjectsSortMode.None)
.Select(t => t.gameObject).FirstOrDefault(g => GetPath(g.transform) == p);
if (go == null) { log.Add($"없음: {p}"); continue; }
Undo.RecordObject(go, "Disable old background");
go.SetActive(false);
log.Add($"끔: {p}");
}
// 실제 땅 윗면(무한 지면 콜라이더) · 카메라 세로 범위(시작 높이 · Confiner 위 끝)
var ground = Object.FindFirstObjectByType<InfiniteHorizontalGround>();
float groundY = ground.GetComponent<BoxCollider2D>().bounds.max.y;
var cam = Camera.main;
float camBottom = cam.transform.position.y - cam.orthographicSize;
float camTop = cam.transform.position.y + cam.orthographicSize;
var confiner = Object.FindFirstObjectByType<CinemachineConfiner2D>();
if (confiner != null && confiner.BoundingShape2D is PolygonCollider2D poly && poly.enabled)
camTop = Mathf.Max(camTop, poly.bounds.max.y);
float m = cfg.camera_margin_world;
var far = cfg.layers.far; var gnd = cfg.layers.ground;
float kTop = far.height_px * (1f - far.walk_v) / (camTop - groundY + m);
float kBottom = gnd.height_px * gnd.walk_v / (groundY - camBottom + m);
float k = Mathf.Min(kTop, kBottom);
log.Add($"땅 {groundY:F2} · 카메라 {camBottom:F2}~{camTop:F2} · px/월드 {k:F1} (위 {kTop:F1} · 아래 {kBottom:F1})");
MakeLayer(RootName, far, k, groundY, cam, log);
MakeLayer(RootName + "_Ground", gnd, k, groundY, cam, log);
EditorSceneManager.MarkSceneDirty(scene);
EditorSceneManager.SaveScene(scene);
return string.Join("\n", log);
}
static void MakeLayer(string goName, Layer l, float k, float groundY, Camera cam, List<string> log)
{
var root = GameObject.Find(goName);
if (root == null) root = new GameObject(goName);
root.transform.position = new Vector3(cam.transform.position.x, groundY, 10f);
var sr = root.GetComponent<SpriteRenderer>();
if (sr == null) sr = root.AddComponent<SpriteRenderer>();
sr.sprite = AssetDatabase.LoadAssetAtPath<Sprite>($"{Dir}/{l.file}");
sr.sortingLayerName = "Default";
sr.sortingOrder = l.sorting_order;
var lb = root.GetComponent<LoopingBackdrop>();
if (lb == null) lb = root.AddComponent<LoopingBackdrop>();
lb.parallax = l.parallax;
lb.pixelsPerWorldUnit = k;
lb.anchorImageV = l.walk_v;
lb.anchorWorldY = groundY;
lb.verticalFollow = 0f;
EditorUtility.SetDirty(lb);
log.Add($"{goName}: {l.file} 시차 {l.parallax} 정렬 {l.sorting_order} 높이 {l.height_px / k:F2}");
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c0696e3a558af1d4bba5b045880ef303

View File

@ -0,0 +1,171 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Platformer.Gameplay;
using Platformer.Mechanics;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
/// <summary>
/// 리뉴얼 2026-11-10 (PD 지시) — 새 캐릭터(Hero2) 스프라이트 교체 + 근접 자동 공격 부착.
/// 값 SOT = Assets/Character/Sprites/Hero2/hero2_import.json (finalize_frames.py 산출 · 캔버스·기준점·PPU·클립 구성).
/// 발 위치 = Player 프리팹 콜라이더 바닥에서 계산(값 중복 없음).
/// </summary>
public static class Hero2RenewalSetup
{
const string Hero2Dir = "Assets/Character/Sprites/Hero2";
const string ClipDir = "Assets/Character/Animations/Hero2";
const string PlayerPrefab = "Assets/Prefabs/Player.prefab";
const string BaseController = "Assets/Character/Animations/Player.controller";
const string OverridePath = "Assets/Character/Animations/Hero2/Hero2.overrideController";
[System.Serializable] class ClipCfg { public string[] frames; public float fps; public bool loop; public float[] times; public float length; }
[System.Serializable] class ClipSet { public ClipCfg run, attack, jump; }
[System.Serializable] class ImportCfg { public int[] canvas; public float[] anchor_px_from_top_left; public float ppu; public ClipSet clips; }
static ImportCfg LoadCfg() => JsonUtility.FromJson<ImportCfg>(File.ReadAllText(Path.Combine(Hero2Dir, "hero2_import.json")));
/// <summary>프리팹 콜라이더 바닥(로컬 y, 스케일 적용 전).</summary>
static float ColliderBottomLocal(GameObject root)
{
var box = root.GetComponent<BoxCollider2D>();
if (box != null) return box.offset.y - box.size.y * 0.5f - box.edgeRadius;
var cap = root.GetComponent<CapsuleCollider2D>();
if (cap != null) return cap.offset.y - cap.size.y * 0.5f;
var circle = root.GetComponent<CircleCollider2D>();
if (circle != null) return circle.offset.y - circle.radius;
throw new System.Exception("Player 콜라이더를 찾지 못함");
}
[MenuItem("Tools/Renewal/1. Hero2 Import Settings")]
public static string ImportSprites()
{
var cfg = LoadCfg();
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefab);
float feetLocal = ColliderBottomLocal(prefab);
float W = cfg.canvas[0], H = cfg.canvas[1];
float ax = cfg.anchor_px_from_top_left[0], ay = cfg.anchor_px_from_top_left[1];
// 발 픽셀 행(ay, 위에서) 이 콜라이더 바닥(feetLocal) 에 오도록 기준점 y 를 정한다.
var pivot = new Vector2(ax / W, (H - ay - feetLocal * cfg.ppu) / H);
int n = 0;
foreach (var guid in AssetDatabase.FindAssets("t:Texture2D", new[] { Hero2Dir }))
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var ti = (TextureImporter)AssetImporter.GetAtPath(path);
ti.textureType = TextureImporterType.Sprite;
ti.spriteImportMode = SpriteImportMode.Single;
var s = new TextureImporterSettings();
ti.ReadTextureSettings(s);
s.spriteAlignment = (int)SpriteAlignment.Custom;
s.spritePivot = pivot;
s.spritePixelsPerUnit = cfg.ppu;
s.spriteMeshType = SpriteMeshType.FullRect;
s.alphaIsTransparency = true;
s.mipmapEnabled = false;
s.filterMode = FilterMode.Bilinear;
s.wrapMode = TextureWrapMode.Clamp;
ti.SetTextureSettings(s);
ti.textureCompression = TextureImporterCompression.CompressedHQ;
ti.SaveAndReimport();
n++;
}
return $"import {n} sprites · ppu {cfg.ppu} · pivot {pivot.x:F4},{pivot.y:F4} · feetLocal {feetLocal:F4}";
}
static Sprite S(string name) => AssetDatabase.LoadAssetAtPath<Sprite>($"{Hero2Dir}/{name}.png");
static AnimationClip MakeClip(string clipName, string[] frames, float[] times, float length, bool loop)
{
Directory.CreateDirectory(ClipDir);
string path = $"{ClipDir}/{clipName}.anim";
var clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(path);
if (clip == null) { clip = new AnimationClip { frameRate = 60 }; AssetDatabase.CreateAsset(clip, path); }
clip.ClearCurves();
var binding = EditorCurveBinding.PPtrCurve("", typeof(SpriteRenderer), "m_Sprite");
var keys = new List<ObjectReferenceKeyframe>();
for (int i = 0; i < frames.Length; i++) keys.Add(new ObjectReferenceKeyframe { time = times[i], value = S(frames[i]) });
// 마지막 프레임을 끝 시각까지 유지(클립 길이 = length)
keys.Add(new ObjectReferenceKeyframe { time = length, value = S(frames[frames.Length - 1]) });
AnimationUtility.SetObjectReferenceCurve(clip, binding, keys.ToArray());
var st = AnimationUtility.GetAnimationClipSettings(clip);
st.loopTime = loop;
AnimationUtility.SetAnimationClipSettings(clip, st);
EditorUtility.SetDirty(clip);
return clip;
}
static AnimationClip MakeFpsClip(string clipName, ClipCfg c)
{
float dt = 1f / c.fps;
var times = Enumerable.Range(0, c.frames.Length).Select(i => i * dt).ToArray();
// 반복 클립은 마지막 키를 한 칸 뒤(= 첫 프레임 직전)에 두어 모든 프레임이 같은 시간 보이게 한다.
return MakeClip(clipName, c.frames, times, c.frames.Length * dt - (c.loop ? 0.0001f : 0f), c.loop);
}
[MenuItem("Tools/Renewal/2. Hero2 Clips + Override")]
public static string BuildAnimation()
{
var cfg = LoadCfg();
var run = MakeFpsClip("Hero2_Run", cfg.clips.run);
var attack = MakeClip("Hero2_Attack", cfg.clips.attack.frames, cfg.clips.attack.times, cfg.clips.attack.length, false);
var jump = MakeFpsClip("Hero2_Jump", cfg.clips.jump);
// 대기·피격·사망·부활 전용 그림은 아직 없다 → 달리기 첫 프레임 정지 그림으로 대신(보고에 명시).
var still = MakeClip("Hero2_Still", new[] { cfg.clips.run.frames[0] }, new[] { 0f }, 0.1f, true);
var hit = MakeClip("Hero2_Hit", new[] { cfg.clips.run.frames[1] }, new[] { 0f }, 0.2f, false);
var baseCtrl = AssetDatabase.LoadAssetAtPath<AnimatorController>(BaseController);
var ov = AssetDatabase.LoadAssetAtPath<AnimatorOverrideController>(OverridePath);
if (ov == null) { ov = new AnimatorOverrideController(baseCtrl); AssetDatabase.CreateAsset(ov, OverridePath); }
ov.runtimeAnimatorController = baseCtrl;
var byState = new Dictionary<string, AnimationClip>
{
{ "Player-Run", run }, { "Player-Attack", attack }, { "Player-Jump", jump },
{ "Player-Idle", still }, { "Player-CombatIdle", still }, { "Player-Hit", hit },
{ "Player-Death", still }, { "Player-Resurrection", still },
};
var pairs = new List<KeyValuePair<AnimationClip, AnimationClip>>();
var log = new List<string>();
foreach (var cs in baseCtrl.layers[0].stateMachine.states)
{
var orig = cs.state.motion as AnimationClip;
if (orig == null) { log.Add($"{cs.state.name}: (클립 아님)"); continue; }
if (byState.TryGetValue(cs.state.name, out var nc)) { pairs.Add(new KeyValuePair<AnimationClip, AnimationClip>(orig, nc)); log.Add($"{cs.state.name}: {orig.name}->{nc.name}"); }
else log.Add($"{cs.state.name}: {orig.name} (그대로)");
}
ov.ApplyOverrides(pairs);
EditorUtility.SetDirty(ov);
AssetDatabase.SaveAssets();
return string.Join(" | ", log);
}
[MenuItem("Tools/Renewal/3. Apply Hero2 To Player Prefab")]
public static string ApplyToPrefab()
{
var root = PrefabUtility.LoadPrefabContents(PlayerPrefab);
try
{
var cfg = LoadCfg();
var sr = root.GetComponent<SpriteRenderer>();
sr.sprite = S(cfg.clips.run.frames[0]);
var anim = root.GetComponent<Animator>();
anim.runtimeAnimatorController = AssetDatabase.LoadAssetAtPath<AnimatorOverrideController>(OverridePath);
var pc = root.GetComponent<PlayerController>();
pc.autoRun = true;
var ticker = root.GetComponent<PlayerAttackTicker>();
if (ticker == null) ticker = root.AddComponent<PlayerAttackTicker>();
ticker.onlyWhenEnemyNear = true;
if (pc.attackHitbox == null) pc.attackHitbox = root.GetComponent<AttackHitbox>();
PrefabUtility.SaveAsPrefabAsset(root, PlayerPrefab);
}
finally { PrefabUtility.UnloadPrefabContents(root); }
// 기본 그림은 프리팹 편집 장면에서 저장되지 않는 경우가 있어(2026-11-10 실측) 에셋에 직접 한 번 더 넣는다.
var asset = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefab);
var assetSr = asset.GetComponent<SpriteRenderer>();
var first = S(LoadCfg().clips.run.frames[0]);
if (assetSr.sprite != first) { assetSr.sprite = first; EditorUtility.SetDirty(asset); PrefabUtility.SavePrefabAsset(asset); }
var a2 = asset.GetComponent<Animator>();
return $"prefab ok · sprite {assetSr.sprite?.name} · ctrl {a2.runtimeAnimatorController?.name} · ticker {asset.GetComponent<PlayerAttackTicker>() != null}";
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 973c500806fa393478207d518219c68b

View File

@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Linq;
using Platformer.Mechanics;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
/// <summary>
/// 리뉴얼 2026-11-10 (PD 지시 「무한 스크롤 중 적은 새로 스크롤되는 화면에 랜덤 등장」) —
/// Ingame 씬의 미리 놓인 적을 끄고 무한 적 생성기를 둔다. 생성 프리팹 = 미리 놓인 적들의 원본 프리팹.
/// </summary>
public static class RunnerRenewalSetup
{
const string ScenePath = "Assets/Scenes/Ingame.unity";
const string SpawnerName = "EnemySpawner_Endless";
[MenuItem("Tools/Renewal/5. Endless Enemy Spawner")]
public static string SetupSpawner()
{
var scene = EditorSceneManager.GetActiveScene();
if (scene.path != ScenePath) scene = EditorSceneManager.OpenScene(ScenePath);
var enemies = Object.FindObjectsByType<EnemyController>(FindObjectsInactive.Include, FindObjectsSortMode.None);
var sources = new Dictionary<string, int>();
var prefabs = new List<GameObject>();
foreach (var e in enemies)
{
var src = PrefabUtility.GetCorrespondingObjectFromSource(e.gameObject);
string path = src != null ? AssetDatabase.GetAssetPath(src) : "(프리팹 아님)";
sources[path] = sources.TryGetValue(path, out var n) ? n + 1 : 1;
if (src != null && !prefabs.Contains(src)) prefabs.Add(src);
Undo.RecordObject(e.gameObject, "Disable placed enemy");
e.gameObject.SetActive(false);
}
var root = GameObject.Find(SpawnerName);
if (root == null) root = new GameObject(SpawnerName);
var sp = root.GetComponent<EndlessEnemySpawner>();
if (sp == null) sp = root.AddComponent<EndlessEnemySpawner>();
sp.enemyPrefabs = prefabs.OrderBy(p => p.name).ToArray();
EditorUtility.SetDirty(sp);
EditorSceneManager.MarkSceneDirty(scene);
EditorSceneManager.SaveScene(scene);
return $"미리 놓인 적 {enemies.Length} 끔 · 원본 프리팹: " + string.Join(", ", sources.Select(kv => $"{kv.Key}×{kv.Value}")) +
$" · 생성기 프리팹 {sp.enemyPrefabs.Length}종";
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 27796c6cf234b81498113feab3dfe594

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 041bd918d5ff5da418bf0bca18cd13d5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
{
"note": "수상한 고을 배경 2층 (2026-11-10 · make_layers.py)",
"tile_width_px": 3584,
"layers": {
"far": {
"file": "bg_eerie_village_tile.png",
"height_px": 1536,
"walk_v": 0.10026,
"parallax": 0.4,
"sorting_order": -100
},
"ground": {
"file": "bg_eerie_ground.png",
"height_px": 316,
"walk_v": 0.89241,
"parallax": 1.0,
"sorting_order": -99
}
},
"camera_margin_world": 0.4
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 91b3d4c218d56be46982faba8762813a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 KiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: 73edcbbe2553d20408ee98c2065d29e6
TextureImporter:
internalIDToNameTable:
- first:
213: 1890837388944703917
second: bg_eerie_ground_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: 1
spriteExtrude: 1
spriteMeshType: 0
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: 4096
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 2
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: 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: bg_eerie_ground_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 3584
height: 316
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: da18310569a9d3a10800000000000000
internalID: 1890837388944703917
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
bg_eerie_ground_0: 1890837388944703917
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

View File

@ -0,0 +1,169 @@
fileFormatVersion: 2
guid: cf32ef17b2aef6d48b55a7bcc26457f7
TextureImporter:
internalIDToNameTable:
- first:
213: -7533943643031670097
second: bg_eerie_village_tile_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: 1
spriteExtrude: 1
spriteMeshType: 0
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: 4096
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 2
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: 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: bg_eerie_village_tile_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 3584
height: 1536
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: fa2f8475c2e027790800000000000000
internalID: -7533943643031670097
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
bg_eerie_village_tile_0: -7533943643031670097
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -18,6 +18,7 @@ GameObject:
- component: {fileID: 1824045667} - component: {fileID: 1824045667}
- component: {fileID: 7700000000000000001} - component: {fileID: 7700000000000000001}
- component: {fileID: 7700000000000000004} - component: {fileID: 7700000000000000004}
- component: {fileID: 5396725966993708724}
m_Layer: 13 m_Layer: 13
m_Name: Player m_Name: Player
m_TagString: Player m_TagString: Player
@ -62,12 +63,15 @@ MonoBehaviour:
attackAudio: {fileID: 0} attackAudio: {fileID: 0}
maxSpeed: 3 maxSpeed: 3
jumpTakeOffSpeed: 7 jumpTakeOffSpeed: 7
attackHitbox: {fileID: 0} attackHitbox: {fileID: 7700000000000000001}
jumpState: 0 jumpState: 0
maxJumps: 2
collider2d: {fileID: 0} collider2d: {fileID: 0}
audioSource: {fileID: 0} audioSource: {fileID: 0}
health: {fileID: 0} health: {fileID: 0}
controlEnabled: 1 controlEnabled: 1
autoRun: 1
autoRunDirection: 1
--- !u!212 &212064061491315838 --- !u!212 &212064061491315838
SpriteRenderer: SpriteRenderer:
serializedVersion: 2 serializedVersion: 2
@ -117,8 +121,7 @@ SpriteRenderer:
m_SortingLayer: 0 m_SortingLayer: 0
m_SortingOrder: 5 m_SortingOrder: 5
m_MaskInteraction: 0 m_MaskInteraction: 0
m_Sprite: {fileID: -7999245345599557054, guid: 78c7da0e2fc366543ae4ad5e3ceb1b94, m_Sprite: {fileID: 21300000, guid: d0ef15db1d7cfe942833a436e709d5de, type: 3}
type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1} m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 1 m_FlipX: 1
m_FlipY: 0 m_FlipY: 0
@ -138,7 +141,7 @@ Animator:
m_GameObject: {fileID: 1208144871472054} m_GameObject: {fileID: 1208144871472054}
m_Enabled: 1 m_Enabled: 1
m_Avatar: {fileID: 0} m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: b09e60546065cf9448b36ebb7f759a91, type: 2} m_Controller: {fileID: 22100000, guid: 7dc53f5b013ff8d49a65bc6d14f88cbf, type: 2}
m_CullingMode: 0 m_CullingMode: 0
m_UpdateMode: 0 m_UpdateMode: 0
m_ApplyRootMotion: 0 m_ApplyRootMotion: 0
@ -329,8 +332,8 @@ BoxCollider2D:
m_Offset: {x: 0.03327547, y: -0.15880941} m_Offset: {x: 0.03327547, y: -0.15880941}
m_SpriteTilingProperty: m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0} border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0.5, y: 0.5} pivot: {x: 0.51102364, y: 0.3984499}
oldSize: {x: 0.6566667, y: 1.1033334} oldSize: {x: 1.2390244, y: 1.1414634}
newSize: {x: 1.28, y: 1.26} newSize: {x: 1.28, y: 1.26}
adaptiveTilingThreshold: 0.5 adaptiveTilingThreshold: 0.5
drawMode: 0 drawMode: 0
@ -370,3 +373,20 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
combatIdleDuration: 5 combatIdleDuration: 5
--- !u!114 &5396725966993708724
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1208144871472054}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7d8e9f0a1b20314253647586978a9b0, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Platformer.Gameplay.PlayerAttackTicker
attackInterval: 0.5
startupDelay: 0.3
onlyWhenEnemyNear: 1
detectLead: 0.6
detectHeight: 1.4

View File

@ -5168,6 +5168,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M001_Wolf value: Enemy_M001_Wolf
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6504999383530317407, guid: 9c65c4487bc1dba448954dd4c349a574,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6508303935943450553, guid: 9c65c4487bc1dba448954dd4c349a574, - target: {fileID: 6508303935943450553, guid: 9c65c4487bc1dba448954dd4c349a574,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -5395,6 +5400,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M006_Spider value: Enemy_M006_Spider
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1352356591422558597, guid: ae920194bcfccc94193aa9849a5c43a3,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1355808528257542243, guid: ae920194bcfccc94193aa9849a5c43a3, - target: {fileID: 1355808528257542243, guid: ae920194bcfccc94193aa9849a5c43a3,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -19094,6 +19104,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M006_Spider value: Enemy_M006_Spider
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1352356591422558597, guid: ae920194bcfccc94193aa9849a5c43a3,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1355808528257542243, guid: ae920194bcfccc94193aa9849a5c43a3, - target: {fileID: 1355808528257542243, guid: ae920194bcfccc94193aa9849a5c43a3,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -120409,6 +120424,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M005_Ghost value: Enemy_M005_Ghost
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7848113793813235637, guid: 6ff2339bdaf2e2f4799006c5fd6fb987,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7853816376061787731, guid: 6ff2339bdaf2e2f4799006c5fd6fb987, - target: {fileID: 7853816376061787731, guid: 6ff2339bdaf2e2f4799006c5fd6fb987,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -120861,6 +120881,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M004_ZombieF value: Enemy_M004_ZombieF
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 188415537611797449, guid: 5d0e2b70bea8e7f4aae3b841903f1572,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@ -130769,6 +130794,64 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 526.9} m_AnchoredPosition: {x: 0, y: 526.9}
m_SizeDelta: {x: 905.2, y: 542} m_SizeDelta: {x: 905.2, y: 542}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &910664597
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 910664599}
- component: {fileID: 910664598}
m_Layer: 0
m_Name: EnemySpawner_Endless
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &910664598
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 910664597}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a64a5b45504ee0f448c65f4419271acd, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Platformer.Mechanics.EndlessEnemySpawner
enemyPrefabs:
- {fileID: 6504999383530317407, guid: 9c65c4487bc1dba448954dd4c349a574, type: 3}
- {fileID: 603666063910396448, guid: c942a945bbf795c4fb34c7c41ad3eba8, type: 3}
- {fileID: 6888660251421648212, guid: 5166868e077e5a345bae2929e402f427, type: 3}
- {fileID: 188415537611797449, guid: 5d0e2b70bea8e7f4aae3b841903f1572, type: 3}
- {fileID: 7848113793813235637, guid: 6ff2339bdaf2e2f4799006c5fd6fb987, type: 3}
- {fileID: 1352356591422558597, guid: ae920194bcfccc94193aa9849a5c43a3, type: 3}
minGap: 5
maxGap: 10
firstSpawnDistance: 12
spawnOutsideMargin: 1.5
despawnBehindMargin: 4
minHits: 1
maxHits: 3
--- !u!4 &910664599
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 910664597}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, 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!1 &914162667 --- !u!1 &914162667
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -131357,6 +131440,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M003_ZombieM value: Enemy_M003_ZombieM
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6888660251421648212, guid: 5166868e077e5a345bae2929e402f427,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@ -131830,6 +131918,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M002_Bat value: Enemy_M002_Bat
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 603666063910396448, guid: c942a945bbf795c4fb34c7c41ad3eba8,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 609361017181068230, guid: c942a945bbf795c4fb34c7c41ad3eba8, - target: {fileID: 609361017181068230, guid: c942a945bbf795c4fb34c7c41ad3eba8,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -135057,6 +135150,116 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1016676386} m_GameObject: {fileID: 1016676386}
m_CullTransparentMesh: 1 m_CullTransparentMesh: 1
--- !u!1 &1017563961
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1017563964}
- component: {fileID: 1017563963}
- component: {fileID: 1017563962}
m_Layer: 0
m_Name: Backdrop_EerieVillage
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1017563962
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1017563961}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c003c532857c2cf41aae9d30b0149229, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::EerieVillage.Background.LoopingBackdrop
parallax: 0.4
pixelsPerWorldUnit: 144.61617
anchorImageV: 0.10026
anchorWorldY: -3
verticalFollow: 0
heightCoverage: 1.08
--- !u!212 &1017563963
SpriteRenderer:
serializedVersion: 2
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1017563961}
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_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, 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_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: -100
m_MaskInteraction: 0
m_Sprite: {fileID: 21300000, guid: cf32ef17b2aef6d48b55a7bcc26457f7, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 35.84, y: 15.36}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_SpriteSortPoint: 0
--- !u!4 &1017563964
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1017563961}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -15.137458, y: -3, z: 10}
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!1 &1019271008 --- !u!1 &1019271008
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -136037,6 +136240,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M002_Bat value: Enemy_M002_Bat
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 603666063910396448, guid: c942a945bbf795c4fb34c7c41ad3eba8,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 609361017181068230, guid: c942a945bbf795c4fb34c7c41ad3eba8, - target: {fileID: 609361017181068230, guid: c942a945bbf795c4fb34c7c41ad3eba8,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -136917,6 +137125,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M001_Wolf value: Enemy_M001_Wolf
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6504999383530317407, guid: 9c65c4487bc1dba448954dd4c349a574,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6508303935943450553, guid: 9c65c4487bc1dba448954dd4c349a574, - target: {fileID: 6508303935943450553, guid: 9c65c4487bc1dba448954dd4c349a574,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -144734,7 +144947,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!212 &1251841318 --- !u!212 &1251841318
SpriteRenderer: SpriteRenderer:
serializedVersion: 2 serializedVersion: 2
@ -298328,6 +298541,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M003_ZombieM value: Enemy_M003_ZombieM
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6888660251421648212, guid: 5166868e077e5a345bae2929e402f427,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@ -298712,6 +298930,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M005_Ghost value: Enemy_M005_Ghost
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7848113793813235637, guid: 6ff2339bdaf2e2f4799006c5fd6fb987,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7853816376061787731, guid: 6ff2339bdaf2e2f4799006c5fd6fb987, - target: {fileID: 7853816376061787731, guid: 6ff2339bdaf2e2f4799006c5fd6fb987,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -301424,6 +301647,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M002_Bat value: Enemy_M002_Bat
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 603666063910396448, guid: c942a945bbf795c4fb34c7c41ad3eba8,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 609361017181068230, guid: c942a945bbf795c4fb34c7c41ad3eba8, - target: {fileID: 609361017181068230, guid: c942a945bbf795c4fb34c7c41ad3eba8,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -306158,6 +306386,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M004_ZombieF value: Enemy_M004_ZombieF
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 188415537611797449, guid: 5d0e2b70bea8e7f4aae3b841903f1572,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@ -308264,6 +308497,116 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1769705767} m_GameObject: {fileID: 1769705767}
m_CullTransparentMesh: 1 m_CullTransparentMesh: 1
--- !u!1 &1770146875
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1770146878}
- component: {fileID: 1770146877}
- component: {fileID: 1770146876}
m_Layer: 0
m_Name: Backdrop_EerieVillage_Ground
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1770146876
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1770146875}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c003c532857c2cf41aae9d30b0149229, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::EerieVillage.Background.LoopingBackdrop
parallax: 1
pixelsPerWorldUnit: 144.61617
anchorImageV: 0.89241
anchorWorldY: -3
verticalFollow: 0
heightCoverage: 1.08
--- !u!212 &1770146877
SpriteRenderer:
serializedVersion: 2
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1770146875}
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_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, 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_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: -99
m_MaskInteraction: 0
m_Sprite: {fileID: 21300000, guid: 73edcbbe2553d20408ee98c2065d29e6, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 35.84, y: 3.16}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_SpriteSortPoint: 0
--- !u!4 &1770146878
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1770146875}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -15.137458, y: -3, z: 10}
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!1 &1771039266 --- !u!1 &1771039266
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -310743,6 +311086,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M004_ZombieF value: Enemy_M004_ZombieF
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 188415537611797449, guid: 5d0e2b70bea8e7f4aae3b841903f1572,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@ -312719,6 +313067,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M003_ZombieM value: Enemy_M003_ZombieM
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6888660251421648212, guid: 5166868e077e5a345bae2929e402f427,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []
m_AddedGameObjects: [] m_AddedGameObjects: []
@ -312774,6 +313127,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: Enemy_M001_Wolf value: Enemy_M001_Wolf
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6504999383530317407, guid: 9c65c4487bc1dba448954dd4c349a574,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6508303935943450553, guid: 9c65c4487bc1dba448954dd4c349a574, - target: {fileID: 6508303935943450553, guid: 9c65c4487bc1dba448954dd4c349a574,
type: 3} type: 3}
propertyPath: m_LocalPosition.x propertyPath: m_LocalPosition.x
@ -323549,6 +323907,9 @@ MonoBehaviour:
ActiveSlotMax: 6 ActiveSlotMax: 6
PassiveSlotMax: 6 PassiveSlotMax: 6
StartingCardIds: [] StartingCardIds: []
IsCloneFireActive: 0
CloneFireOrigin: {x: 0, y: 0}
CloneFireFacingX: 1
--- !u!114 &2082714491 --- !u!114 &2082714491
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -325907,3 +326268,6 @@ SceneRoots:
- {fileID: 889757653} - {fileID: 889757653}
- {fileID: 1952853428} - {fileID: 1952853428}
- {fileID: 120371127} - {fileID: 120371127}
- {fileID: 1017563964}
- {fileID: 1770146878}
- {fileID: 910664599}

View File

@ -0,0 +1,116 @@
using UnityEngine;
namespace EerieVillage.Background
{
/// <summary>
/// 무한 가로 스크롤 배경 한 층(리뉴얼 2026-11-10 · PD 지시 「배경을 무한하게 스크롤 가능하게」).
/// <para>
/// 좌우 끝이 맞물리는 그림 1장을 화면 폭을 덮을 만큼 나란히 깔고, 카메라 가로 이동에 맞춰 감아 돌린다.
/// 텍스처는 1장만 쓰고(사본은 같은 Sprite 공유) 오브젝트 수는 화면 폭에 맞춰 최소로 만든다.
/// </para>
/// <para>
/// 크기·높이: <see cref="pixelsPerWorldUnit"/> &gt; 0 이면 「그림 px ÷ 월드 단위」 고정 배율로 키우고,
/// 그림 안 세로 위치 <see cref="anchorImageV"/>(아래 = 0) 를 월드 높이 <see cref="anchorWorldY"/> 에 맞춘다(그린 흙길 = 실제 땅).
/// 0 이하이면 화면 높이에 맞춰 키우고 화면에 붙어 다닌다.
/// </para>
/// </summary>
[RequireComponent(typeof(SpriteRenderer))]
public class LoopingBackdrop : MonoBehaviour
{
[Tooltip("화면에서 이 층이 지나가는 속도(땅 = 1). 0 = 화면에 고정, 0.3~0.5 = 먼 배경, 1 = 땅과 같이.")]
[Range(0f, 1f)] public float parallax = 0.4f;
[Header("고정 배율 · 땅 맞춤 (pixelsPerWorldUnit > 0)")]
[Tooltip("그림 px ÷ 월드 단위. 여러 층이 같은 값을 써야 그림이 맞물린다. 0 이하 = 화면 높이 맞춤 모드.")]
public float pixelsPerWorldUnit = 0f;
[Tooltip("그림 아래 끝 = 0, 위 끝 = 1 기준으로 땅(발 디딤선)이 그려진 세로 위치.")]
[Range(0f, 1f)] public float anchorImageV = 0.1f;
[Tooltip("그 디딤선을 맞출 월드 높이(실제 땅 윗면).")]
public float anchorWorldY = 0f;
[Tooltip("카메라 세로 이동을 따라가는 비율. 0 = 땅에 붙어 있음(권장), 1 = 화면에 붙어 다님.")]
[Range(0f, 1f)] public float verticalFollow = 0f;
[Header("화면 높이 맞춤 모드 (pixelsPerWorldUnit <= 0)")]
[Tooltip("화면 높이 대비 배경 높이 배율.")]
public float heightCoverage = 1.08f;
Camera _cam;
SpriteRenderer _sr;
Transform[] _tiles;
float _tileWidth, _height;
float _lastOrtho = -1f, _lastAspect = -1f;
Vector3 _camStart;
Vector3 _rootStart;
void Start()
{
_cam = Camera.main;
_sr = GetComponent<SpriteRenderer>();
if (_cam == null || _sr.sprite == null)
{
Debug.LogWarning($"[LoopingBackdrop@{name}] 카메라 또는 Sprite 없음 — 꺼짐.");
enabled = false;
return;
}
_camStart = _cam.transform.position;
_rootStart = transform.position;
Rebuild();
}
void Rebuild()
{
float viewH = _cam.orthographicSize * 2f;
float viewW = viewH * _cam.aspect;
Vector2 spriteSize = _sr.sprite.bounds.size;
_height = pixelsPerWorldUnit > 0f ? _sr.sprite.rect.height / pixelsPerWorldUnit : viewH * heightCoverage;
float scale = _height / spriteSize.y;
transform.localScale = new Vector3(scale, scale, 1f);
_tileWidth = spriteSize.x * scale;
int need = Mathf.CeilToInt(viewW / _tileWidth) + 2; // 화면 폭 + 양옆 여유 1장씩
if (_tiles != null) foreach (var t in _tiles) if (t != null && t != transform) Destroy(t.gameObject);
_tiles = new Transform[need];
_tiles[0] = transform;
for (int i = 1; i < need; i++)
{
var go = new GameObject($"{name}_Tile{i}");
go.transform.SetParent(transform, false);
go.transform.localPosition = new Vector3(i * spriteSize.x, 0f, 0f);
var sr = go.AddComponent<SpriteRenderer>();
sr.sprite = _sr.sprite;
sr.sortingLayerID = _sr.sortingLayerID;
sr.sortingOrder = _sr.sortingOrder;
sr.color = _sr.color;
sr.sharedMaterial = _sr.sharedMaterial;
_tiles[i] = go.transform;
}
_lastOrtho = _cam.orthographicSize;
_lastAspect = _cam.aspect;
}
void LateUpdate()
{
if (_cam == null) return;
if (!Mathf.Approximately(_lastOrtho, _cam.orthographicSize) || !Mathf.Approximately(_lastAspect, _cam.aspect)) Rebuild();
Vector3 cam = _cam.transform.position;
float viewW = _cam.orthographicSize * 2f * _cam.aspect;
// 가로: 이 층은 카메라 이동의 (1 - parallax) 배를 따라간다 → 화면에서는 땅 속도의 parallax 배로 지나간다.
float leftEdge = cam.x - viewW * 0.5f;
float baseX = _rootStart.x + (cam.x - _camStart.x) * (1f - parallax); // 감기 전 첫 장 가운데
float firstLeft = baseX - _tileWidth * 0.5f;
// 첫 장 왼쪽 끝이 화면 왼쪽 끝 바로 왼쪽(한 장 이내)에 오도록 타일 폭 단위로 감는다(그림이 좌우로 이어져 끊김 없음).
float k = Mathf.Floor((leftEdge - firstLeft) / _tileWidth);
float x = baseX + k * _tileWidth;
float y;
if (pixelsPerWorldUnit > 0f)
// 스프라이트 기준점 = 가운데 → 가운데 높이 = 디딤선 높이 + (0.5 - 디딤선 비율) × 높이
y = anchorWorldY + (0.5f - anchorImageV) * _height + (cam.y - _camStart.y) * verticalFollow;
else
y = cam.y;
transform.position = new Vector3(x, y, transform.position.z);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c003c532857c2cf41aae9d30b0149229

View File

@ -15,6 +15,8 @@ namespace Platformer.Gameplay
{ {
public PlayerController player; public PlayerController player;
public Vector2 direction; // 플레이어 facing 방향 (±1, 0) — PlayerController.facing 기반 public Vector2 direction; // 플레이어 facing 방향 (±1, 0) — PlayerController.facing 기반
/// <summary>리뉴얼 2026-11-10 — 근접 자동 공격이 타격을 직접 처리했으면 true (판정 박스 중복 타격 방지).</summary>
public bool strikeHandled;
public override void Execute() public override void Execute()
{ {
@ -34,10 +36,11 @@ namespace Platformer.Gameplay
} }
// 플레이어 앞에 판정 박스 발생 // 플레이어 앞에 판정 박스 발생
if (player.attackHitbox != null) if (player.attackHitbox != null && !strikeHandled)
{ {
player.attackHitbox.Fire(direction); player.attackHitbox.Fire(direction);
} }
strikeHandled = false; // 이벤트 객체 재사용(풀) 대비 초기화
// [BT5-Dev Hero1 2026-05-07] combatidle 5초 타이머 갱신 (PlayerStateTimer.NotifyAttackFired) // [BT5-Dev Hero1 2026-05-07] combatidle 5초 타이머 갱신 (PlayerStateTimer.NotifyAttackFired)
var stateTimer = player.GetComponent<PlayerStateTimer>(); var stateTimer = player.GetComponent<PlayerStateTimer>();

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using Platformer.Mechanics; using Platformer.Mechanics;
using UnityEngine; using UnityEngine;
using static Platformer.Core.Simulation; using static Platformer.Core.Simulation;
@ -5,35 +6,42 @@ using static Platformer.Core.Simulation;
namespace Platformer.Gameplay namespace Platformer.Gameplay
{ {
/// <summary> /// <summary>
/// Periodic PlayerAttack event emitter — BT7-Plan PD 지시 2026-04-24 VS 순수형 자동 발동. /// Player 기본 공격 발화기 — <see cref="PlayerAttack"/> 이벤트를 Schedule 한다.
/// Player GameObject에 부착되어 <see cref="attackInterval"/> 초마다 <see cref="PlayerAttack"/> 이벤트를 Schedule.
/// <para> /// <para>
/// 기획 balance/01 v0.2 확정 전 임시 기본값: 0.5초 간격 · Phase 3-B 튠 대상. /// 리뉴얼 2026-11-10 (PD 지시 「항상 달리고, 적이 근접하면 자동으로 공격 · 닿기 전에 공격 · 맞은 적은 밀려남」):
/// 카드·특성 효과로 주기 수정이 필요해지면 외부에서 <see cref="attackInterval"/>을 직접 조작하거나 /// <see cref="onlyWhenEnemyNear"/> 가 켜져 있으면 진행 방향 앞, 같은 높이의 살아 있는 적이
/// <see cref="ApplyIntervalMultiplier"/>를 통해 합산한다 (P13-1 공용 모듈 인터페이스 전략). /// 「접촉 거리 + <see cref="strikeLead"/>」 안에 들어오면 쿨타임이 끝나 있는 그 프레임에 바로 친다.
/// </para> /// 살아남은 적은 「(달리기 속도 + 적이 다가오는 속도) × 쿨타임 + 여유」만큼 밀려나, 다음 공격 전에 닿지 않는다(PD 2026-11-10 참고 사항).
/// <para> /// 꺼 두면 예전 BT7-Plan VS 순수형(주기마다 판정 박스 발동)으로 동작한다.
/// <b>설계 근거</b>: PlayerAttack.Execute는 이벤트 처리 로직, 본 컴포넌트는 발화 트리거.
/// 단일 책임 원칙 + 범용성 (C11) — 타이머 컴포넌트만 교체하면 발화 방식 전환 가능.
/// </para> /// </para>
/// <para>카드·특성 효과로 주기 수정이 필요하면 <see cref="ApplyIntervalMultiplier"/> 를 쓴다 (P13-1 공용 모듈 인터페이스 전략).</para>
/// </summary> /// </summary>
[RequireComponent(typeof(PlayerController))] [RequireComponent(typeof(PlayerController))]
public class PlayerAttackTicker : MonoBehaviour public class PlayerAttackTicker : MonoBehaviour
{ {
/// <summary> /// <summary>공격 쿨타임(초). balance/01 확정 후 튠 대상.</summary>
/// 공격 자동 발동 주기(초). balance/01 v0.2 확정 후 튠 대상. [Tooltip("공격 쿨타임(초). 카드·특성으로 증감 가능.")]
/// </summary>
[Tooltip("공격 자동 발동 주기(초). 카드·특성으로 증감 가능.")]
public float attackInterval = 0.5f; public float attackInterval = 0.5f;
/// <summary> /// <summary>게임 시작 직후 첫 발화까지 지연(초). 플레이어 소환 애니메이션 여유.</summary>
/// 게임 시작 직후 첫 발화까지 지연(초). 플레이어 소환 애니메이션 여유.
/// </summary>
[Tooltip("게임 시작 직후 첫 발화까지의 지연(초). Spawn 애니메이션 여유.")] [Tooltip("게임 시작 직후 첫 발화까지의 지연(초). Spawn 애니메이션 여유.")]
public float startupDelay = 0.3f; public float startupDelay = 0.3f;
[Header("근접 자동 공격 (리뉴얼 2026-11-10)")]
[Tooltip("켜면 앞쪽 같은 높이의 적이 사거리 안에 있을 때만 공격한다.")]
public bool onlyWhenEnemyNear = true;
[Tooltip("적의 접촉 거리보다 이만큼 더 먼 곳에서 친다(월드). 닿기 전에 맞히기 위한 여유.")]
public float strikeLead = 0.5f;
[Tooltip("같은 높이로 보는 세로 허용 차(월드).")]
public float verticalTolerance = 1.0f;
[Tooltip("넉백 거리 계산에 더하는 여유(월드).")]
public float knockbackMargin = 0.3f;
[Tooltip("밀려나는 데 걸리는 시간(초).")]
public float knockbackDuration = 0.15f;
PlayerController player; PlayerController player;
float attackTimer; float attackTimer;
readonly List<EnemyController> _targets = new List<EnemyController>();
void Awake() void Awake()
{ {
@ -43,29 +51,95 @@ namespace Platformer.Gameplay
void Update() void Update()
{ {
// 컨트롤 비활성 상태(마을 이동·메뉴 등)에서는 자동 공격 중단 // 컨트롤 비활성 상태(마을 이동·메뉴·사망 등)에서는 자동 공격 중단
if (player == null || !player.controlEnabled) if (player == null || !player.controlEnabled) return;
{
return;
}
// 유효 간격이 0 이하이면 tick 중단 (디자이너 실수 방지) // 유효 간격이 0 이하이면 tick 중단 (디자이너 실수 방지)
if (attackInterval <= 0f) if (attackInterval <= 0f) return;
if (attackTimer > 0f) attackTimer -= Time.deltaTime;
if (attackTimer > 0f) return;
bool handled = false;
if (onlyWhenEnemyNear)
{ {
return; if (!FindTargets(_targets))
{
attackTimer = 0f; // 쿨타임은 끝난 채로 대기 → 적이 들어오면 즉시 발동
return;
}
float dir = player.Facing.x >= 0f ? 1f : -1f;
float kb = KnockbackDistance();
if (player.attackHitbox != null)
{
foreach (var e in _targets) player.attackHitbox.StrikeEnemy(e, dir, kb, knockbackDuration);
handled = true;
}
} }
attackTimer -= Time.deltaTime; attackTimer = attackInterval;
if (attackTimer <= 0f) var ev = Schedule<PlayerAttack>();
{ ev.player = player;
attackTimer += attackInterval; ev.direction = player.Facing;
ev.strikeHandled = handled;
}
var ev = Schedule<PlayerAttack>(); /// <summary>
ev.player = player; /// 넉백 거리 = (달리기 속도 + 적이 다가오는 속도) × 쿨타임 + 여유.
ev.direction = player.Facing; /// 러너 모드 적은 제자리라 다가오는 속도 = 0.
/// </summary>
public float KnockbackDistance(float enemyApproachSpeed = 0f)
{
return (player.maxSpeed + enemyApproachSpeed) * attackInterval + knockbackMargin;
}
/// <summary>적 1마리의 사거리 = 접촉 거리(중심 사이 · 그림 폭 기준 중 큰 쪽) + 앞 여유.</summary>
public float StrikeRange(EnemyController e)
{
float contact = Mathf.Max(e.contactDistance, e.VisualBounds.extents.x + player.Bounds.extents.x);
return contact + strikeLead;
}
/// <summary>진행 방향 앞, 같은 높이, 사거리 안의 살아 있는 적을 모은다.</summary>
public bool FindTargets(List<EnemyController> result)
{
result.Clear();
float dir = player.Facing.x >= 0f ? 1f : -1f;
Vector2 p = player.transform.position;
foreach (var e in EnemyRegistry)
{
if (e == null || !e.isActiveAndEnabled) continue;
var h = e.GetComponent<Health>();
if (h != null && !h.IsAlive) continue;
Vector2 q = e.transform.position;
float ahead = (q.x - p.x) * dir;
if (ahead < -0.2f) continue; // 이미 지나간 적은 제외
if (Mathf.Abs(e.VisualBounds.center.y - player.Bounds.center.y) > verticalTolerance + e.VisualBounds.extents.y) continue;
if (Vector2.Distance(p, q) <= StrikeRange(e)) result.Add(e);
}
return result.Count > 0;
}
// 적 목록: 매 프레임 FindObjectsByType 대신 캐시(적 수가 바뀔 때만 갱신)
static readonly List<EnemyController> s_registry = new List<EnemyController>();
static int s_frame = -1;
static List<EnemyController> EnemyRegistry
{
get
{
if (s_frame != Time.frameCount && Time.frameCount % 10 == 0 || s_registry.Count == 0)
{
s_registry.Clear();
s_registry.AddRange(Object.FindObjectsByType<EnemyController>(FindObjectsSortMode.None));
s_frame = Time.frameCount;
}
return s_registry;
} }
} }
/// <summary>앞에 칠 수 있는 적이 있는가(디버그·외부 확인용).</summary>
public bool EnemyAhead() => FindTargets(_targets);
/// <summary> /// <summary>
/// 카드·특성 효과가 공격 주기를 배수로 조정할 때 사용하는 편의 API. /// 카드·특성 효과가 공격 주기를 배수로 조정할 때 사용하는 편의 API.
/// </summary> /// </summary>

View File

@ -78,6 +78,25 @@ namespace Platformer.Mechanics
} }
} }
/// <summary>
/// 리뉴얼 2026-11-10 — 근접 자동 공격 1타: 지정한 적에게 <see cref="damage"/> 를 주고(무적 시간 무시 · 피격 모션),
/// 살아남으면 dir 방향으로 밀어낸다. 죽으면 EnemyDeath 체인. 반환 = 처치 여부.
/// </summary>
public bool StrikeEnemy(EnemyController enemy, float dir, float knockbackDistance, float knockbackDuration)
{
if (enemy == null) return false;
var health = enemy.GetComponent<Health>();
if (health == null || !health.IsAlive) return false;
health.DecrementBypassInvulnWithHit(damage);
if (!health.IsAlive)
{
Schedule<EnemyDeath>().enemy = enemy;
return true;
}
enemy.Knockback(dir, knockbackDistance, knockbackDuration);
return false;
}
// Scene view 가시화 — 활성 상태에서 박스 표시 // Scene view 가시화 — 활성 상태에서 박스 표시
void OnDrawGizmos() void OnDrawGizmos()
{ {

View File

@ -0,0 +1,112 @@
using System.Collections.Generic;
using UnityEngine;
namespace Platformer.Mechanics
{
/// <summary>
/// 무한 스크롤 적 생성기(리뉴얼 2026-11-10 · PD 지시 「무한 스크롤하는 동안 적은 항상 새롭게 스크롤되는 화면에 랜덤으로 등장」).
/// <para>
/// 카메라 오른쪽 끝이 다음 생성 지점에 닿으면 그 지점(화면 밖 바로 오른쪽)에 적 프리팹을 만들고,
/// 다음 지점은 <see cref="minGap"/>~<see cref="maxGap"/> 사이 무작위로 정한다. 종류는 프리팹의 MonsterRandomizer 가 무작위로 고른다.
/// 생성된 적은 러너 모드(제자리 · 캐릭터 발 높이 · 맞으면 밀려남)이며, 화면 왼쪽 뒤로 지나가면 지운다.
/// </para>
/// <para>체력: 몬스터마다 무작위 <see cref="minHits"/>~<see cref="maxHits"/> 회 공격으로 처치(PD 2026-11-10 「임시로 1~3회」).</para>
/// </summary>
public class EndlessEnemySpawner : MonoBehaviour
{
[Tooltip("생성할 적 프리팹 목록(종류별) — 매번 무작위로 하나를 고른다.")]
public GameObject[] enemyPrefabs;
[Tooltip("적 사이 최소 간격(월드).")]
public float minGap = 5f;
[Tooltip("적 사이 최대 간격(월드).")]
public float maxGap = 10f;
[Tooltip("첫 적이 나타날 거리(플레이어 시작 위치 기준 · 월드).")]
public float firstSpawnDistance = 12f;
[Tooltip("화면 오른쪽 끝에서 이만큼 바깥에 만든다(월드) — 스크롤되며 화면에 들어온다.")]
public float spawnOutsideMargin = 1.5f;
[Tooltip("화면 왼쪽 끝에서 이만큼 뒤로 지나간 적은 지운다(월드).")]
public float despawnBehindMargin = 4f;
[Header("임시 체력 (PD 2026-11-10 「임시로 몬스터마다 랜덤 1~3회 공격으로 처치」)")]
public int minHits = 1;
public int maxHits = 3;
Camera _cam;
PlayerController _player;
float _nextSpawnX;
float _feetY;
bool _feetYReady;
Transform _staging; // 꺼진 보관 자리: Awake 전에 설정을 넣기 위해 여기서 만든 뒤 꺼낸다
readonly List<EnemyController> _alive = new List<EnemyController>();
void Start()
{
_cam = Camera.main;
_player = FindFirstObjectByType<PlayerController>();
if (_cam == null || _player == null || enemyPrefabs == null || enemyPrefabs.Length == 0)
{
Debug.LogWarning("[EndlessEnemySpawner] 카메라·플레이어·적 프리팹 중 없음 — 꺼짐.");
enabled = false;
return;
}
var st = new GameObject("_SpawnStaging");
st.SetActive(false);
st.transform.SetParent(transform, false);
_staging = st.transform;
_nextSpawnX = _player.transform.position.x + firstSpawnDistance;
}
void LateUpdate()
{
// 캐릭터 발 높이 = 땅에 선 플레이어 콜라이더 바닥(새 캐릭터 그림의 발 = 콜라이더 바닥)
if (_player.IsGrounded)
{
_feetY = _player.Bounds.min.y;
_feetYReady = true;
}
if (!_feetYReady) return;
float halfW = _cam.orthographicSize * _cam.aspect;
float camRight = _cam.transform.position.x + halfW;
float camLeft = _cam.transform.position.x - halfW;
// 다음 생성 지점이 화면 오른쪽 끝 바깥 여유 안으로 들어오면 만든다(한 프레임에 여러 마리 가능)
int guard = 0;
while (camRight + spawnOutsideMargin >= _nextSpawnX && guard++ < 8)
{
Spawn(Mathf.Max(_nextSpawnX, camRight + spawnOutsideMargin));
_nextSpawnX += Random.Range(minGap, maxGap);
}
for (int i = _alive.Count - 1; i >= 0; i--)
{
var e = _alive[i];
if (e == null) { _alive.RemoveAt(i); continue; }
if (e.transform.position.x < camLeft - despawnBehindMargin)
{
Destroy(e.gameObject);
_alive.RemoveAt(i);
}
else e.runnerFeetY = _feetY;
}
}
void Spawn(float x)
{
var prefab = enemyPrefabs[Random.Range(0, enemyPrefabs.Length)];
var go = Instantiate(prefab, new Vector3(x, _feetY + 1f, 0f), Quaternion.identity, _staging);
var ec = go.GetComponent<EnemyController>();
ec.runnerMode = true;
ec.runnerFeetY = _feetY;
ec.flyingYOffset = 0f; // 날으는 몬스터도 같은 높이(PD 「몬스터 y = 캐릭터 y」)
var h = go.GetComponent<Health>();
if (h != null)
{
int dmg = _player.attackHitbox != null ? Mathf.Max(1, _player.attackHitbox.damage) : 1;
int hits = Random.Range(minHits, maxHits + 1);
h.RandomMaxHPRange = new Vector2Int(hits * dmg, hits * dmg); // Awake 에서 maxHP 로 반영
}
go.transform.SetParent(null, true); // 켜진 곳으로 꺼냄 → 여기서 Awake(종류 무작위 · 체력) 실행
_alive.Add(ec);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a64a5b45504ee0f448c65f4419271acd

View File

@ -60,7 +60,8 @@ namespace Platformer.Mechanics
internal Collider2D _collider; internal Collider2D _collider;
internal AudioSource _audio; internal AudioSource _audio;
SpriteRenderer spriteRenderer; SpriteRenderer spriteRenderer;
Rigidbody2D _body; // BT96: KinematicObject body 영역 직접 set 위해 캐싱 Rigidbody2D _body; // BT96: KinematicObject body 직접 set 위해 캐싱
Health _health; // 리뉴얼 2026-11-10: 죽은 적 접촉 피해 차단용
public Bounds Bounds => _collider.bounds; public Bounds Bounds => _collider.bounds;
@ -73,6 +74,57 @@ namespace Platformer.Mechanics
PlayerController _cachedPlayer; PlayerController _cachedPlayer;
bool _ignoreCollisionApplied; bool _ignoreCollisionApplied;
[Header("리뉴얼 2026-11-10 — 러너 모드 (PD 지시: 자동 달리기 · 랜덤 생성 · 같은 높이 · 밀려남)")]
[Tooltip("켜면 순찰·떨어짐 복귀를 하지 않고 제자리에서 플레이어(왼쪽)를 바라보며, 그림 아래 끝을 runnerFeetY 에 맞춘다.")]
public bool runnerMode = false;
[Tooltip("러너 모드에서 그림 아래 끝(발)을 맞출 월드 높이 = 캐릭터 발 높이.")]
public float runnerFeetY = 0f;
[Tooltip("플레이어 접촉 피해 거리(중심 사이). 예전 상수 1.5 를 값으로 꺼냄 — 플레이어 근접 공격 사거리 계산에도 쓴다.")]
public float contactDistance = 1.5f;
float _knockStartX, _knockDist, _knockStartTime, _knockDuration;
/// <summary>밀려나는 중인가 (밀려나는 동안은 접촉 피해를 주지 않는다).</summary>
public bool IsKnockedBack => Time.time < _knockStartTime + _knockDuration;
/// <summary>
/// 맞고 밀려남(리뉴얼 2026-11-10). dir 방향(±1)으로 distance 만큼 duration 동안 감속하며 이동.
/// </summary>
public void Knockback(float dir, float distance, float duration)
{
_knockStartX = transform.position.x;
_knockDist = Mathf.Sign(dir) * Mathf.Max(0f, distance);
_knockStartTime = Time.time;
_knockDuration = Mathf.Max(0.01f, duration);
if (control != null) { control.move.x = 0f; control.velocity = Vector2.zero; }
}
void UpdateRunner()
{
if (control != null)
{
control.move.x = 0f;
control.gravityModifier = 0f;
control.velocity = Vector2.zero;
}
if (spriteRenderer != null) spriteRenderer.flipX = false; // 원본 그림 = 왼쪽(플레이어 쪽)을 봄
var p = transform.position;
if (_knockDuration > 0f)
{
float t = Mathf.Clamp01((Time.time - _knockStartTime) / _knockDuration);
float ease = 1f - (1f - t) * (1f - t); // 처음 빠르고 끝에서 멈춤
p.x = _knockStartX + _knockDist * ease;
if (t >= 1f) _knockDuration = 0f;
}
// 그림 아래 끝 = 캐릭터 발 높이 (프레임마다 잘린 사각형 가운데가 기준점이라 매 프레임 맞춘다)
if (spriteRenderer != null && spriteRenderer.sprite != null)
{
var s = spriteRenderer.sprite;
p.y = runnerFeetY + s.pivot.y / s.pixelsPerUnit * transform.lossyScale.y;
}
transform.position = p;
if (_body != null) _body.position = p;
}
void Awake() void Awake()
{ {
control = GetComponent<AnimationController>(); control = GetComponent<AnimationController>();
@ -80,6 +132,7 @@ namespace Platformer.Mechanics
_audio = GetComponent<AudioSource>(); _audio = GetComponent<AudioSource>();
spriteRenderer = GetComponent<SpriteRenderer>(); spriteRenderer = GetComponent<SpriteRenderer>();
_body = GetComponent<Rigidbody2D>(); _body = GetComponent<Rigidbody2D>();
_health = GetComponent<Health>();
// BT5-Dev #21 — Awake 시점 fallback 추가 (Player tag 영역 미설정 영역 대비) // BT5-Dev #21 — Awake 시점 fallback 추가 (Player tag 영역 미설정 영역 대비)
var playerObj = GameObject.FindGameObjectWithTag("Player"); var playerObj = GameObject.FindGameObjectWithTag("Player");
@ -410,14 +463,16 @@ namespace Platformer.Mechanics
void Update() void Update()
{ {
// BT89 — 자동 patrol + 즉시 벽 검출 + 1~3초 대기 영역 // 리뉴얼 2026-11-10 — 러너 모드: 순찰 대신 제자리 · 같은 높이 · 밀려남 처리
UpdatePatrol(); if (runnerMode) UpdateRunner();
// BT89 — 자동 patrol + 즉시 벽 검출 + 1~3초 대기
else UpdatePatrol();
// BT102 — 떨어짐 검출 영역: y < _startY - fallThreshold 시 = 시작 위치 텔레포트 복귀 // BT102 — 떨어짐 검출: y < _startY - fallThreshold 시 = 시작 위치 텔레포트 복귀
// PD 명시 (2026-05-08): 투명벽 폐기·떨어짐 차단 다른 방법 // PD 명시 (2026-05-08): 투명벽 폐기·떨어짐 차단 다른 방법
// 단순·근본 방법 — 떨어진 후 검출 영역 즉시 복귀 (영구 떨어짐 X) // 단순·근본 방법 — 떨어진 후 검출 즉시 복귀 (영구 떨어짐 X)
// PD 지시 2026-05-15 — 날으는 몬스터 영역 떨어짐 검출 skip (공중 patrol 정상) // PD 지시 2026-05-15 — 날으는 몬스터는 떨어짐 검출 skip (공중 patrol 정상)
if (_isInitialized && !IsFlying && transform.position.y < _startY - fallThreshold) if (!runnerMode && _isInitialized && !IsFlying && transform.position.y < _startY - fallThreshold)
{ {
Vector3 safe = new Vector3(_startX, _startY, transform.position.z); Vector3 safe = new Vector3(_startX, _startY, transform.position.z);
transform.position = safe; transform.position = safe;
@ -443,12 +498,14 @@ namespace Platformer.Mechanics
if (pgo != null) _cachedPlayer = pgo.GetComponent<PlayerController>(); if (pgo != null) _cachedPlayer = pgo.GetComponent<PlayerController>();
if (_cachedPlayer == null) _cachedPlayer = Object.FindFirstObjectByType<PlayerController>(); if (_cachedPlayer == null) _cachedPlayer = Object.FindFirstObjectByType<PlayerController>();
} }
if (_cachedPlayer != null && _cachedPlayer.health != null && _cachedPlayer.health.IsAlive) // 리뉴얼 2026-11-10 — 밀려나는 중(맞은 직후)·죽은 적은 접촉 피해 없음
bool selfAlive = _health == null || _health.IsAlive;
if (_cachedPlayer != null && _cachedPlayer.health != null && _cachedPlayer.health.IsAlive && selfAlive && !IsKnockedBack)
{ {
// PD 지시 2026-05-13 — VisualBounds.Intersects OR distance < 1.5f 단일 조건·ground·공중 무관 피격 // PD 지시 2026-05-13 — VisualBounds.Intersects OR distance < contactDistance(예전 1.5f) 단일 조건·ground·공중 무관 피격
float dist = Vector2.Distance(transform.position, _cachedPlayer.transform.position); float dist = Vector2.Distance(transform.position, _cachedPlayer.transform.position);
bool boundsHit = VisualBounds.Intersects(_cachedPlayer.Bounds); bool boundsHit = VisualBounds.Intersects(_cachedPlayer.Bounds);
bool distHit = dist < 1.5f; bool distHit = dist < contactDistance;
if ((boundsHit || distHit) && !_cachedPlayer.health.IsInvulnerable) if ((boundsHit || distHit) && !_cachedPlayer.health.IsInvulnerable)
{ {
_cachedPlayer.health.Decrement(); _cachedPlayer.health.Decrement();

View File

@ -61,7 +61,14 @@ namespace Platformer.Mechanics
public Health health; public Health health;
public bool controlEnabled = true; public bool controlEnabled = true;
[Header("리뉴얼 2026-11-10 — 자동 달리기 · 터치 점프 (PD 지시)")]
[Tooltip("켜면 이동 입력 없이 항상 달리고, 화면 터치(마우스 클릭)는 점프만 한다.")]
public bool autoRun = true;
[Tooltip("자동 달리기 방향 (+1 = 오른쪽, -1 = 왼쪽).")]
public float autoRunDirection = 1f;
bool jump; bool jump;
bool _pointerJumpHeld; // 터치·클릭으로 시작한 점프를 누르고 있는 중 (떼면 점프 감속)
Vector2 move; Vector2 move;
SpriteRenderer spriteRenderer; SpriteRenderer spriteRenderer;
internal Animator animator; internal Animator animator;
@ -152,12 +159,18 @@ namespace Platformer.Mechanics
if (controlEnabled) if (controlEnabled)
{ {
Vector2 moveInput = m_MoveAction.ReadValue<Vector2>(); Vector2 moveInput = m_MoveAction.ReadValue<Vector2>();
move.x = moveInput.x; // 리뉴얼 2026-11-10 — 자동 달리기: 이동 입력을 쓰지 않고 항상 한 방향으로 달린다.
move.x = autoRun ? Mathf.Sign(autoRunDirection) : moveInput.x;
bool pointerPressed = autoRun && PointerJumpPressedThisFrame();
bool pointerReleased = autoRun && _pointerJumpHeld && PointerReleasedThisFrame();
if (pointerPressed) _pointerJumpHeld = true;
if (pointerReleased) _pointerJumpHeld = false;
// PD 결정 §15-2 (2026-05-18) — 이중 점프 + 사선 점프. // PD 결정 §15-2 (2026-05-18) — 이중 점프 + 사선 점프.
// 사선 점프 = 점프 + move.x 입력 동시 (KinematicObject ComputeVelocity 영역 velocity.y·targetVelocity.x 동시 set 영역 자연 정합). // 사선 점프 = 점프 + move.x 입력 동시 (KinematicObject ComputeVelocity 의 velocity.y·targetVelocity.x 동시 설정).
// 이중 점프 = Grounded 1차 점프 후 공중 영역 2차 점프 (_jumpCount < maxJumps 영역). // 이중 점프 = Grounded 1차 점프 후 공중 2차 점프 (_jumpCount < maxJumps).
if (m_JumpAction.WasPressedThisFrame()) if (m_JumpAction.WasPressedThisFrame() || pointerPressed)
{ {
bool downHeld = moveInput.y < -0.5f; bool downHeld = moveInput.y < -0.5f;
bool onJumpThroughPlatform = false; bool onJumpThroughPlatform = false;
@ -186,7 +199,7 @@ namespace Platformer.Mechanics
jumpState = JumpState.PrepareToJump; jumpState = JumpState.PrepareToJump;
} }
} }
else if (m_JumpAction.WasReleasedThisFrame()) else if (m_JumpAction.WasReleasedThisFrame() || pointerReleased)
{ {
stopJump = true; stopJump = true;
Schedule<PlayerStopJump>().player = this; Schedule<PlayerStopJump>().player = this;
@ -208,6 +221,29 @@ namespace Platformer.Mechanics
if (IsGrounded) LastGroundedPosition = transform.position; if (IsGrounded) LastGroundedPosition = transform.position;
} }
/// <summary>
/// 화면 터치(또는 에디터·PC 의 마우스 왼쪽 클릭)가 이번 프레임에 눌렸는가. UI 위를 누른 것은 제외.
/// </summary>
bool PointerJumpPressedThisFrame()
{
bool pressed = false;
var touch = Touchscreen.current;
if (touch != null && touch.primaryTouch.press.wasPressedThisFrame) pressed = true;
var mouse = Mouse.current;
if (!pressed && mouse != null && mouse.leftButton.wasPressedThisFrame) pressed = true;
if (!pressed) return false;
var es = UnityEngine.EventSystems.EventSystem.current;
return es == null || !es.IsPointerOverGameObject();
}
bool PointerReleasedThisFrame()
{
var touch = Touchscreen.current;
if (touch != null && touch.primaryTouch.press.wasReleasedThisFrame) return true;
var mouse = Mouse.current;
return mouse != null && mouse.leftButton.wasReleasedThisFrame;
}
// Drop-Through Layer (Foreground·AutoForeground GameObject Layer 16). // Drop-Through Layer (Foreground·AutoForeground GameObject Layer 16).
// KinematicObject body.Cast의 contactFilter는 Start() 시점 캐싱되므로 Drop-Through는 SetLayerMask 동적 갱신으로 처리. // KinematicObject body.Cast의 contactFilter는 Start() 시점 캐싱되므로 Drop-Through는 SetLayerMask 동적 갱신으로 처리.
const int JUMP_THROUGH_LAYER = 16; const int JUMP_THROUGH_LAYER = 16;

View File

@ -16,6 +16,13 @@ namespace EerieVillage.Progression
/// <summary>레벨업 발화 — int = new Level. LevelUpManager 구독 hook.</summary> /// <summary>레벨업 발화 — int = new Level. LevelUpManager 구독 hook.</summary>
public event System.Action<int> OnLevelUp; public event System.Action<int> OnLevelUp;
/// <summary>
/// [임시 2026-11-10 · PD 지시 「내가 지시하기 전까지 레벨업은 하지 않도록」] false 면 XP 를 받지 않아 레벨업(기술 선택 창)이 없다.
/// PD 가 다시 켜라고 지시하면 기본값을 true 로 되돌리고 이 주석을 지운다.
/// </summary>
[Tooltip("임시(PD 2026-11-10): 꺼져 있으면 경험치·레벨업 없음.")]
public bool levelUpEnabled = false;
void Awake() void Awake()
{ {
XPToNextLevel = LevelXPTableLoader.GetXPToNextLevel(Level); XPToNextLevel = LevelXPTableLoader.GetXPToNextLevel(Level);
@ -25,6 +32,7 @@ namespace EerieVillage.Progression
public void GainXP(int amount) public void GainXP(int amount)
{ {
if (amount <= 0) return; if (amount <= 0) return;
if (!levelUpEnabled) return; // 임시(PD 2026-11-10): 레벨업 끔
CurrentXP += amount; CurrentXP += amount;
Debug.Log($"[PlayerProgression] GainXP +{amount} → Lv.{Level} {CurrentXP}/{XPToNextLevel}"); Debug.Log($"[PlayerProgression] GainXP +{amount} → Lv.{Level} {CurrentXP}/{XPToNextLevel}");
while (CurrentXP >= XPToNextLevel) while (CurrentXP >= XPToNextLevel)

View File

@ -8,6 +8,7 @@
"com.unity.feature.development": "1.0.2", "com.unity.feature.development": "1.0.2",
"com.unity.inputsystem": "1.19.0", "com.unity.inputsystem": "1.19.0",
"com.unity.multiplayer.center": "1.0.1", "com.unity.multiplayer.center": "1.0.1",
"com.unity.pipeline": "0.10.0-exp.1",
"com.unity.render-pipelines.universal": "17.3.0", "com.unity.render-pipelines.universal": "17.3.0",
"com.unity.test-framework": "1.6.0", "com.unity.test-framework": "1.6.0",
"com.unity.timeline": "1.8.12", "com.unity.timeline": "1.8.12",

View File

@ -11,11 +11,11 @@
"hash": "73eb27aeccfa8e0676eaf3304136e9b85953d913" "hash": "73eb27aeccfa8e0676eaf3304136e9b85953d913"
}, },
"com.unity.2d.animation": { "com.unity.2d.animation": {
"version": "13.0.4", "version": "13.0.6",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
"com.unity.2d.common": "12.0.2", "com.unity.2d.common": "12.0.4",
"com.unity.2d.sprite": "1.0.0", "com.unity.2d.sprite": "1.0.0",
"com.unity.collections": "2.4.3", "com.unity.collections": "2.4.3",
"com.unity.modules.animation": "1.0.0", "com.unity.modules.animation": "1.0.0",
@ -24,11 +24,11 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.2d.aseprite": { "com.unity.2d.aseprite": {
"version": "3.0.1", "version": "3.0.2",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
"com.unity.2d.common": "12.0.1", "com.unity.2d.common": "12.0.3",
"com.unity.2d.sprite": "1.0.0", "com.unity.2d.sprite": "1.0.0",
"com.unity.2d.tilemap": "1.0.0", "com.unity.2d.tilemap": "1.0.0",
"com.unity.mathematics": "1.2.6", "com.unity.mathematics": "1.2.6",
@ -37,7 +37,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.2d.common": { "com.unity.2d.common": {
"version": "12.0.2", "version": "12.0.4",
"depth": 2, "depth": 2,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -61,11 +61,11 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.2d.psdimporter": { "com.unity.2d.psdimporter": {
"version": "12.0.1", "version": "12.0.2",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
"com.unity.2d.common": "12.0.1", "com.unity.2d.common": "12.0.3",
"com.unity.2d.sprite": "1.0.0", "com.unity.2d.sprite": "1.0.0",
"com.unity.2d.tilemap": "1.0.0" "com.unity.2d.tilemap": "1.0.0"
}, },
@ -98,7 +98,7 @@
} }
}, },
"com.unity.2d.tilemap.extras": { "com.unity.2d.tilemap.extras": {
"version": "6.0.1", "version": "6.0.3",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -109,11 +109,11 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.2d.tooling": { "com.unity.2d.tooling": {
"version": "1.0.2", "version": "1.0.4",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
"com.unity.2d.common": "12.0.2", "com.unity.2d.common": "12.0.4",
"com.unity.modules.uielements": "1.0.0" "com.unity.modules.uielements": "1.0.0"
}, },
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
@ -135,7 +135,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.burst": { "com.unity.burst": {
"version": "1.8.29", "version": "1.8.30",
"depth": 2, "depth": 2,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -155,11 +155,11 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.collections": { "com.unity.collections": {
"version": "2.6.5", "version": "2.6.8",
"depth": 2, "depth": 2,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
"com.unity.burst": "1.8.27", "com.unity.burst": "1.8.29",
"com.unity.mathematics": "1.3.2", "com.unity.mathematics": "1.3.2",
"com.unity.test-framework": "1.4.6", "com.unity.test-framework": "1.4.6",
"com.unity.nuget.mono-cecil": "1.11.6", "com.unity.nuget.mono-cecil": "1.11.6",
@ -178,7 +178,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.editorcoroutines": { "com.unity.editorcoroutines": {
"version": "1.0.1", "version": "1.1.0",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": {}, "dependencies": {},
@ -195,15 +195,15 @@
"depth": 0, "depth": 0,
"source": "builtin", "source": "builtin",
"dependencies": { "dependencies": {
"com.unity.2d.animation": "13.0.4", "com.unity.2d.animation": "13.0.6",
"com.unity.2d.pixel-perfect": "5.1.1", "com.unity.2d.pixel-perfect": "5.1.1",
"com.unity.2d.psdimporter": "12.0.1", "com.unity.2d.psdimporter": "12.0.2",
"com.unity.2d.sprite": "1.0.0", "com.unity.2d.sprite": "1.0.0",
"com.unity.2d.spriteshape": "13.0.0", "com.unity.2d.spriteshape": "13.0.0",
"com.unity.2d.tilemap": "1.0.0", "com.unity.2d.tilemap": "1.0.0",
"com.unity.2d.tilemap.extras": "6.0.1", "com.unity.2d.tilemap.extras": "6.0.3",
"com.unity.2d.aseprite": "3.0.1", "com.unity.2d.aseprite": "3.0.2",
"com.unity.2d.tooling": "1.0.2" "com.unity.2d.tooling": "1.0.4"
} }
}, },
"com.unity.feature.development": { "com.unity.feature.development": {
@ -212,15 +212,15 @@
"source": "builtin", "source": "builtin",
"dependencies": { "dependencies": {
"com.unity.ide.visualstudio": "2.0.26", "com.unity.ide.visualstudio": "2.0.26",
"com.unity.ide.rider": "3.0.39", "com.unity.ide.rider": "3.0.40",
"com.unity.editorcoroutines": "1.0.1", "com.unity.editorcoroutines": "1.1.0",
"com.unity.performance.profile-analyzer": "1.3.3", "com.unity.performance.profile-analyzer": "1.4.0",
"com.unity.test-framework": "1.6.0", "com.unity.test-framework": "1.6.0",
"com.unity.testtools.codecoverage": "1.3.0" "com.unity.testtools.codecoverage": "1.3.0"
} }
}, },
"com.unity.ide.rider": { "com.unity.ide.rider": {
"version": "3.0.39", "version": "3.0.40",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -263,7 +263,7 @@
}, },
"com.unity.nuget.mono-cecil": { "com.unity.nuget.mono-cecil": {
"version": "1.11.6", "version": "1.11.6",
"depth": 3, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": {}, "dependencies": {},
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
@ -276,12 +276,26 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.performance.profile-analyzer": { "com.unity.performance.profile-analyzer": {
"version": "1.3.3", "version": "1.4.0",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": {}, "dependencies": {},
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.pipeline": {
"version": "0.10.0-exp.1",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.test-framework": "1.1.33",
"com.unity.nuget.mono-cecil": "1.11.6",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.nuget.newtonsoft-json": "3.0.2"
},
"url": "https://packages.unity.com"
},
"com.unity.profiling.core": { "com.unity.profiling.core": {
"version": "1.0.3", "version": "1.0.3",
"depth": 1, "depth": 1,
@ -332,7 +346,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.searcher": { "com.unity.searcher": {
"version": "4.9.4", "version": "4.9.5",
"depth": 2, "depth": 2,
"source": "registry", "source": "registry",
"dependencies": {}, "dependencies": {},
@ -355,7 +369,7 @@
} }
}, },
"com.unity.splines": { "com.unity.splines": {
"version": "2.8.4", "version": "2.9.0",
"depth": 1, "depth": 1,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -376,7 +390,7 @@
} }
}, },
"com.unity.test-framework.performance": { "com.unity.test-framework.performance": {
"version": "3.4.0", "version": "3.5.0",
"depth": 3, "depth": 3,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {

View File

@ -66,6 +66,9 @@ PlayerSettings:
useOSAutorotation: 1 useOSAutorotation: 1
use32BitDisplayBuffer: 1 use32BitDisplayBuffer: 1
preserveFramebufferAlpha: 0 preserveFramebufferAlpha: 0
adjustIOSFPSUsingThermalState: 1
thermalStateSeriousIOSFPS: 30
thermalStateCriticalIOSFPS: 15
disableDepthAndStencilBuffers: 0 disableDepthAndStencilBuffers: 0
androidStartInFullscreen: 1 androidStartInFullscreen: 1
androidRenderOutsideSafeArea: 0 androidRenderOutsideSafeArea: 0

View File

@ -1,2 +1,2 @@
m_EditorVersion: 6000.3.13f1 m_EditorVersion: 6000.3.23f1
m_EditorVersionWithRevision: 6000.3.13f1 (8c4f11e4fb20) m_EditorVersionWithRevision: 6000.3.23f1 (09d2ecc7fb28)