auto: 2026-04-23 23:47 · scene: SampleScene · 20 files
This commit is contained in:
parent
9f689c1661
commit
a10c38605d
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e499cd2788426d8489d9f64bdae9471a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50dac50a87be5624191ce4a471d65653
|
||||
|
|
@ -16,6 +16,7 @@ GameObject:
|
|||
- component: {fileID: 2651140156555518892}
|
||||
- component: {fileID: 772289407653213039}
|
||||
- component: {fileID: 5843668731025413174}
|
||||
- component: {fileID: 7700000000000000002}
|
||||
m_Layer: 13
|
||||
m_Name: Enemy
|
||||
m_TagString: Player
|
||||
|
|
@ -277,3 +278,16 @@ AudioSource:
|
|||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
--- !u!114 &7700000000000000002
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ffad43bb006db4856a9c527b89b48db9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
maxHP: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,279 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1661912868639658944
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1658460978237467174}
|
||||
- component: {fileID: 1577774018119691272}
|
||||
- component: {fileID: 1605217082131907960}
|
||||
- component: {fileID: 1702612949800919892}
|
||||
- component: {fileID: 1724124757368974630}
|
||||
- component: {fileID: 2651140156555518892}
|
||||
- component: {fileID: 772289407653213039}
|
||||
- component: {fileID: 5843668731025413174}
|
||||
m_Layer: 13
|
||||
m_Name: Enemy
|
||||
m_TagString: Player
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1658460978237467174
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 5.508, y: 1.032, z: 1}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!212 &1577774018119691272
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 0
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 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: 0
|
||||
m_SelectedEditorRenderState: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 1907945055
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 5
|
||||
m_Sprite: {fileID: 21300000, guid: fe68c6e1242e94a9eab222e1f49440ff, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 1.28, y: 1.26}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!95 &1605217082131907960
|
||||
Animator:
|
||||
serializedVersion: 4
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: ed1bbb2dccb7a424a9969f916919f446, type: 2}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorControllerStateOnDisable: 0
|
||||
--- !u!50 &1702612949800919892
|
||||
Rigidbody2D:
|
||||
serializedVersion: 4
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_BodyType: 1
|
||||
m_Simulated: 1
|
||||
m_UseFullKinematicContacts: 1
|
||||
m_UseAutoMass: 0
|
||||
m_Mass: 1
|
||||
m_LinearDrag: 0
|
||||
m_AngularDrag: 0.05
|
||||
m_GravityScale: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_Interpolate: 1
|
||||
m_SleepingMode: 0
|
||||
m_CollisionDetection: 1
|
||||
m_Constraints: 4
|
||||
--- !u!70 &1724124757368974630
|
||||
CapsuleCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_UsedByComposite: 0
|
||||
m_Offset: {x: 0, y: -0.11}
|
||||
m_Size: {x: 0.45, y: 0.09}
|
||||
m_Direction: 0
|
||||
--- !u!114 &2651140156555518892
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: be4d02721cd9d4baa869d3b890cec48f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
minGroundNormalY: 0.65
|
||||
gravityModifier: 1
|
||||
velocity: {x: 0, y: 0}
|
||||
maxSpeed: 7
|
||||
jumpTakeOffSpeed: 7
|
||||
move: {x: 0, y: 0}
|
||||
jump: 0
|
||||
stopJump: 0
|
||||
--- !u!114 &772289407653213039
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: cd654acc1f7894a509f3420e5c9ffea6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
path: {fileID: 0}
|
||||
ouch: {fileID: 8300000, guid: b7f741588644cd64bbee6387cb54a96d, type: 3}
|
||||
--- !u!82 &5843668731025413174
|
||||
AudioSource:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1661912868639658944}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 4
|
||||
OutputAudioMixerGroup: {fileID: 0}
|
||||
m_audioClip: {fileID: 0}
|
||||
m_PlayOnAwake: 0
|
||||
m_Volume: 1
|
||||
m_Pitch: 1
|
||||
Loop: 0
|
||||
Mute: 0
|
||||
Spatialize: 0
|
||||
SpatializePostEffects: 0
|
||||
Priority: 128
|
||||
DopplerLevel: 1
|
||||
MinDistance: 1
|
||||
MaxDistance: 500
|
||||
Pan2D: 0
|
||||
rolloffMode: 0
|
||||
BypassEffects: 0
|
||||
BypassListenerEffects: 0
|
||||
BypassReverbZones: 0
|
||||
rolloffCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
panLevelCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
spreadCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
reverbZoneMixCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
|
|
@ -16,6 +16,7 @@ GameObject:
|
|||
- component: {fileID: 8509783501685719824}
|
||||
- component: {fileID: 6082575806313374961}
|
||||
- component: {fileID: 1824045667}
|
||||
- component: {fileID: 7700000000000000001}
|
||||
m_Layer: 13
|
||||
m_Name: Player
|
||||
m_TagString: Player
|
||||
|
|
@ -325,3 +326,22 @@ BoxCollider2D:
|
|||
m_AutoTiling: 0
|
||||
m_Size: {x: 0.32, y: 0.54}
|
||||
m_EdgeRadius: 0
|
||||
--- !u!114 &7700000000000000001
|
||||
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: b2c3d4e5f60718293a4b5c6d7e8f90a1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
size: {x: 1.2, y: 0.9}
|
||||
offsetDistance: 0.7
|
||||
activeDuration: 0.12
|
||||
damage: 1
|
||||
targetLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
|
|
|
|||
|
|
@ -0,0 +1,327 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1208144871472054
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4520396350849616}
|
||||
- component: {fileID: 114230831923080080}
|
||||
- component: {fileID: 212064061491315838}
|
||||
- component: {fileID: 95391780594314510}
|
||||
- component: {fileID: 50915408107096866}
|
||||
- component: {fileID: 8509783501685719824}
|
||||
- component: {fileID: 6082575806313374961}
|
||||
- component: {fileID: 1824045667}
|
||||
m_Layer: 13
|
||||
m_Name: Player
|
||||
m_TagString: Player
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4520396350849616
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1208144871472054}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -4.14, y: 3.39, z: 1}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &114230831923080080
|
||||
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: 709ee11994a2f44658e5fc9887c45081, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
minGroundNormalY: 0.9
|
||||
gravityModifier: 1
|
||||
velocity: {x: 0, y: 0}
|
||||
jumpAudio: {fileID: 8300000, guid: 67975c08d56ceb147bad38572d805aa8, type: 3}
|
||||
respawnAudio: {fileID: 8300000, guid: e18959d46b63f3c4c8cc020a433cf848, type: 3}
|
||||
ouchAudio: {fileID: 8300000, guid: 6c05149e5a2fba64ba172e25a61074b7, type: 3}
|
||||
maxSpeed: 3
|
||||
jumpTakeOffSpeed: 7
|
||||
jumpState: 0
|
||||
collider2d: {fileID: 0}
|
||||
audioSource: {fileID: 0}
|
||||
health: {fileID: 0}
|
||||
controlEnabled: 1
|
||||
InputAsset: {fileID: -944628639613478452, guid: e56a71532e878ca498ffce08f1e0f519,
|
||||
type: 3}
|
||||
--- !u!212 &212064061491315838
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1208144871472054}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 0
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 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: 0
|
||||
m_SelectedEditorRenderState: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 1907945055
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 5
|
||||
m_Sprite: {fileID: 21300020, guid: ba86c7b200abe499cb750833482830b3, type: 3}
|
||||
m_Color: {r: 0.18039216, g: 0.8901961, b: 0.99215686, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 1.28, y: 1.26}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
--- !u!95 &95391780594314510
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1208144871472054}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000, guid: b09e60546065cf9448b36ebb7f759a91, type: 2}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_AnimatePhysics: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!50 &50915408107096866
|
||||
Rigidbody2D:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1208144871472054}
|
||||
m_BodyType: 1
|
||||
m_Simulated: 1
|
||||
m_UseFullKinematicContacts: 1
|
||||
m_UseAutoMass: 0
|
||||
m_Mass: 1
|
||||
m_LinearDamping: 0
|
||||
m_AngularDamping: 0.05
|
||||
m_GravityScale: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_Interpolate: 1
|
||||
m_SleepingMode: 0
|
||||
m_CollisionDetection: 1
|
||||
m_Constraints: 4
|
||||
--- !u!82 &8509783501685719824
|
||||
AudioSource:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1208144871472054}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 4
|
||||
OutputAudioMixerGroup: {fileID: 0}
|
||||
m_audioClip: {fileID: 0}
|
||||
m_Resource: {fileID: 0}
|
||||
m_PlayOnAwake: 0
|
||||
m_Volume: 1
|
||||
m_Pitch: 1
|
||||
Loop: 0
|
||||
Mute: 0
|
||||
Spatialize: 0
|
||||
SpatializePostEffects: 0
|
||||
Priority: 128
|
||||
DopplerLevel: 1
|
||||
MinDistance: 1
|
||||
MaxDistance: 500
|
||||
Pan2D: 0
|
||||
rolloffMode: 0
|
||||
BypassEffects: 0
|
||||
BypassListenerEffects: 0
|
||||
BypassReverbZones: 0
|
||||
rolloffCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
panLevelCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
spreadCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
reverbZoneMixCustomCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
--- !u!114 &6082575806313374961
|
||||
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: ffad43bb006db4856a9c527b89b48db9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
maxHP: 1
|
||||
--- !u!61 &1824045667
|
||||
BoxCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1208144871472054}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 0}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: -0.09, y: -0.14}
|
||||
m_SpriteTilingProperty:
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
oldSize: {x: 1.28, y: 1.26}
|
||||
newSize: {x: 1.28, y: 1.26}
|
||||
adaptiveTilingThreshold: 0.5
|
||||
drawMode: 0
|
||||
adaptiveTiling: 0
|
||||
m_AutoTiling: 0
|
||||
m_Size: {x: 0.32, y: 0.54}
|
||||
m_EdgeRadius: 0
|
||||
|
|
@ -4244,7 +4244,7 @@ SpriteRenderer:
|
|||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_Sprite: {fileID: 21300000, guid: 443583d5024ec0b46889a8bed11f2d5d, type: 3}
|
||||
m_Sprite: {fileID: 21300020, guid: ba86c7b200abe499cb750833482830b3, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
using Platformer.Core;
|
||||
using Platformer.Mechanics;
|
||||
using UnityEngine;
|
||||
using static Platformer.Core.Simulation;
|
||||
|
||||
namespace Platformer.Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Fired when the player triggers an attack (mouse left click / touch attack button).
|
||||
/// EerieVillage BT5-Dev 2단계 신설 — 기획 04 §5 근거리 공격 1종 파일럿.
|
||||
/// OnExecute 훅으로 카드 효과·특성 효과가 결합될 확장 지점 (개발 02 §2-1).
|
||||
/// </summary>
|
||||
public class PlayerAttack : Simulation.Event<PlayerAttack>
|
||||
{
|
||||
public PlayerController player;
|
||||
public Vector2 direction; // 플레이어 facing 방향 (±1, 0)
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
// 공격 애니메이션 트리거 (Animator에 "attack" trigger 있으면 재생 — 정적 스프라이트면 무시)
|
||||
if (player.animator != null)
|
||||
{
|
||||
var attackHash = Animator.StringToHash("attack");
|
||||
// SetTrigger는 미존재 파라미터여도 예외 없음
|
||||
player.animator.SetTrigger(attackHash);
|
||||
}
|
||||
|
||||
// 공격 효과음 (존재 시)
|
||||
if (player.audioSource != null && player.attackAudio != null)
|
||||
{
|
||||
player.audioSource.PlayOneShot(player.attackAudio);
|
||||
}
|
||||
|
||||
// 플레이어 앞에 판정 박스 발생
|
||||
if (player.attackHitbox != null)
|
||||
{
|
||||
player.attackHitbox.Fire(direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a1b2c3d4e5f60718293a4b5c6d7e8f90
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -9,6 +9,9 @@ namespace Platformer.Gameplay
|
|||
|
||||
/// <summary>
|
||||
/// Fired when a Player collides with an Enemy.
|
||||
/// BT5-Dev 2단계 개정: 기획 04 §3·§5 준수 — "위에서 밟기" 판정 폐기, i-frame 체크된 피격 로직으로 교체.
|
||||
/// 적 처치는 PlayerAttack 이벤트 + AttackHitbox 공격 판정 경로로 일원화.
|
||||
/// 적과 접촉 시 플레이어는 i-frame 내라면 피해 없음, 아니면 라이프 1 → 사망 체인 발동.
|
||||
/// </summary>
|
||||
/// <typeparam name="EnemyCollision"></typeparam>
|
||||
public class PlayerEnemyCollision : Simulation.Event<PlayerEnemyCollision>
|
||||
|
|
@ -20,34 +23,17 @@ namespace Platformer.Gameplay
|
|||
|
||||
public override void Execute()
|
||||
{
|
||||
var willHurtEnemy = player.Bounds.center.y >= enemy.Bounds.max.y;
|
||||
if (player == null || player.health == null) return;
|
||||
|
||||
if (willHurtEnemy)
|
||||
{
|
||||
var enemyHealth = enemy.GetComponent<Health>();
|
||||
if (enemyHealth != null)
|
||||
{
|
||||
enemyHealth.Decrement();
|
||||
if (!enemyHealth.IsAlive)
|
||||
{
|
||||
Schedule<EnemyDeath>().enemy = enemy;
|
||||
player.Bounce(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
player.Bounce(7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Schedule<EnemyDeath>().enemy = enemy;
|
||||
player.Bounce(2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Schedule<PlayerDeath>();
|
||||
}
|
||||
// i-frame 내에는 피해 무효 (Health.Decrement가 내부에서 체크)
|
||||
// — 접촉 지속 동안 연속 히트되는 것을 방지
|
||||
if (player.health.IsInvulnerable) return;
|
||||
|
||||
// 적과 접촉 → 플레이어 피해 (Health.Decrement가 i-frame 활성화)
|
||||
player.health.Decrement();
|
||||
|
||||
// HP 0 도달 시 HealthIsZero 이벤트가 PlayerDeath 체인을 발동 (기존 경로)
|
||||
// 여기서 Schedule<PlayerDeath> 직접 호출은 중복이므로 제거 — Health 이벤트 체인 신뢰
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
using System.Collections.Generic;
|
||||
using Platformer.Gameplay;
|
||||
using UnityEngine;
|
||||
using static Platformer.Core.Simulation;
|
||||
|
||||
namespace Platformer.Mechanics
|
||||
{
|
||||
/// <summary>
|
||||
/// 플레이어 근거리 공격 판정 박스.
|
||||
/// PlayerAttack 이벤트에서 Fire(direction)를 호출하면 지정 활성 지속 시간 동안
|
||||
/// OverlapBox 로 적을 감지하고, Health 보유 적에 Decrement 적용 → EnemyDeath 체인.
|
||||
/// 기획 04 §5-1 근거리 공격 1종 — 쿨타임·대미지·판정 박스는 Phase 3-B 튠 대상.
|
||||
/// </summary>
|
||||
public class AttackHitbox : MonoBehaviour
|
||||
{
|
||||
[Header("판정 박스 크기 (플레이어 기준 로컬)")]
|
||||
public Vector2 size = new Vector2(1.2f, 0.9f);
|
||||
[Tooltip("플레이어 중심으로부터 공격 방향으로의 오프셋 거리")]
|
||||
public float offsetDistance = 0.7f;
|
||||
[Tooltip("판정 활성 지속 시간 (초). 정적 스프라이트 기반이면 짧게 유지")]
|
||||
public float activeDuration = 0.12f;
|
||||
[Tooltip("대미지 (Health.Decrement 호출 횟수)")]
|
||||
public int damage = 1;
|
||||
|
||||
[Header("타격 대상 레이어 마스크")]
|
||||
public LayerMask targetLayers = ~0; // 전 레이어 기본. 실전에서 Enemy 레이어로 제한 권장
|
||||
|
||||
float activeUntil = -1f;
|
||||
Vector2 lastDirection = Vector2.right;
|
||||
|
||||
// 같은 스윙으로 동일 Health 중복 타격 방지
|
||||
readonly HashSet<Health> alreadyHit = new HashSet<Health>();
|
||||
|
||||
/// <summary>
|
||||
/// PlayerAttack.Execute 에서 호출. direction은 플레이어 facing (x축 ±1 or 0).
|
||||
/// </summary>
|
||||
public void Fire(Vector2 direction)
|
||||
{
|
||||
if (Mathf.Abs(direction.x) > 0.01f) lastDirection = new Vector2(Mathf.Sign(direction.x), 0);
|
||||
activeUntil = Time.time + activeDuration;
|
||||
alreadyHit.Clear();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Time.time > activeUntil) return;
|
||||
|
||||
// 로컬 오프셋: 플레이어 중심 + facing * offsetDistance
|
||||
var center = (Vector2)transform.position + lastDirection * offsetDistance;
|
||||
|
||||
// OverlapBox로 적 검출
|
||||
var hits = Physics2D.OverlapBoxAll(center, size, 0f, targetLayers);
|
||||
foreach (var col in hits)
|
||||
{
|
||||
if (col == null) continue;
|
||||
// 자기 자신 collider 제외 (PlayerController 부착 GameObject)
|
||||
if (col.transform == transform || col.transform.IsChildOf(transform)) continue;
|
||||
|
||||
var health = col.GetComponent<Health>();
|
||||
if (health == null || !health.IsAlive) continue;
|
||||
if (alreadyHit.Contains(health)) continue;
|
||||
|
||||
alreadyHit.Add(health);
|
||||
for (int i = 0; i < damage; i++)
|
||||
{
|
||||
health.Decrement();
|
||||
if (!health.IsAlive) break;
|
||||
}
|
||||
|
||||
// Enemy 즉사 시 EnemyController 기반 EnemyDeath 체인 발동 (선택)
|
||||
if (!health.IsAlive)
|
||||
{
|
||||
var enemy = col.GetComponent<EnemyController>();
|
||||
if (enemy != null)
|
||||
{
|
||||
Schedule<EnemyDeath>().enemy = enemy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scene view 가시화 — 활성 상태에서 박스 표시
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.color = (Application.isPlaying && Time.time <= activeUntil)
|
||||
? new Color(1f, 0.3f, 0.3f, 0.6f)
|
||||
: new Color(1f, 1f, 1f, 0.2f);
|
||||
var dir = Application.isPlaying ? lastDirection : Vector2.right;
|
||||
var center = (Vector2)transform.position + dir * offsetDistance;
|
||||
Gizmos.DrawWireCube(center, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b2c3d4e5f60718293a4b5c6d7e8f90a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -15,12 +15,24 @@ namespace Platformer.Mechanics
|
|||
/// </summary>
|
||||
public int maxHP = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 무적 시간 (i-frame) 지속 초 단위. 기획 04 §3-2 후보 0.4~0.8s.
|
||||
/// 라이프 1 전제에서 연속 히트 인정 금지를 위한 핵심 장치 (BT5-Dev 2단계 신설).
|
||||
/// </summary>
|
||||
public float invulnerableDuration = 0.6f;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 무적 상태 여부 (디버그·UX 피드백용 — 깜박임 제어 등에 사용 가능).
|
||||
/// </summary>
|
||||
public bool IsInvulnerable => Time.time < invulnerableUntil;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the entity should be considered 'alive'.
|
||||
/// </summary>
|
||||
public bool IsAlive => currentHP > 0;
|
||||
|
||||
int currentHP;
|
||||
float invulnerableUntil = -1f;
|
||||
|
||||
/// <summary>
|
||||
/// Increment the HP of the entity.
|
||||
|
|
@ -32,11 +44,24 @@ namespace Platformer.Mechanics
|
|||
|
||||
/// <summary>
|
||||
/// Decrement the HP of the entity. Will trigger a HealthIsZero event when
|
||||
/// current HP reaches 0.
|
||||
/// current HP reaches 0. 무적 시간 (i-frame) 내에는 호출되어도 스킵된다.
|
||||
/// </summary>
|
||||
public void Decrement()
|
||||
{
|
||||
// BT5-Dev 2단계: i-frame 보호 — 무적 시간 내 중복 피격 차단
|
||||
if (Time.time < invulnerableUntil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentHP = Mathf.Clamp(currentHP - 1, 0, maxHP);
|
||||
|
||||
// 피격 성공 시 무적 시간 활성화 (다음 피격 대비)
|
||||
if (invulnerableDuration > 0f)
|
||||
{
|
||||
invulnerableUntil = Time.time + invulnerableDuration;
|
||||
}
|
||||
|
||||
if (currentHP == 0)
|
||||
{
|
||||
var ev = Schedule<HealthIsZero>();
|
||||
|
|
@ -46,10 +71,21 @@ namespace Platformer.Mechanics
|
|||
|
||||
/// <summary>
|
||||
/// Decrement the HP of the entitiy until HP reaches 0.
|
||||
/// i-frame 우회하여 즉사 처리 (낙사·승리 이탈 등 시스템 강제 사망).
|
||||
/// </summary>
|
||||
public void Die()
|
||||
{
|
||||
while (currentHP > 0) Decrement();
|
||||
invulnerableUntil = -1f; // i-frame 무효화
|
||||
while (currentHP > 0)
|
||||
{
|
||||
currentHP = Mathf.Clamp(currentHP - 1, 0, maxHP);
|
||||
if (currentHP == 0)
|
||||
{
|
||||
var ev = Schedule<HealthIsZero>();
|
||||
ev.health = this;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Awake()
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ namespace Platformer.Mechanics
|
|||
public AudioClip jumpAudio;
|
||||
public AudioClip respawnAudio;
|
||||
public AudioClip ouchAudio;
|
||||
/// <summary>
|
||||
/// Attack sound effect (BT5-Dev 2단계 신설). 미지정 시 무음.
|
||||
/// </summary>
|
||||
public AudioClip attackAudio;
|
||||
|
||||
/// <summary>
|
||||
/// Max horizontal speed of the player.
|
||||
|
|
@ -28,6 +32,16 @@ namespace Platformer.Mechanics
|
|||
/// </summary>
|
||||
public float jumpTakeOffSpeed = 7;
|
||||
|
||||
/// <summary>
|
||||
/// Cooldown between attacks in seconds (기획 04 §5-1 Phase 3-B 튠 대상).
|
||||
/// </summary>
|
||||
public float attackCooldown = 0.35f;
|
||||
|
||||
/// <summary>
|
||||
/// Attack hitbox component (자동 GetComponent, 없으면 null — PlayerAttack.Execute에서 null 체크).
|
||||
/// </summary>
|
||||
public AttackHitbox attackHitbox;
|
||||
|
||||
public JumpState jumpState = JumpState.Grounded;
|
||||
private bool stopJump;
|
||||
/*internal new*/ public Collider2D collider2d;
|
||||
|
|
@ -43,6 +57,12 @@ namespace Platformer.Mechanics
|
|||
|
||||
private InputAction m_MoveAction;
|
||||
private InputAction m_JumpAction;
|
||||
private InputAction m_AttackAction;
|
||||
|
||||
// 마지막 공격 시각 — attackCooldown과 비교해 연타 제한
|
||||
float nextAttackTime = 0f;
|
||||
// 현재 facing 방향 (마지막 이동 입력 기반, 정지 시 이전 값 유지)
|
||||
Vector2 facing = Vector2.right;
|
||||
|
||||
public Bounds Bounds => collider2d.bounds;
|
||||
|
||||
|
|
@ -53,12 +73,15 @@ namespace Platformer.Mechanics
|
|||
collider2d = GetComponent<Collider2D>();
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
animator = GetComponent<Animator>();
|
||||
if (attackHitbox == null) attackHitbox = GetComponent<AttackHitbox>();
|
||||
|
||||
m_MoveAction = InputSystem.actions.FindAction("Player/Move");
|
||||
m_JumpAction = InputSystem.actions.FindAction("Player/Jump");
|
||||
|
||||
m_AttackAction = InputSystem.actions.FindAction("Player/Attack");
|
||||
|
||||
m_MoveAction.Enable();
|
||||
m_JumpAction.Enable();
|
||||
if (m_AttackAction != null) m_AttackAction.Enable();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
|
@ -73,6 +96,15 @@ namespace Platformer.Mechanics
|
|||
stopJump = true;
|
||||
Schedule<PlayerStopJump>().player = this;
|
||||
}
|
||||
|
||||
// 공격 입력 처리 (마우스 좌클릭 / 게임패드 RT / 모바일 터치 — Phase 3-B UX)
|
||||
if (m_AttackAction != null && m_AttackAction.WasPressedThisFrame() && Time.time >= nextAttackTime)
|
||||
{
|
||||
nextAttackTime = Time.time + attackCooldown;
|
||||
var ev = Schedule<PlayerAttack>();
|
||||
ev.player = this;
|
||||
ev.direction = facing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -129,9 +161,15 @@ namespace Platformer.Mechanics
|
|||
}
|
||||
|
||||
if (move.x > 0.01f)
|
||||
{
|
||||
spriteRenderer.flipX = false;
|
||||
facing = Vector2.right;
|
||||
}
|
||||
else if (move.x < -0.01f)
|
||||
{
|
||||
spriteRenderer.flipX = true;
|
||||
facing = Vector2.left;
|
||||
}
|
||||
|
||||
animator.SetBool("grounded", IsGrounded);
|
||||
animator.SetFloat("velocityX", Mathf.Abs(velocity.x) / maxSpeed);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@
|
|||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "Attack",
|
||||
"type": "Button",
|
||||
"id": "c9d8e7f6-a5b4-4c3d-2e1f-0a9b8c7d6e5f",
|
||||
"expectedControlType": "",
|
||||
"processors": "",
|
||||
"interactions": "",
|
||||
"initialStateCheck": false
|
||||
},
|
||||
{
|
||||
"name": "Menu",
|
||||
"type": "Button",
|
||||
|
|
@ -200,6 +209,28 @@
|
|||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "d7e6f5a4-b3c2-4d1e-9f8a-7b6c5d4e3f2a",
|
||||
"path": "<Mouse>/leftButton",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": ";Keyboard&Mouse",
|
||||
"action": "Attack",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "e8f7a6b5-c4d3-4e2f-1a9b-8c7d6e5f4a3b",
|
||||
"path": "<Gamepad>/rightTrigger",
|
||||
"interactions": "",
|
||||
"processors": "",
|
||||
"groups": ";Gamepad",
|
||||
"action": "Attack",
|
||||
"isComposite": false,
|
||||
"isPartOfComposite": false
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"id": "bf91b079-c2a3-41a7-ab9e-6e5fbc7e9f4b",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "EerieVillage.Tests.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
/// <summary>
|
||||
/// EerieVillage BT5-Dev 2단계 — Player 근거리 공격 체계 EditMode 테스트.
|
||||
/// Prefab 자산의 컴포넌트 구성이 기획 04 §5-1 (근거리 공격 1종) 을 충족하는지 검증.
|
||||
/// Play 모드 실행 불요 — prefab YAML 직렬화 상태를 직접 검증하여 회귀 방지.
|
||||
/// </summary>
|
||||
public class PlayerAttackTests
|
||||
{
|
||||
const string PlayerPrefabPath = "Assets/Prefabs/Player.prefab";
|
||||
const string EnemyPrefabPath = "Assets/Prefabs/Enemy.prefab";
|
||||
|
||||
[Test]
|
||||
public void Player_Prefab_Has_AttackHitbox_Component()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||||
Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}");
|
||||
|
||||
var hitbox = prefab.GetComponent<Platformer.Mechanics.AttackHitbox>();
|
||||
Assert.IsNotNull(hitbox,
|
||||
"Player.prefab에 AttackHitbox 컴포넌트가 누락. " +
|
||||
"BT5-Dev 2단계 재위임 집행분 (2026-04-23) 이 prefab YAML 에 반영되어야 함.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Player_Prefab_Has_Health_Component()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||||
Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}");
|
||||
|
||||
var health = prefab.GetComponent<Platformer.Mechanics.Health>();
|
||||
Assert.IsNotNull(health, "Player.prefab 에 Health 컴포넌트 누락 (템플릿 기본).");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Player_Prefab_Has_PlayerController_Component()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||||
Assert.IsNotNull(prefab);
|
||||
|
||||
var controller = prefab.GetComponent<Platformer.Mechanics.PlayerController>();
|
||||
Assert.IsNotNull(controller, "Player.prefab 에 PlayerController 컴포넌트 누락.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AttackHitbox_Default_Damage_Is_One()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||||
var hitbox = prefab.GetComponent<Platformer.Mechanics.AttackHitbox>();
|
||||
Assert.IsNotNull(hitbox);
|
||||
|
||||
Assert.AreEqual(1, hitbox.damage,
|
||||
"기본 대미지 1 (기획 04 §5-1, Phase 3-B 튠 전 파일럿 값).");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AttackHitbox_Active_Duration_Is_Positive()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||||
var hitbox = prefab.GetComponent<Platformer.Mechanics.AttackHitbox>();
|
||||
Assert.IsNotNull(hitbox);
|
||||
|
||||
Assert.Greater(hitbox.activeDuration, 0f,
|
||||
"activeDuration 가 0 이하면 OverlapBox 판정이 즉시 종료되어 공격 무효.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Enemy_Prefab_Has_Health_Component()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(EnemyPrefabPath);
|
||||
Assert.IsNotNull(prefab, $"Enemy.prefab not found at {EnemyPrefabPath}");
|
||||
|
||||
var health = prefab.GetComponent<Platformer.Mechanics.Health>();
|
||||
Assert.IsNotNull(health,
|
||||
"Enemy.prefab 에 Health 컴포넌트 누락. " +
|
||||
"BT5-Dev 2단계 재위임 집행분 (2026-04-23) 이 prefab YAML 에 반영되어야 함. " +
|
||||
"Health 없으면 AttackHitbox.Update 의 Decrement 호출이 불가 → EnemyDeath 체인 미발동.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Enemy_Prefab_Health_MaxHP_Is_One()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(EnemyPrefabPath);
|
||||
var health = prefab.GetComponent<Platformer.Mechanics.Health>();
|
||||
Assert.IsNotNull(health);
|
||||
|
||||
Assert.AreEqual(1, health.maxHP,
|
||||
"일반 적 기본 maxHP 1 (코어 룰 7 정합, 첫 세팅).");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Enemy_Prefab_Has_EnemyController_Component()
|
||||
{
|
||||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(EnemyPrefabPath);
|
||||
var controller = prefab.GetComponent<Platformer.Mechanics.EnemyController>();
|
||||
Assert.IsNotNull(controller,
|
||||
"EnemyDeath 체인에 EnemyController 필수 (AttackHitbox.Update 에서 Schedule<EnemyDeath>().enemy = enemy).");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8d0fdca71e4a88641bbbad43fd38037f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 091ef1a2cf1de204dbf3ad2e613d095c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in New Issue