diff --git a/Assets/0.SCENE/MainGame.unity b/Assets/0.SCENE/MainGame.unity index 666e92c0..2413d4bd 100644 --- a/Assets/0.SCENE/MainGame.unity +++ b/Assets/0.SCENE/MainGame.unity @@ -157294,6 +157294,50 @@ Transform: m_CorrespondingSourceObject: {fileID: 4342764212392476, guid: 4278c6284d6d0874e930abe05bd1e995, type: 3} m_PrefabInstance: {fileID: 288143037} m_PrefabAsset: {fileID: 0} +--- !u!1 &1467171476 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1467171478} + - component: {fileID: 1467171477} + m_Layer: 0 + m_Name: BossDataManger + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1467171477 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1467171476} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c23a9c1b76724ab459bf32a732f6a2f7, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1467171478 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1467171476} + 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!1001 &1467480949 PrefabInstance: m_ObjectHideFlags: 0 @@ -219472,6 +219516,100 @@ Transform: m_CorrespondingSourceObject: {fileID: 4917135111635402, guid: 4fb7e29eb03a19e4099b10ed3f307852, type: 3} m_PrefabInstance: {fileID: 2078546377} m_PrefabAsset: {fileID: 0} +--- !u!1001 &2078726753 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalPosition.x + value: 22.611275 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalPosition.y + value: 7.2501984 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalPosition.z + value: 14.457466 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919132149155446097, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + propertyPath: m_Name + value: BossMonster3 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + insertIndex: -1 + addedObject: {fileID: 2078726755} + m_SourcePrefab: {fileID: 100100000, guid: 42503441aeeebad428b07b02a39d6598, type: 3} +--- !u!1 &2078726754 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 42503441aeeebad428b07b02a39d6598, type: 3} + m_PrefabInstance: {fileID: 2078726753} + m_PrefabAsset: {fileID: 0} +--- !u!114 &2078726755 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2078726754} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04f39bf969074e6488f84b47bd517dc9, type: 3} + m_Name: + m_EditorClassIdentifier: + optimizationDistance: 40 + maxHP: 100 + attackDamage: 10 + expReward: 10 + moveSpeed: 3.5 + myWeapon: {fileID: 0} + Monster_Idle: Monster_Idle + Monster_GetDamage: Monster_GetDamage + Monster_Die: Monster_Die + attackRestDuration: 1.5 + hitSound: {fileID: 0} + deathSound: {fileID: 0} + deathEffectPrefab: {fileID: 0} + hitEffect: {fileID: 0} + impactSpawnPoint: {fileID: 0} + counterSystem: {fileID: 0} + patternInterval: 3 --- !u!1001 &2078921403 PrefabInstance: m_ObjectHideFlags: 0 @@ -228052,6 +228190,7 @@ SceneRoots: - {fileID: 317692096} - {fileID: 2004000787} - {fileID: 850992421} + - {fileID: 1467171478} - {fileID: 1800120326328798950} - {fileID: 4755848957906863847} - {fileID: 398512784} @@ -228073,3 +228212,4 @@ SceneRoots: - {fileID: 200768984} - {fileID: 1759137305} - {fileID: 198901434} + - {fileID: 2078726753} diff --git a/Assets/1.myPrefab/MyMonster/BossMonster 3D model.prefab b/Assets/1.myPrefab/MyMonster/BossMonster 3D model.prefab new file mode 100644 index 00000000..a2b437dd --- /dev/null +++ b/Assets/1.myPrefab/MyMonster/BossMonster 3D model.prefab @@ -0,0 +1,101 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &566391006787012280 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalPosition.x + value: 21.990122 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalPosition.y + value: 8.148115 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalPosition.z + value: 12.154666 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919132149155446097, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_Name + value: BossMonster 3D model + objectReference: {fileID: 0} + - target: {fileID: 5866666021909216657, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + propertyPath: m_Controller + value: + objectReference: {fileID: 9100000, guid: b207531287111e74d890e730f7278dfa, type: 2} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + insertIndex: -1 + addedObject: {fileID: 8863122437628348909} + m_SourcePrefab: {fileID: 100100000, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} +--- !u!1 &800884610308848617 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 1cbe1e69b0d0be345be0872afa3e381e, type: 3} + m_PrefabInstance: {fileID: 566391006787012280} + m_PrefabAsset: {fileID: 0} +--- !u!114 &8863122437628348909 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 800884610308848617} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04f39bf969074e6488f84b47bd517dc9, type: 3} + m_Name: + m_EditorClassIdentifier: + optimizationDistance: 40 + maxHP: 100 + attackDamage: 10 + expReward: 10 + moveSpeed: 3.5 + myWeapon: {fileID: 0} + Monster_Idle: Monster_Idle + Monster_GetDamage: Monster_GetDamage + Monster_Die: Monster_Die + attackRestDuration: 1.5 + hitSound: {fileID: 0} + deathSound: {fileID: 0} + deathEffectPrefab: {fileID: 0} + hitEffect: {fileID: 0} + impactSpawnPoint: {fileID: 0} + counterSystem: {fileID: 0} + patternInterval: 3 + bossHealthBar: {fileID: 0} diff --git a/Assets/1.myPrefab/MyMonster/BossMonster 3D model.prefab.meta b/Assets/1.myPrefab/MyMonster/BossMonster 3D model.prefab.meta new file mode 100644 index 00000000..2521b3ee --- /dev/null +++ b/Assets/1.myPrefab/MyMonster/BossMonster 3D model.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bbcb1e950f1b5a24881632ef960a27aa +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/1.myPrefab/MyMonster/BossMonsterAnimater.controller b/Assets/1.myPrefab/MyMonster/BossMonsterAnimater.controller new file mode 100644 index 00000000..78363cd2 --- /dev/null +++ b/Assets/1.myPrefab/MyMonster/BossMonsterAnimater.controller @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!91 &9100000 +AnimatorController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: BossMonsterAnimater + serializedVersion: 5 + m_AnimatorParameters: [] + m_AnimatorLayers: + - serializedVersion: 5 + m_Name: Base Layer + m_StateMachine: {fileID: 7444453749730313805} + m_Mask: {fileID: 0} + m_Motions: [] + m_Behaviours: [] + m_BlendingMode: 0 + m_SyncedLayerIndex: -1 + m_DefaultWeight: 0 + m_IKPass: 0 + m_SyncedLayerAffectsTiming: 0 + m_Controller: {fileID: 9100000} +--- !u!1107 &7444453749730313805 +AnimatorStateMachine: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Base Layer + m_ChildStates: [] + m_ChildStateMachines: [] + m_AnyStateTransitions: [] + m_EntryTransitions: [] + m_StateMachineTransitions: {} + m_StateMachineBehaviours: [] + m_AnyStatePosition: {x: 50, y: 20, z: 0} + m_EntryPosition: {x: 50, y: 120, z: 0} + m_ExitPosition: {x: 510, y: 310, z: 0} + m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} + m_DefaultState: {fileID: 0} diff --git a/Assets/1.myPrefab/MyMonster/BossMonsterAnimater.controller.meta b/Assets/1.myPrefab/MyMonster/BossMonsterAnimater.controller.meta new file mode 100644 index 00000000..051c9cc5 --- /dev/null +++ b/Assets/1.myPrefab/MyMonster/BossMonsterAnimater.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b207531287111e74d890e730f7278dfa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 9100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/1.myPrefab/MyMonster/RushMonster2.prefab b/Assets/1.myPrefab/MyMonster/RushMonster2.prefab index 79a067e2..19e52fa0 100644 --- a/Assets/1.myPrefab/MyMonster/RushMonster2.prefab +++ b/Assets/1.myPrefab/MyMonster/RushMonster2.prefab @@ -900,6 +900,7 @@ MonoBehaviour: prepareTime: 3 dropItemPrefabs: - {fileID: 791703799912573729, guid: e9867839af14eb14ca3d49ee41fc5390, type: 3} + - {fileID: 1171483609561952824, guid: 5d18660a7620e4e48bb1462c7e0e1187, type: 3} dropChance: 100 chargeAnimation: Run-run prepareAnimation: Run-wait diff --git a/Assets/1.myPrefab/New Random Stat Card Data 1.asset b/Assets/1.myPrefab/New Random Stat Card Data 1.asset index 548c9f4e..4fc69279 100644 --- a/Assets/1.myPrefab/New Random Stat Card Data 1.asset +++ b/Assets/1.myPrefab/New Random Stat Card Data 1.asset @@ -13,6 +13,7 @@ MonoBehaviour: m_Name: New Random Stat Card Data 1 m_EditorClassIdentifier: icon: {fileID: 21300000, guid: 15546573e2e8b0c489f921128d1e5073, type: 3} - possibleStats: 0200000000000000 + requiredObsessionLevel: 1 + possibleStats: 020000000000000001000000 minValue: -30 maxValue: 1 diff --git a/Assets/1.myPrefab/New Random Stat Card Data.asset b/Assets/1.myPrefab/New Random Stat Card Data.asset index 5ec0c0bf..ef467ef2 100644 --- a/Assets/1.myPrefab/New Random Stat Card Data.asset +++ b/Assets/1.myPrefab/New Random Stat Card Data.asset @@ -13,6 +13,7 @@ MonoBehaviour: m_Name: New Random Stat Card Data m_EditorClassIdentifier: icon: {fileID: 21300000, guid: 15546573e2e8b0c489f921128d1e5073, type: 3} - possibleStats: 03000000010000000000000002000000 + requiredObsessionLevel: 1 + possibleStats: 020000000100000000000000 minValue: -10 maxValue: 1 diff --git a/Assets/1.myPrefab/Player.prefab b/Assets/1.myPrefab/Player.prefab index 18b98899..aa21d6b8 100644 --- a/Assets/1.myPrefab/Player.prefab +++ b/Assets/1.myPrefab/Player.prefab @@ -1231,6 +1231,9 @@ PrefabInstance: insertIndex: -1 addedObject: {fileID: 7115393052906583336} m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 76cee5628aa6b874c96342f004fa138b, type: 3} + insertIndex: -1 + addedObject: {fileID: -903076858900737616} - targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 76cee5628aa6b874c96342f004fa138b, type: 3} insertIndex: -1 addedObject: {fileID: 8017155627325348063} @@ -1270,6 +1273,19 @@ GameObject: m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 76cee5628aa6b874c96342f004fa138b, type: 3} m_PrefabInstance: {fileID: 1112926104530361804} m_PrefabAsset: {fileID: 0} +--- !u!114 &-903076858900737616 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 265854990890279069} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 320dac90fad4bd94dbdc466f5f2458cd, type: 3} + m_Name: + m_EditorClassIdentifier: + windowDuration: 10 --- !u!114 &8017155627325348063 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1367,6 +1383,7 @@ MonoBehaviour: stats: {fileID: 395629277865203624} animator: {fileID: 6781151982184439901} attackScript: {fileID: 0} + bossPattern: {fileID: 0} isInvincible: 0 --- !u!114 &7686364893196566162 MonoBehaviour: diff --git a/Assets/3D Assets/BossMonster 3D model.fbx b/Assets/3D Assets/BossMonster 3D model.fbx new file mode 100644 index 00000000..3e3074ed Binary files /dev/null and b/Assets/3D Assets/BossMonster 3D model.fbx differ diff --git a/Assets/3D Assets/BossMonster 3D model.fbx.meta b/Assets/3D Assets/BossMonster 3D model.fbx.meta new file mode 100644 index 00000000..d8fc4f3f --- /dev/null +++ b/Assets/3D Assets/BossMonster 3D model.fbx.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: 1cbe1e69b0d0be345be0872afa3e381e +ModelImporter: + serializedVersion: 22200 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 3 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 0 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 1 + importBlendShapes: 1 + importCameras: 1 + importLights: 1 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 0 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 1 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 3 + humanoidOversampling: 1 + avatarSetup: 1 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/3D Assets/material0_basecolor.jpg b/Assets/3D Assets/material0_basecolor.jpg new file mode 100644 index 00000000..b2f973d4 Binary files /dev/null and b/Assets/3D Assets/material0_basecolor.jpg differ diff --git a/Assets/3D Assets/material0_basecolor.jpg.meta b/Assets/3D Assets/material0_basecolor.jpg.meta new file mode 100644 index 00000000..9d0fdaee --- /dev/null +++ b/Assets/3D Assets/material0_basecolor.jpg.meta @@ -0,0 +1,114 @@ +fileFormatVersion: 2 +guid: bb7a32e0d6762f34f881755d070ffcf8 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + 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 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/4.PlayerAnimation/ThrowAnimation_Boss_BoyFBX.fbx b/Assets/4.PlayerAnimation/ThrowAnimation_Boss_BoyFBX.fbx new file mode 100644 index 00000000..9733dd5f Binary files /dev/null and b/Assets/4.PlayerAnimation/ThrowAnimation_Boss_BoyFBX.fbx differ diff --git a/Assets/4.PlayerAnimation/ThrowAnimation_Boss_BoyFBX.fbx.meta b/Assets/4.PlayerAnimation/ThrowAnimation_Boss_BoyFBX.fbx.meta new file mode 100644 index 00000000..761dbe2e --- /dev/null +++ b/Assets/4.PlayerAnimation/ThrowAnimation_Boss_BoyFBX.fbx.meta @@ -0,0 +1,991 @@ +fileFormatVersion: 2 +guid: 04227e99d65ec83448222e5a50c69dae +ModelImporter: + serializedVersion: 22200 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: "\nClip 'Take 001' has import animation warnings that + might lower retargeting quality:\nNote: Activate translation DOF on avatar + to improve retargeting quality.\n\t'Bip001 Spine' has translation animation + that will be discarded.\n\t'Bip001 Spine1' has translation animation that will + be discarded.\n\t'Bip001 Spine2' has translation animation that will be discarded.\n\t'Bip001 + Neck' has translation animation that will be discarded.\n\t'Bip001 Head' has + translation animation that will be discarded.\n\t'Bip001 L Clavicle' has translation + animation that will be discarded.\n\t'Bip001 L UpperArm' has translation animation + that will be discarded.\n\t'Bip001 L Forearm' has translation animation that + will be discarded.\n\t'Bip001 L Hand' has translation animation that will be + discarded.\n\t'Bip001 L Finger0' has translation animation that will be discarded.\n\t'Bip001 + L Finger01' has translation animation that will be discarded.\n\t'Bip001 L + Finger02' has translation animation that will be discarded.\n\t'Bip001 L Finger1' + has translation animation that will be discarded.\n\t'Bip001 L Finger11' has + translation animation that will be discarded.\n\t'Bip001 L Finger12' has translation + animation that will be discarded.\n\t'Bip001 L Finger2' has translation animation + that will be discarded.\n\t'Bip001 L Finger21' has translation animation that + will be discarded.\n\t'Bip001 L Finger22' has translation animation that will + be discarded.\n\t'Bip001 L Finger3' has translation animation that will be + discarded.\n\t'Bip001 L Finger31' has translation animation that will be discarded.\n\t'Bip001 + L Finger32' has translation animation that will be discarded.\n\t'Bip001 L + Finger4' has translation animation that will be discarded.\n\t'Bip001 L Finger41' + has translation animation that will be discarded.\n\t'Bip001 L Finger42' has + translation animation that will be discarded.\n\t'Bip001 R Clavicle' has translation + animation that will be discarded.\n\t'Bip001 R UpperArm' has translation animation + that will be discarded.\n\t'Bip001 R Forearm' has translation animation that + will be discarded.\n\t'Bip001 R Hand' has translation animation that will be + discarded.\n\t'Bip001 R Finger0' has translation animation that will be discarded.\n\t'Bip001 + R Finger01' has translation animation that will be discarded.\n\t'Bip001 R + Finger02' has translation animation that will be discarded.\n\t'Bip001 R Finger1' + has translation animation that will be discarded.\n\t'Bip001 R Finger11' has + translation animation that will be discarded.\n\t'Bip001 R Finger12' has translation + animation that will be discarded.\n\t'Bip001 R Finger2' has translation animation + that will be discarded.\n\t'Bip001 R Finger21' has translation animation that + will be discarded.\n\t'Bip001 R Finger22' has translation animation that will + be discarded.\n\t'Bip001 R Finger3' has translation animation that will be + discarded.\n\t'Bip001 R Finger31' has translation animation that will be discarded.\n\t'Bip001 + R Finger32' has translation animation that will be discarded.\n\t'Bip001 R + Finger4' has translation animation that will be discarded.\n\t'Bip001 R Finger41' + has translation animation that will be discarded.\n\t'Bip001 R Finger42' has + translation animation that will be discarded.\n\t'Bip001 L Thigh' has translation + animation that will be discarded.\n\t'Bip001 L Calf' has translation animation + that will be discarded.\n\t'Bip001 L Foot' has translation animation that will + be discarded.\n\t'Bip001 L Toe0' has translation animation that will be discarded.\n\t'Bip001 + R Thigh' has translation animation that will be discarded.\n\t'Bip001 R Calf' + has translation animation that will be discarded.\n\t'Bip001 R Foot' has translation + animation that will be discarded.\n\t'Bip001 R Toe0' has translation animation + that will be discarded.\n" + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 3 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: Take 001 + takeName: Take 001 + internalID: 1827226128182048838 + firstFrame: 0 + lastFrame: 204 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 1 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 1 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 1 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 + isReadable: 0 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 1 + importBlendShapes: 1 + importCameras: 1 + importLights: 1 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 0 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: + - boneName: Bip001 + humanName: Hips + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Thigh + humanName: LeftUpperLeg + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Thigh + humanName: RightUpperLeg + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Calf + humanName: LeftLowerLeg + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Calf + humanName: RightLowerLeg + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Foot + humanName: LeftFoot + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Foot + humanName: RightFoot + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 Spine + humanName: Spine + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 Spine1 + humanName: Chest + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 Neck + humanName: Neck + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 Head + humanName: Head + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Clavicle + humanName: LeftShoulder + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Clavicle + humanName: RightShoulder + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L UpperArm + humanName: LeftUpperArm + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R UpperArm + humanName: RightUpperArm + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Forearm + humanName: LeftLowerArm + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Forearm + humanName: RightLowerArm + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Hand + humanName: LeftHand + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Hand + humanName: RightHand + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Toe0 + humanName: LeftToes + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Toe0 + humanName: RightToes + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger1 + humanName: Left Thumb Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger11 + humanName: Left Thumb Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger12 + humanName: Left Thumb Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger0 + humanName: Left Index Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger01 + humanName: Left Index Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger02 + humanName: Left Index Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger4 + humanName: Left Middle Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger41 + humanName: Left Middle Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger42 + humanName: Left Middle Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger3 + humanName: Left Ring Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger31 + humanName: Left Ring Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger32 + humanName: Left Ring Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger2 + humanName: Left Little Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger21 + humanName: Left Little Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 L Finger22 + humanName: Left Little Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger1 + humanName: Right Thumb Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger11 + humanName: Right Thumb Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger12 + humanName: Right Thumb Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger0 + humanName: Right Index Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger01 + humanName: Right Index Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger02 + humanName: Right Index Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger2 + humanName: Right Middle Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger21 + humanName: Right Middle Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger22 + humanName: Right Middle Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger3 + humanName: Right Ring Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger31 + humanName: Right Ring Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger32 + humanName: Right Ring Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger4 + humanName: Right Little Proximal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger41 + humanName: Right Little Intermediate + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 R Finger42 + humanName: Right Little Distal + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + - boneName: Bip001 Spine2 + humanName: UpperChest + limit: + min: {x: 0, y: 0, z: 0} + max: {x: 0, y: 0, z: 0} + value: {x: 0, y: 0, z: 0} + length: 0 + modified: 0 + skeleton: + - name: ThrowAnimation_Boss_BoyFBX(Clone) + parentName: + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + scale: {x: 1, y: 1, z: 1} + - name: Socks + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: -0.000000038146972} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Eye + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Head + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Gloves + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: -0.00000014185905} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Shoes + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Jacket + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Hair + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Pants + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + scale: {x: 1, y: 1, z: 1} + - name: Bip001 + parentName: ThrowAnimation_Boss_BoyFBX(Clone) + position: {x: 0.000089325615, y: 0.8913384, z: 0.0001307253} + rotation: {x: -0.34501126, y: 0.5415012, z: 0.58973247, w: 0.48985636} + scale: {x: 0.99999994, y: 1, z: 1} + - name: Bip001 Footsteps + parentName: Bip001 + position: {x: -0.17585585, y: -0.057175994, z: -0.8414508} + rotation: {x: -0.10242095, y: 0.034104656, z: -0.79990304, w: 0.59034055} + scale: {x: 1.0000001, y: 1.0000004, z: 1.0000001} + - name: Bip001 Pelvis + parentName: Bip001 + position: {x: -0, y: 0, z: 0} + rotation: {x: -0.39331752, y: 0.63804, z: 0.44154865, w: 0.4931948} + scale: {x: 0.99999994, y: 0.9999999, z: 1.0000001} + - name: Bip001 Spine + parentName: Bip001 + position: {x: 0.0000824356, y: 0.0000013160706, z: 0.0769754} + rotation: {x: 0.39331853, y: -0.6380391, z: -0.44154996, w: -0.49319398} + scale: {x: 1.0000004, y: 1.0000005, z: 1.0000002} + - name: Bip001 Spine1 + parentName: Bip001 Spine + position: {x: -0.109362714, y: -0.00007510185, z: 0.000002260208} + rotation: {x: -0.000000074505806, y: 0.00000017881393, z: -0, w: 1} + scale: {x: 1, y: 0.99999994, z: 1} + - name: Bip001 Spine2 + parentName: Bip001 Spine1 + position: {x: -0.09437401, y: -0.00016386986, z: 0.000004997253} + rotation: {x: -0, y: -0, z: -0, w: 1} + scale: {x: 0.99999994, y: 1, z: 0.9999999} + - name: Bip001 Neck + parentName: Bip001 Spine2 + position: {x: -0.30066803, y: -0.019272458, z: -0.000000107884404} + rotation: {x: -0.000000059604645, y: 0.000000059604645, z: -0, w: 1} + scale: {x: 1, y: 0.99999994, z: 1.0000002} + - name: Bip001 Head + parentName: Bip001 Neck + position: {x: -0.06684417, y: -0.000000038146972, z: 0} + rotation: {x: -0.00000008940697, y: -0.00000005960464, z: -0.000000029802358, w: 1} + scale: {x: 1.0000007, y: 1.0000007, z: 1.0000013} + - name: Bip001 HeadNub + parentName: Bip001 Head + position: {x: -0.22498488, y: 0, z: 0} + rotation: {x: -2.3283064e-10, y: -8.6736174e-19, z: 0.0000000037252903, w: 1} + scale: {x: 0.9999999, y: 0.9999999, z: 0.99999994} + - name: Bip001 L Clavicle + parentName: Bip001 Spine2 + position: {x: -0.23186554, y: -0.0068668723, z: 0.03048319} + rotation: {x: -0.705454, y: -0.057321876, z: 0.7041411, w: 0.05687063} + scale: {x: 1.0000002, y: 1.0000001, z: 0.99999994} + - name: Bip001 L UpperArm + parentName: Bip001 L Clavicle + position: {x: -0.15688339, y: -0.000000007152557, z: 0} + rotation: {x: -0.00019042748, y: 0.0049661174, z: 0.1179365, w: 0.99300873} + scale: {x: 0.99999994, y: 1.0000002, z: 1.0000007} + - name: Bip001 L Forearm + parentName: Bip001 L UpperArm + position: {x: -0.2145063, y: 0, z: 0.000000038146972} + rotation: {x: 0.000000029802322, y: 0.000000035652192, z: 0.0013483746, w: 0.99999917} + scale: {x: 1, y: 0.9999998, z: 1} + - name: Bip001 L Hand + parentName: Bip001 L Forearm + position: {x: -0.23720428, y: -0.000000019073486, z: 0} + rotation: {x: -0.4447016, y: 0.06362462, z: -0.3355158, w: 0.8280227} + scale: {x: 1, y: 1.0000011, z: 1.0000004} + - name: Bip001 L Finger0 + parentName: Bip001 L Hand + position: {x: -0.02183136, y: 0.014335327, z: -0.031267326} + rotation: {x: 0.4188472, y: 0.10403948, z: -0.066113874, w: 0.899651} + scale: {x: 0.9999998, y: 0.99999994, z: 1.0000001} + - name: Bip001 L Finger01 + parentName: Bip001 L Finger0 + position: {x: -0.029194182, y: 0.000000019073486, z: 0.000000019073486} + rotation: {x: 0.000000089406946, y: 0.000000014901158, z: -0.000000014901158, w: 1} + scale: {x: 1.0000001, y: 1.0000001, z: 1.0000001} + - name: Bip001 L Finger02 + parentName: Bip001 L Finger01 + position: {x: -0.025641555, y: -0.000000019073486, z: 0} + rotation: {x: 0.000000029802305, y: -0.000000044703484, z: -0.00000013411041, w: 1} + scale: {x: 1.0000002, y: 1.0000007, z: 1} + - name: Bip001 L Finger0Nub + parentName: Bip001 L Finger02 + position: {x: -0.024530564, y: 0, z: 0.000000038146972} + rotation: {x: -0.000000011175871, y: 0, z: -0, w: 1} + scale: {x: 1, y: 1, z: 1} + - name: Bip001 L Finger2 + parentName: Bip001 L Hand + position: {x: -0.08869598, y: -0.0009292602, z: -0.008032665} + rotation: {x: -0.0088504525, y: 0.10908988, z: -0.00029446918, w: 0.9939925} + scale: {x: 1.0000001, y: 0.9999998, z: 1} + - name: Bip001 L Finger21 + parentName: Bip001 L Finger2 + position: {x: -0.035237882, y: 0.000000019073486, z: 0} + rotation: {x: -0.000000033061948, y: -0.00000014528631, z: 2.6193445e-10, w: 1} + scale: {x: 1.0000004, y: 0.99999994, z: 1.0000004} + - name: Bip001 L Finger22 + parentName: Bip001 L Finger21 + position: {x: -0.028829575, y: -0.000000038146972, z: 0} + rotation: {x: 0.000000033061948, y: 0.00000014528631, z: 0.0000000010622896, w: 1} + scale: {x: 1.0000006, y: 1.0000002, z: 1.0000001} + - name: Bip001 L Finger2Nub + parentName: Bip001 L Finger22 + position: {x: -0.022979412, y: 0, z: 0} + rotation: {x: 0.0000000074505815, y: 0.000000016763805, z: -0.000000007450581, w: 1} + scale: {x: 1, y: 0.9999999, z: 0.99999994} + - name: Bip001 L Finger1 + parentName: Bip001 L Hand + position: {x: -0.08566628, y: 0.0019595718, z: -0.030115388} + rotation: {x: 0.042771712, y: -0.08654338, z: 0.16646817, w: 0.9813099} + scale: {x: 1, y: 0.99999994, z: 1} + - name: Bip001 L Finger11 + parentName: Bip001 L Finger1 + position: {x: -0.03399338, y: 0.000000009536743, z: -0.000000009536743} + rotation: {x: 0.0000000037252894, y: -0.000000033527606, z: -0.000000028521747, w: 1} + scale: {x: 1.0000002, y: 0.99999994, z: 1.0000001} + - name: Bip001 L Finger12 + parentName: Bip001 L Finger11 + position: {x: -0.024710998, y: 0.000000019073486, z: -0.000000009536743} + rotation: {x: -0, y: -0, z: 1.2490004e-16, w: 1} + scale: {x: 1.0000001, y: 0.99999994, z: 1.0000004} + - name: Bip001 L Finger1Nub + parentName: Bip001 L Finger12 + position: {x: -0.02008175, y: 0, z: 0} + rotation: {x: -0.0000000037252907, y: -0.000000013038517, z: -4.857227e-17, w: 1} + scale: {x: 0.9999999, y: 0.9999998, z: 0.9999998} + - name: Bip001 L Finger3 + parentName: Bip001 L Hand + position: {x: -0.08759277, y: 0.000010223388, z: 0.012853202} + rotation: {x: -0.01829287, y: 0.107390136, z: -0.0058450163, w: 0.99403155} + scale: {x: 1, y: 0.9999998, z: 0.99999994} + - name: Bip001 L Finger31 + parentName: Bip001 L Finger3 + position: {x: -0.034347076, y: 0.000000019073486, z: 0.000000009536743} + rotation: {x: -0.00000002793967, y: 0.00000005960463, z: -1.16415294e-10, w: 1} + scale: {x: 1.0000006, y: 0.9999998, z: 0.9999998} + - name: Bip001 L Finger32 + parentName: Bip001 L Finger31 + position: {x: -0.028483544, y: -0.000000076293944, z: 0} + rotation: {x: 0.00000002793967, y: -0.00000005960463, z: 1.16415294e-10, w: 1} + scale: {x: 0.99999994, y: 1.0000001, z: 1.0000005} + - name: Bip001 L Finger3Nub + parentName: Bip001 L Finger32 + position: {x: -0.022639636, y: 0, z: 0.000000019073486} + rotation: {x: 9.3132246e-10, y: 0.0000000091968095, z: -8.5651955e-18, w: 1} + scale: {x: 1.0000001, y: 1, z: 1.0000001} + - name: Bip001 L Finger4 + parentName: Bip001 L Hand + position: {x: -0.07877823, y: 0.0028040314, z: 0.030893011} + rotation: {x: -0.029101618, y: 0.10210211, z: -0.018447932, w: 0.994177} + scale: {x: 1.0000002, y: 0.99999994, z: 1} + - name: Bip001 L Finger41 + parentName: Bip001 L Finger4 + position: {x: -0.027974395, y: -0.000000019073486, z: 0} + rotation: {x: 0.00000007264315, y: 0.00000005960463, z: 0.000000010011715, w: 1} + scale: {x: 1.0000004, y: 0.9999998, z: 1.0000005} + - name: Bip001 L Finger42 + parentName: Bip001 L Finger41 + position: {x: -0.021889571, y: -0.000000038146972, z: -0.000000019073486} + rotation: {x: -0.00000007264315, y: -0.00000005960463, z: -0.000000009080393, w: 1} + scale: {x: 1, y: 0.99999994, z: 1.0000005} + - name: Bip001 L Finger4Nub + parentName: Bip001 L Finger42 + position: {x: -0.01619625, y: 0, z: 0} + rotation: {x: 3.2065286e-17, y: -0.000000009837096, z: 0.0000000032596292, w: 1} + scale: {x: 0.9999999, y: 1, z: 1} + - name: Bip001 L ForeTwist + parentName: Bip001 L Forearm + position: {x: -0, y: 0, z: 0} + rotation: {x: 1.57776e-11, y: 0.000000011699727, z: -0.0000000114087015, w: 1} + scale: {x: 1.0000004, y: 1.0000007, z: 1.0000006} + - name: Bip001 R Clavicle + parentName: Bip001 Spine2 + position: {x: -0.23186538, y: -0.0068666814, z: -0.030483061} + rotation: {x: 0.70322347, y: 0.05756271, z: 0.70635873, w: 0.056750953} + scale: {x: 1.0000002, y: 1.0000001, z: 0.99999994} + - name: Bip001 R UpperArm + parentName: Bip001 R Clavicle + position: {x: -0.15688334, y: -0.0000000023841857, z: -0.00000015258789} + rotation: {x: 0.00096321857, y: -0.0035985468, z: -0.04355907, w: -0.99904394} + scale: {x: 1.0000002, y: 1, z: 1.0000005} + - name: Bip001 R Forearm + parentName: Bip001 R UpperArm + position: {x: -0.21450637, y: 0, z: 0} + rotation: {x: 0.000000024707944, y: -9.749783e-10, z: 0.0007118039, w: 0.9999998} + scale: {x: 0.99999994, y: 0.9999998, z: 0.99999994} + - name: Bip001 R Hand + parentName: Bip001 R Forearm + position: {x: -0.23720436, y: -0.000000019073486, z: 0.000000038146972} + rotation: {x: -0.61243856, y: 0.08376613, z: 0.005410347, w: -0.78604895} + scale: {x: 1.0000002, y: 1.0000007, z: 1} + - name: Bip001 R Finger0 + parentName: Bip001 R Hand + position: {x: -0.021831436, y: 0.014335327, z: 0.031267323} + rotation: {x: -0.4211995, y: 0.11073542, z: 0.04821671, w: 0.8988904} + scale: {x: 1.0000001, y: 0.99999994, z: 1} + - name: Bip001 R Finger01 + parentName: Bip001 R Finger0 + position: {x: -0.029194182, y: 0, z: 0} + rotation: {x: 0.00000014901158, y: -0.00000005960463, z: 0.000000044703473, w: 1} + scale: {x: 1.0000001, y: 1.0000002, z: 1} + - name: Bip001 R Finger02 + parentName: Bip001 R Finger01 + position: {x: -0.025641555, y: -0.000000009536743, z: 0.000000038146972} + rotation: {x: -0.00000008940697, y: -7.105425e-15, z: -0.00000014156096, w: 1} + scale: {x: 1.0000004, y: 1.0000002, z: 1.0000007} + - name: Bip001 R Finger0Nub + parentName: Bip001 R Finger02 + position: {x: -0.024530487, y: -0.000000009536743, z: -0.000000019073486} + rotation: {x: 0.000000014901161, y: 0.0000000037252907, z: 1, w: 5.7211802e-18} + scale: {x: -0.99999994, y: -0.9999999, z: -0.99999994} + - name: Bip001 R Finger2 + parentName: Bip001 R Hand + position: {x: -0.08869598, y: -0.0009292602, z: 0.00803266} + rotation: {x: 0.007193503, y: -0.025448194, z: 0.015477205, w: 0.99953043} + scale: {x: 1, y: 1.0000002, z: 1} + - name: Bip001 R Finger21 + parentName: Bip001 R Finger2 + position: {x: -0.035238035, y: -0.000000076293944, z: 0} + rotation: {x: -0.000000027939667, y: -0.0000000018626445, z: 0.00000006149637, w: 1} + scale: {x: 0.9999998, y: 0.9999997, z: 0.9999999} + - name: Bip001 R Finger22 + parentName: Bip001 R Finger21 + position: {x: -0.028829575, y: 0.000000057220458, z: 0} + rotation: {x: -0.0000000623986, y: 0.000000027939677, z: -0.0000001464359, w: 1} + scale: {x: 0.99999994, y: 1.0000001, z: 1.0000001} + - name: Bip001 R Finger2Nub + parentName: Bip001 R Finger22 + position: {x: -0.022979354, y: -0.000000019073486, z: 0} + rotation: {x: -0.0000000037252899, y: 0.000000009313224, z: 1, w: -2.653788e-17} + scale: {x: -1.0000001, y: -1.0000001, z: -1.0000001} + - name: Bip001 R Finger1 + parentName: Bip001 R Hand + position: {x: -0.08566628, y: 0.0019595337, z: 0.030115388} + rotation: {x: -0.041125704, y: 0.34547937, z: 0.109422445, w: 0.93111724} + scale: {x: 1, y: 1, z: 0.99999994} + - name: Bip001 R Finger11 + parentName: Bip001 R Finger1 + position: {x: -0.0339933, y: 0.000000038146972, z: -0.0000000047683715} + rotation: {x: 0.000000022351735, y: -0.000000083819, z: -0.000000033527602, w: 1} + scale: {x: 1.0000001, y: 1, z: 1} + - name: Bip001 R Finger12 + parentName: Bip001 R Finger11 + position: {x: -0.02471115, y: -0.000000019073486, z: -0.0000000047683715} + rotation: {x: -0, y: -0, z: -1.6792123e-15, w: 1} + scale: {x: 1.0000005, y: 1.0000004, z: 0.9999999} + - name: Bip001 R Finger1Nub + parentName: Bip001 R Finger12 + position: {x: -0.02008171, y: 0.000000019073486, z: 0.0000000047683715} + rotation: {x: 5.702705e-26, y: -9.3132246e-10, z: 1, w: -6.123234e-17} + scale: {x: -1.0000001, y: -1.0000001, z: -1.0000001} + - name: Bip001 R Finger3 + parentName: Bip001 R Hand + position: {x: -0.08759277, y: 0.000010223388, z: -0.012853216} + rotation: {x: 0.018083032, y: -0.039043806, z: 0.00067552907, w: 0.9990737} + scale: {x: 1.0000002, y: 1, z: 0.99999994} + - name: Bip001 R Finger31 + parentName: Bip001 R Finger3 + position: {x: -0.034347076, y: 0.000000038146972, z: 0.000000009536743} + rotation: {x: -0.00000009313222, y: 0.000000026077023, z: -0.00000011612424, w: 1} + scale: {x: 1.0000002, y: 1.0000001, z: 1.0000001} + - name: Bip001 R Finger32 + parentName: Bip001 R Finger31 + position: {x: -0.02848358, y: -0.000000038146972, z: -0.000000014305114} + rotation: {x: 0.00000009126957, y: 0.000000063329914, z: 0.00000008475033, w: 1} + scale: {x: 1.0000001, y: 0.99999994, z: 0.9999998} + - name: Bip001 R Finger3Nub + parentName: Bip001 R Finger32 + position: {x: -0.022639694, y: -0.000000057220458, z: -0.0000000047683715} + rotation: {x: -6.8432476e-25, y: 0.000000011175871, z: 1, w: -6.123234e-17} + scale: {x: -1, y: -1, z: -1} + - name: Bip001 R Finger4 + parentName: Bip001 R Hand + position: {x: -0.07877823, y: 0.002803955, z: -0.030893024} + rotation: {x: 0.029447902, y: -0.033610202, z: -0.008080942, w: 0.9989685} + scale: {x: 1, y: 0.99999994, z: 0.9999998} + - name: Bip001 R Finger41 + parentName: Bip001 R Finger4 + position: {x: -0.027974471, y: 0.000000038146972, z: -0.000000009536743} + rotation: {x: -0.00000002793967, y: 0.000000029802315, z: 0.0000000032596283, w: 1} + scale: {x: 1.0000004, y: 1.0000005, z: 0.9999999} + - name: Bip001 R Finger42 + parentName: Bip001 R Finger41 + position: {x: -0.021889495, y: 0.000000019073486, z: 0} + rotation: {x: 0.000000029802315, y: -0.000000029802315, z: -9.3132235e-10, w: 1} + scale: {x: 1.0000001, y: 0.99999994, z: 1.0000001} + - name: Bip001 R Finger4Nub + parentName: Bip001 R Finger42 + position: {x: -0.016196288, y: -0.000000038146972, z: -0.000000009536743} + rotation: {x: -2.2810825e-25, y: -0.0000000037252903, z: 1, w: 6.123234e-17} + scale: {x: -1.0000001, y: -1, z: -1} + - name: Bip001 R ForeTwist + parentName: Bip001 R Forearm + position: {x: -0, y: 0, z: 0} + rotation: {x: 3.1121772e-12, y: 0.0000000070867827, z: 0.000000023297616, w: 1} + scale: {x: 1.0000011, y: 1.0000005, z: 1.0000007} + - name: Bip001 R Thigh + parentName: Bip001 + position: {x: -0.000000057220458, y: -0.08523403, z: 0.00000015258789} + rotation: {x: 0.4414919, y: -0.4932458, z: 0.39339268, w: 0.6379936} + scale: {x: 1.0000004, y: 1.0000002, z: 1.0000004} + - name: Bip001 R Calf + parentName: Bip001 R Thigh + position: {x: -0.36894354, y: 0, z: 0} + rotation: {x: 0.00000011920929, y: -0.00000011920929, z: 0.0006225109, w: 0.9999999} + scale: {x: 1.0000002, y: 1.0000004, z: 1.0000001} + - name: Bip001 R Foot + parentName: Bip001 R Calf + position: {x: -0.4258783, y: -0.000000009536743, z: 0} + rotation: {x: -0.0000015199186, y: 0.000000089406974, z: -0.00073921686, w: 0.99999976} + scale: {x: 1.0000005, y: 1.0000004, z: 1.0000006} + - name: Bip001 R Toe0 + parentName: Bip001 R Foot + position: {x: -0.08415353, y: 0.11247517, z: 0} + rotation: {x: 0.000000059604645, y: 0.000000029802322, z: -0.7071068, w: 0.7071068} + scale: {x: 0.99999994, y: 1.0000001, z: 1} + - name: Bip001 R Toe0Nub + parentName: Bip001 R Toe0 + position: {x: -0.063924685, y: 0.0000000011920929, z: 0.000000019073486} + rotation: {x: -0.0000000037252903, y: -0.0000000095278665, z: 5.8207626e-11, w: 1} + scale: {x: 1, y: 1, z: 1.0000001} + - name: Bip001 L Thigh + parentName: Bip001 + position: {x: -0, y: 0.08523406, z: -0.000000076293944} + rotation: {x: 0.44171643, y: -0.49304473, z: 0.3931021, w: 0.63817257} + scale: {x: 1, y: 1.0000002, z: 1.0000004} + - name: Bip001 L Calf + parentName: Bip001 L Thigh + position: {x: -0.36894354, y: -0.0000000047683715, z: 0} + rotation: {x: 0.000000029802322, y: -0.000000029802322, z: 0.0006225109, w: 0.9999998} + scale: {x: 1.0000006, y: 1.0000004, z: 1.0000002} + - name: Bip001 L Foot + parentName: Bip001 L Calf + position: {x: -0.42587817, y: 0.0000000047683715, z: 0} + rotation: {x: -0, y: 0.000000014901161, z: -0.00028386712, w: 1} + scale: {x: 0.9999997, y: 1, z: 0.99999976} + - name: Bip001 L Toe0 + parentName: Bip001 L Foot + position: {x: -0.08415352, y: 0.11247517, z: 0} + rotation: {x: -0.0000001192093, y: -0.00000005960465, z: -0.7071068, w: 0.7071068} + scale: {x: 1.0000001, y: 1.0000002, z: 1.0000002} + - name: Bip001 L Toe0Nub + parentName: Bip001 L Toe0 + position: {x: -0.0639247, y: -5.9604643e-10, z: 0.000000019073486} + rotation: {x: 6.975825e-10, y: 4.271461e-26, z: 1, w: -6.123234e-17} + scale: {x: -0.99999994, y: -0.99999994, z: -1} + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 1 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 3 + humanoidOversampling: 1 + avatarSetup: 1 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/5.Enemy Animation/BossAnimation'.meta b/Assets/5.Enemy Animation/BossAnimation'.meta new file mode 100644 index 00000000..549ba783 --- /dev/null +++ b/Assets/5.Enemy Animation/BossAnimation'.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8b8446902f8367e448f85dab277f598f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Epic Toon FX/Upgrade/ETFX URP Upgrade (6000.0.11f1).unitypackage.meta b/Assets/Epic Toon FX/Upgrade/ETFX URP Upgrade (6000.0.11f1).unitypackage.meta new file mode 100644 index 00000000..ffa13bfe --- /dev/null +++ b/Assets/Epic Toon FX/Upgrade/ETFX URP Upgrade (6000.0.11f1).unitypackage.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5f14e783a5ba44a45a317ffae28af4e7 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Epic Toon FX/Upgrade/Legacy/ETFX URP Upgrade (2020.3.45f1).unitypackage.meta b/Assets/Epic Toon FX/Upgrade/Legacy/ETFX URP Upgrade (2020.3.45f1).unitypackage.meta new file mode 100644 index 00000000..a9c2e213 --- /dev/null +++ b/Assets/Epic Toon FX/Upgrade/Legacy/ETFX URP Upgrade (2020.3.45f1).unitypackage.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3d7c4217783978e4abe6496ac71eee94 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI.meta b/Assets/Scripts/Enemy/BossAI.meta new file mode 100644 index 00000000..32f4c621 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f548a77d5fa24ee45862ea98298a00d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterConfig.cs b/Assets/Scripts/Enemy/BossAI/BossCounterConfig.cs new file mode 100644 index 00000000..fdd6bd33 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterConfig.cs @@ -0,0 +1,77 @@ +using UnityEngine; + +/// +/// 보스 카운터 시스템의 임계치, 가중치, 감소(Decay) 설정을 담는 ScriptableObject. +/// Inspector에서 밸런싱을 위해 쉽게 조정할 수 있습니다. +/// +/// [사용법] Project 창에서 우클릭 → Create → Boss/Counter Config +/// +[CreateAssetMenu(fileName = "BossCounterConfig", menuName = "Boss/Counter Config")] +public class BossCounterConfig : ScriptableObject +{ + [Header("══ 기본 임계치 (첫 런 / 잠금 해제 전) ══")] + [Tooltip("회피 카운터 발동 조건: 10초 내 회피 횟수")] + public int dodgeThreshold = 5; + + [Tooltip("조준 카운터 발동 조건: 10초 내 조준 유지 시간(초)")] + public float aimThreshold = 4.0f; + + [Tooltip("관통 카운터 발동 조건: 10초 내 관통 비율")] + [Range(0f, 1f)] + public float pierceThreshold = 0.6f; + + [Tooltip("관통 비율 판단을 위한 최소 발사 횟수")] + public int minShotsForPierceCheck = 3; + + [Header("══ 잠금 해제 후 임계치 감소 ══")] + [Tooltip("잠금 해제된 카운터의 임계치 감소 비율 (0.8 = 20% 낮아짐)")] + [Range(0.5f, 1.0f)] + public float unlockedThresholdMultiplier = 0.8f; + + [Header("══ 가중치 설정 (확률 가중치 방식) ══")] + [Tooltip("카운터 발동 시 해당 카운터 패턴에 추가되는 가중치")] + public float counterWeightBonus = 3f; + + [Tooltip("카운터 발동 시 보조 패턴에 추가되는 가중치")] + public float counterSubWeightBonus = 2f; + + [Header("══ Decay(감소) 설정 ══")] + [Tooltip("카운터 모드 유지 시간(초). 이 시간 동안 조건 미충족 시 비활성화")] + public float counterDecayTime = 8f; + + [Header("══ 빈도 제한 ══")] + [Tooltip("카운터 패턴 선택 확률 상한 (0.25 = 최대 25%)")] + [Range(0.1f, 0.5f)] + public float maxCounterFrequency = 0.25f; + + [Tooltip("카운터 패턴 발동 후 쿨타임(초)")] + public float counterCooldown = 5f; + + [Header("══ 습관 변경 보상 ══")] + [Tooltip("플레이어가 이전 런에서 발동된 카운터 습관을 이번 런에서 안 보이면, 보스 일반 패턴 난이도 감소 비율")] + [Range(0f, 0.3f)] + public float habitChangeRewardRatio = 0.15f; + + // ═══════════════════════════════════════════ + // 임계치 조회 (잠금 해제 여부 반영) + // ═══════════════════════════════════════════ + + /// 현재 유효 임계치 반환 (잠금 해제 시 낮아짐) + public int GetEffectiveDodgeThreshold(bool isUnlocked) + { + if (!isUnlocked) return dodgeThreshold; + return Mathf.Max(2, Mathf.RoundToInt(dodgeThreshold * unlockedThresholdMultiplier)); + } + + public float GetEffectiveAimThreshold(bool isUnlocked) + { + if (!isUnlocked) return aimThreshold; + return aimThreshold * unlockedThresholdMultiplier; + } + + public float GetEffectivePierceThreshold(bool isUnlocked) + { + if (!isUnlocked) return pierceThreshold; + return pierceThreshold * unlockedThresholdMultiplier; + } +} diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterConfig.cs.meta b/Assets/Scripts/Enemy/BossAI/BossCounterConfig.cs.meta new file mode 100644 index 00000000..2de0098e --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 127d57ae132759d4f8233580c8075e39 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterDebugPanel.cs b/Assets/Scripts/Enemy/BossAI/BossCounterDebugPanel.cs new file mode 100644 index 00000000..60ae8c9d --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterDebugPanel.cs @@ -0,0 +1,93 @@ +using UnityEngine; + +/// +/// 개발 중 보스 카운터 시스템을 테스트하기 위한 디버그 패널. +/// 빌드 시 자동으로 비활성화됩니다. +/// +public class BossCounterDebugPanel : MonoBehaviour +{ + [SerializeField] private BossCounterSystem counterSystem; + [SerializeField] private bool showDebugGUI = true; + + #if UNITY_EDITOR || DEVELOPMENT_BUILD + + private void OnGUI() + { + if (!showDebugGUI) return; + + GUILayout.BeginArea(new Rect(10, 10, 400, 500)); + GUILayout.BeginVertical("box"); + + GUILayout.Label("═══ 보스 카운터 디버그 ═══", GUI.skin.box); + + // ── 플레이어 행동 데이터 ── + var tracker = PlayerBehaviorTracker.Instance; + if (tracker != null) + { + GUILayout.Label("── 플레이어 행동 (10초 윈도우) ──"); + GUILayout.Label($" 회피 횟수: {tracker.DodgeCount}"); + GUILayout.Label($" 조준 시간: {tracker.AimHoldTime:F1}s"); + GUILayout.Label($" 관통 비율: {tracker.PierceRatio:P0} ({tracker.TotalShotsInWindow}발)"); + } + + GUILayout.Space(5); + + // ── 카운터 상태 ── + if (counterSystem != null) + { + GUILayout.Label("── 카운터 모드 ──"); + var actives = counterSystem.GetActiveCounters(); + GUILayout.Label($" 활성 카운터: {(actives.Count > 0 ? string.Join(", ", actives) : "없음")}"); + GUILayout.Label($" 습관 변경 보상: {(counterSystem.IsHabitChangeRewarded ? "ON" : "OFF")}"); + } + + GUILayout.Space(5); + + // ── 영구 데이터 ── + var persistence = BossCounterPersistence.Instance; + if (persistence != null) + { + GUILayout.Label("── 영구 잠금 해제 ──"); + GUILayout.Label($" 회피: {(persistence.IsUnlocked(CounterType.Dodge) ? "✓" : "✗")} (발동 {persistence.Data.dodgeCounterActivations}회)"); + GUILayout.Label($" 조준: {(persistence.IsUnlocked(CounterType.Aim) ? "✓" : "✗")} (발동 {persistence.Data.aimCounterActivations}회)"); + GUILayout.Label($" 관통: {(persistence.IsUnlocked(CounterType.Pierce) ? "✓" : "✗")} (발동 {persistence.Data.pierceCounterActivations}회)"); + } + + GUILayout.Space(10); + + // ── 수동 트리거 버튼 ── + GUILayout.Label("── 수동 테스트 ──"); + + if (tracker != null) + { + GUILayout.BeginHorizontal(); + if (GUILayout.Button("회피 x5")) { for (int i = 0; i < 5; i++) tracker.RecordDodge(); } + if (GUILayout.Button("발사(일반)")) { tracker.RecordShot(false); } + if (GUILayout.Button("발사(관통)")) { tracker.RecordShot(true); } + GUILayout.EndHorizontal(); + } + + if (counterSystem != null) + { + if (GUILayout.Button("패턴 선택 테스트")) + { + string pattern = counterSystem.SelectBossPattern(); + Debug.Log($"[디버그] 선택된 패턴: {pattern}"); + } + } + + if (persistence != null) + { + GUILayout.Space(5); + if (GUILayout.Button("영구 데이터 초기화")) + { + persistence.ResetAllData(); + } + } + + GUILayout.EndVertical(); + GUILayout.EndArea(); + } + + #endif +} diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterDebugPanel.cs.meta b/Assets/Scripts/Enemy/BossAI/BossCounterDebugPanel.cs.meta new file mode 100644 index 00000000..8f00ef7d --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterDebugPanel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ccdc3124c64881747b53b7b469a36e10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterFeedback.cs b/Assets/Scripts/Enemy/BossAI/BossCounterFeedback.cs new file mode 100644 index 00000000..ca6f380f --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterFeedback.cs @@ -0,0 +1,189 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.UI; +using TMPro; + +/// +/// 보스 카운터 시스템의 연출/UI를 담당합니다. +/// 카운터 발동 시 보스 대사, 화면 효과 등을 처리합니다. +/// +/// "...또 그 수법이냐" 같은 대사로 "보스가 기억한다"는 서사 전달. +/// +public class BossCounterFeedback : MonoBehaviour +{ + [Header("참조")] + [SerializeField] private BossCounterSystem counterSystem; + + [Header("UI 요소 (선택)")] + [SerializeField] private TextMeshProUGUI bossDialogueText; + [SerializeField] private CanvasGroup dialogueCanvasGroup; + [SerializeField] private float dialogueDisplayDuration = 3f; + [SerializeField] private float dialogueFadeDuration = 0.5f; + + [Header("카운터별 보스 대사")] + [SerializeField] private string[] dodgeCounterDialogues = new string[] + { + "...또 도망치려는 건가.", + "네 발은 이미 읽었다.", + "아무리 피해도 소용없어." + }; + + [SerializeField] private string[] aimCounterDialogues = new string[] + { + "그렇게 오래 노려봐야...", + "느린 조준은 빈틈이지.", + "시간을 줄 생각은 없다." + }; + + [SerializeField] private string[] pierceCounterDialogues = new string[] + { + "그 화살은 더 이상 통하지 않아.", + "관통? 이번엔 막아주지.", + "같은 수를 반복하다니." + }; + + [SerializeField] private string[] habitChangeDialogues = new string[] + { + "...다른 수를 쓰는 건가.", + "흥, 조금은 배운 모양이군.", + "이번엔 다르군... 재밌어." + }; + + // ── 잠금 해제 여부에 따른 첫 발동 대사 ── + [Header("첫 잠금 해제 시 대사 (서사 강조)")] + [SerializeField] private string[] firstUnlockDialogues = new string[] + { + "...기억했다. 네 버릇을.", + "이제 알겠어. 네 전투 방식이.", + "한 번이면 충분해. 패턴을 읽었다." + }; + + private Coroutine dialogueCoroutine; + + private void OnEnable() + { + if (counterSystem != null) + { + counterSystem.OnCounterActivated.AddListener(OnCounterActivated); + counterSystem.OnCounterDeactivated.AddListener(OnCounterDeactivated); + counterSystem.OnHabitChangeRewarded.AddListener(OnHabitChangeRewarded); + } + } + + private void OnDisable() + { + if (counterSystem != null) + { + counterSystem.OnCounterActivated.RemoveListener(OnCounterActivated); + counterSystem.OnCounterDeactivated.RemoveListener(OnCounterDeactivated); + counterSystem.OnHabitChangeRewarded.RemoveListener(OnHabitChangeRewarded); + } + } + + // ═══════════════════════════════════════════ + // 이벤트 핸들러 + // ═══════════════════════════════════════════ + + private void OnCounterActivated(CounterType type) + { + var persistence = BossCounterPersistence.Instance; + + // 첫 잠금 해제인지 확인 (총 발동 횟수가 1이면 방금 처음 잠금 해제된 것) + bool isFirstUnlock = false; + if (persistence != null) + { + int activations = type switch + { + CounterType.Dodge => persistence.Data.dodgeCounterActivations, + CounterType.Aim => persistence.Data.aimCounterActivations, + CounterType.Pierce => persistence.Data.pierceCounterActivations, + _ => 0 + }; + isFirstUnlock = (activations <= 1); + } + + // 대사 선택 + string dialogue; + if (isFirstUnlock) + { + dialogue = firstUnlockDialogues[Random.Range(0, firstUnlockDialogues.Length)]; + } + else + { + dialogue = type switch + { + CounterType.Dodge => dodgeCounterDialogues[Random.Range(0, dodgeCounterDialogues.Length)], + CounterType.Aim => aimCounterDialogues[Random.Range(0, aimCounterDialogues.Length)], + CounterType.Pierce => pierceCounterDialogues[Random.Range(0, pierceCounterDialogues.Length)], + _ => "" + }; + } + + ShowDialogue(dialogue); + + // TODO: 여기에 추가 연출 넣기 + // - 보스 전용 애니메이션 트리거 (예: animator.SetTrigger("CounterReady")) + // - 보스 주변 이펙트 (파티클, 오라 등) + // - 카메라 연출 (줌인, 슬로모션 등) + // - 사운드 효과 + Debug.Log($"[BossCounterFeedback] {type} 카운터 연출 재생" + + (isFirstUnlock ? " (첫 잠금 해제!)" : "")); + } + + private void OnCounterDeactivated(CounterType type) + { + // 카운터 해제 시 연출 (이펙트 종료 등) + Debug.Log($"[BossCounterFeedback] {type} 카운터 연출 종료"); + } + + private void OnHabitChangeRewarded() + { + string dialogue = habitChangeDialogues[Random.Range(0, habitChangeDialogues.Length)]; + ShowDialogue(dialogue); + + Debug.Log("[BossCounterFeedback] 습관 변경 보상 연출!"); + } + + // ═══════════════════════════════════════════ + // 대사 표시 + // ═══════════════════════════════════════════ + + private void ShowDialogue(string text) + { + if (bossDialogueText == null || dialogueCanvasGroup == null) return; + + if (dialogueCoroutine != null) + StopCoroutine(dialogueCoroutine); + + dialogueCoroutine = StartCoroutine(DialogueRoutine(text)); + } + + private IEnumerator DialogueRoutine(string text) + { + bossDialogueText.text = text; + dialogueCanvasGroup.alpha = 0f; + + // 페이드 인 + float t = 0f; + while (t < dialogueFadeDuration) + { + t += Time.deltaTime; + dialogueCanvasGroup.alpha = t / dialogueFadeDuration; + yield return null; + } + dialogueCanvasGroup.alpha = 1f; + + // 유지 + yield return new WaitForSeconds(dialogueDisplayDuration); + + // 페이드 아웃 + t = 0f; + while (t < dialogueFadeDuration) + { + t += Time.deltaTime; + dialogueCanvasGroup.alpha = 1f - (t / dialogueFadeDuration); + yield return null; + } + dialogueCanvasGroup.alpha = 0f; + } +} diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterFeedback.cs.meta b/Assets/Scripts/Enemy/BossAI/BossCounterFeedback.cs.meta new file mode 100644 index 00000000..83e31b06 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterFeedback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c7bf8a7166b27040a70563b18bd6b3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterPersistence.cs b/Assets/Scripts/Enemy/BossAI/BossCounterPersistence.cs new file mode 100644 index 00000000..d75ca940 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterPersistence.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using UnityEngine; + +/// +/// 런 간 영구 저장되는 보스 카운터 잠금 해제 데이터. +/// "보스가 플레이어를 기억한다"는 서사를 담당합니다. +/// +/// 핵심 규칙: +/// - 잠금 해제는 영구 (런이 끝나도 유지) +/// - 발동은 조건부 (해당 런에서 플레이어가 습관을 보여야만 활성화) +/// - 잠금 해제된 카운터는 임계치가 약간 낮아짐 (보스가 "이미 알고 있으니 더 빨리 눈치챔") +/// +[System.Serializable] +public class BossCounterSaveData +{ + public bool dodgeCounterUnlocked = false; + public bool aimCounterUnlocked = false; + public bool pierceCounterUnlocked = false; + + /// 각 카운터가 발동된 총 횟수 (연출/난이도 스케일링에 활용 가능) + public int dodgeCounterActivations = 0; + public int aimCounterActivations = 0; + public int pierceCounterActivations = 0; +} + +/// +/// 보스 카운터 영구 데이터를 관리합니다. +/// PlayerPrefs 기반으로 런 간 저장/로드합니다. +/// +public class BossCounterPersistence : MonoBehaviour +{ + public static BossCounterPersistence Instance { get; private set; } + + private const string SAVE_KEY = "BossCounterData"; + + public BossCounterSaveData Data { get; private set; } + + private void Awake() + { + if (Instance != null && Instance != this) + { + Destroy(gameObject); + return; + } + Instance = this; + DontDestroyOnLoad(gameObject); + Load(); + } + + // ═══════════════════════════════════════════ + // 잠금 해제 + // ═══════════════════════════════════════════ + + /// 특정 카운터 타입을 영구 잠금 해제 + public void UnlockCounter(CounterType type) + { + switch (type) + { + case CounterType.Dodge: + if (!Data.dodgeCounterUnlocked) + { + Data.dodgeCounterUnlocked = true; + Debug.Log("[BossCounter] 회피 카운터 영구 잠금 해제!"); + } + break; + case CounterType.Aim: + if (!Data.aimCounterUnlocked) + { + Data.aimCounterUnlocked = true; + Debug.Log("[BossCounter] 조준 카운터 영구 잠금 해제!"); + } + break; + case CounterType.Pierce: + if (!Data.pierceCounterUnlocked) + { + Data.pierceCounterUnlocked = true; + Debug.Log("[BossCounter] 관통 카운터 영구 잠금 해제!"); + } + break; + } + Save(); + } + + /// 카운터가 잠금 해제되어 있는지 확인 + public bool IsUnlocked(CounterType type) + { + return type switch + { + CounterType.Dodge => Data.dodgeCounterUnlocked, + CounterType.Aim => Data.aimCounterUnlocked, + CounterType.Pierce => Data.pierceCounterUnlocked, + _ => false + }; + } + + /// 카운터 발동 횟수 기록 + public void RecordActivation(CounterType type) + { + switch (type) + { + case CounterType.Dodge: Data.dodgeCounterActivations++; break; + case CounterType.Aim: Data.aimCounterActivations++; break; + case CounterType.Pierce: Data.pierceCounterActivations++; break; + } + Save(); + } + + // ═══════════════════════════════════════════ + // 저장 / 로드 / 리셋 + // ═══════════════════════════════════════════ + + public void Save() + { + string json = JsonUtility.ToJson(Data); + PlayerPrefs.SetString(SAVE_KEY, json); + PlayerPrefs.Save(); + } + + public void Load() + { + if (PlayerPrefs.HasKey(SAVE_KEY)) + { + string json = PlayerPrefs.GetString(SAVE_KEY); + Data = JsonUtility.FromJson(json); + } + else + { + Data = new BossCounterSaveData(); + } + } + + /// 모든 영구 데이터 초기화 (디버그/뉴게임+) + public void ResetAllData() + { + Data = new BossCounterSaveData(); + PlayerPrefs.DeleteKey(SAVE_KEY); + Debug.Log("[BossCounter] 모든 보스 기억 데이터 초기화됨"); + } +} diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterPersistence.cs.meta b/Assets/Scripts/Enemy/BossAI/BossCounterPersistence.cs.meta new file mode 100644 index 00000000..ec736c3e --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterPersistence.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c23a9c1b76724ab459bf32a732f6a2f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterSystem.cs b/Assets/Scripts/Enemy/BossAI/BossCounterSystem.cs new file mode 100644 index 00000000..333e3bbc --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterSystem.cs @@ -0,0 +1,356 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; + +/// +/// 보스 카운터 시스템 메인 컨트롤러. +/// +/// 핵심 흐름: +/// 1. PlayerBehaviorTracker에서 실시간 행동 데이터를 읽음 +/// 2. 임계치 판단 → 카운터 모드 ON/OFF (잠금 해제 여부에 따라 임계치 다름) +/// 3. 가중치 기반으로 보스 패턴 선택 +/// 4. 첫 발동 시 해당 카운터를 영구 잠금 해제 +/// 5. 플레이어가 습관을 바꾸면 보상 (난이도 완화) +/// +public class BossCounterSystem : MonoBehaviour +{ + [Header("참조")] + [SerializeField] private BossCounterConfig config; + + [Header("이벤트 (연출/UI 연동)")] + [Tooltip("카운터 모드가 활성화될 때 발생 (CounterType 전달)")] + public UnityEvent OnCounterActivated; + + [Tooltip("카운터 모드가 비활성화될 때 발생")] + public UnityEvent OnCounterDeactivated; + + [Tooltip("보스가 카운터 패턴을 선택했을 때 발생 (패턴 이름 전달)")] + public UnityEvent OnCounterPatternSelected; + + [Tooltip("플레이어가 습관을 바꿔서 보상받을 때 발생")] + public UnityEvent OnHabitChangeRewarded; + + // ── 카운터 모드 상태 ── + private Dictionary activeCounters = new Dictionary() + { + { CounterType.Dodge, false }, + { CounterType.Aim, false }, + { CounterType.Pierce, false } + }; + + // ── Decay 타이머 ── + private Dictionary counterTimers = new Dictionary() + { + { CounterType.Dodge, 0f }, + { CounterType.Aim, 0f }, + { CounterType.Pierce, 0f } + }; + + // ── 쿨타임 ── + private float lastCounterPatternTime = -100f; + + // ── 습관 변경 보상 추적 ── + private HashSet previousRunCounters = new HashSet(); + private HashSet currentRunActivatedCounters = new HashSet(); + private bool habitChangeRewardGranted = false; + + // ── 보스 패턴 가중치 정의 ── + [System.Serializable] + public class BossPattern + { + public string patternName; + public float baseWeight = 1f; + [Tooltip("이 패턴이 카운터 패턴인 경우 해당 타입")] + public CounterType counterType = CounterType.None; + [Tooltip("카운터 발동 시 보조적으로 가중치가 올라가는 타입")] + public CounterType subCounterType = CounterType.None; + } + + [Header("보스 패턴 목록")] + [SerializeField] private List bossPatterns = new List(); + + // ═══════════════════════════════════════════ + // 초기화 + // ═══════════════════════════════════════════ + + /// + /// 보스 전투 시작 시 호출. 이전 런에서 발동된 카운터 정보를 기반으로 초기화. + /// + public void InitializeBattle() + { + // 이전 런에서 잠금 해제된 카운터들을 기록 (습관 변경 보상 판단용) + previousRunCounters.Clear(); + currentRunActivatedCounters.Clear(); + habitChangeRewardGranted = false; + + var persistence = BossCounterPersistence.Instance; + if (persistence != null) + { + if (persistence.Data.dodgeCounterActivations > 0 && persistence.IsUnlocked(CounterType.Dodge)) + previousRunCounters.Add(CounterType.Dodge); + if (persistence.Data.aimCounterActivations > 0 && persistence.IsUnlocked(CounterType.Aim)) + previousRunCounters.Add(CounterType.Aim); + if (persistence.Data.pierceCounterActivations > 0 && persistence.IsUnlocked(CounterType.Pierce)) + previousRunCounters.Add(CounterType.Pierce); + } + + // 모든 카운터 모드 OFF + foreach (var type in new[] { CounterType.Dodge, CounterType.Aim, CounterType.Pierce }) + { + activeCounters[type] = false; + counterTimers[type] = 0f; + } + + lastCounterPatternTime = -100f; + + Debug.Log($"[BossCounter] 전투 시작. 이전 런 카운터: [{string.Join(", ", previousRunCounters)}]"); + } + + // ═══════════════════════════════════════════ + // 매 프레임 업데이트 + // ═══════════════════════════════════════════ + + private void Update() + { + if (PlayerBehaviorTracker.Instance == null) return; + + EvaluateCounters(); + DecayCounters(); + CheckHabitChangeReward(); + } + + /// 플레이어 행동 데이터를 읽고 카운터 모드 ON/OFF 판단 + private void EvaluateCounters() + { + var tracker = PlayerBehaviorTracker.Instance; + var persistence = BossCounterPersistence.Instance; + + // ── 회피 카운터 ── + bool dodgeUnlocked = persistence != null && persistence.IsUnlocked(CounterType.Dodge); + int dodgeThreshold = config.GetEffectiveDodgeThreshold(dodgeUnlocked); + + if (tracker.DodgeCount >= dodgeThreshold) + { + // 잠금 해제 안 된 상태면 첫 발동 시 잠금 해제 (첫 런에서도 발동 가능) + // 잠금 해제된 상태면 더 낮은 임계치로 발동 + ActivateCounter(CounterType.Dodge); + } + + // ── 조준 카운터 ── + bool aimUnlocked = persistence != null && persistence.IsUnlocked(CounterType.Aim); + float aimThreshold = config.GetEffectiveAimThreshold(aimUnlocked); + + if (tracker.AimHoldTime >= aimThreshold) + { + ActivateCounter(CounterType.Aim); + } + + // ── 관통 카운터 ── + bool pierceUnlocked = persistence != null && persistence.IsUnlocked(CounterType.Pierce); + float pierceThreshold = config.GetEffectivePierceThreshold(pierceUnlocked); + + if (tracker.TotalShotsInWindow >= config.minShotsForPierceCheck + && tracker.PierceRatio >= pierceThreshold) + { + ActivateCounter(CounterType.Pierce); + } + } + + private void ActivateCounter(CounterType type) + { + counterTimers[type] = config.counterDecayTime; + + if (!activeCounters[type]) + { + activeCounters[type] = true; + currentRunActivatedCounters.Add(type); + + // 영구 잠금 해제 + var persistence = BossCounterPersistence.Instance; + if (persistence != null) + { + persistence.UnlockCounter(type); + persistence.RecordActivation(type); + } + + OnCounterActivated?.Invoke(type); + Debug.Log($"[BossCounter] {type} 카운터 활성화!"); + } + } + + /// 시간이 지나면 카운터 모드 자동 해제 + private void DecayCounters() + { + foreach (var type in new[] { CounterType.Dodge, CounterType.Aim, CounterType.Pierce }) + { + if (!activeCounters[type]) continue; + + counterTimers[type] -= Time.deltaTime; + if (counterTimers[type] <= 0f) + { + activeCounters[type] = false; + OnCounterDeactivated?.Invoke(type); + Debug.Log($"[BossCounter] {type} 카운터 Decay로 비활성화"); + } + } + } + + // ═══════════════════════════════════════════ + // 습관 변경 보상 + // ═══════════════════════════════════════════ + + /// + /// 이전 런에서 카운터 당한 습관을 이번 런에서 보이지 않으면 보상. + /// 전투 중반(30초 이후) 한 번 체크. + /// + private float battleTimer = 0f; + private const float HABIT_CHECK_TIME = 30f; + + private void CheckHabitChangeReward() + { + if (habitChangeRewardGranted || previousRunCounters.Count == 0) return; + + battleTimer += Time.deltaTime; + if (battleTimer < HABIT_CHECK_TIME) return; + + // 이전 런에서 발동된 카운터 중, 이번 런에서 아직 발동 안 된 것이 있으면 보상 + foreach (var prevCounter in previousRunCounters) + { + if (!currentRunActivatedCounters.Contains(prevCounter)) + { + habitChangeRewardGranted = true; + OnHabitChangeRewarded?.Invoke(); + Debug.Log($"[BossCounter] 플레이어가 {prevCounter} 습관을 바꿈! 보상 부여"); + break; + } + } + } + + // ═══════════════════════════════════════════ + // 패턴 선택 (보스 AI에서 호출) + // ═══════════════════════════════════════════ + + /// + /// 현재 카운터 상태를 반영하여 보스 패턴을 가중치 랜덤으로 선택합니다. + /// 보스 AI의 패턴 선택 시점에 호출하세요. + /// + /// 선택된 패턴 이름 + public string SelectBossPattern() + { + if (bossPatterns.Count == 0) + { + Debug.LogWarning("[BossCounter] 보스 패턴이 등록되지 않았습니다!"); + return ""; + } + + // 가중치 계산 + float[] weights = new float[bossPatterns.Count]; + float totalWeight = 0f; + float counterWeight = 0f; + + for (int i = 0; i < bossPatterns.Count; i++) + { + weights[i] = bossPatterns[i].baseWeight; + + // 카운터 패턴 가중치 증가 + if (bossPatterns[i].counterType != CounterType.None + && activeCounters.ContainsKey(bossPatterns[i].counterType) + && activeCounters[bossPatterns[i].counterType]) + { + // 쿨타임 체크 + if (Time.time - lastCounterPatternTime >= config.counterCooldown) + { + weights[i] += config.counterWeightBonus; + } + } + + // 보조 카운터 가중치 + if (bossPatterns[i].subCounterType != CounterType.None + && activeCounters.ContainsKey(bossPatterns[i].subCounterType) + && activeCounters[bossPatterns[i].subCounterType]) + { + weights[i] += config.counterSubWeightBonus; + } + + // 습관 변경 보상: 일반 패턴 가중치 감소 (= 난이도 완화) + if (habitChangeRewardGranted && bossPatterns[i].counterType == CounterType.None) + { + weights[i] *= (1f - config.habitChangeRewardRatio); + } + + totalWeight += weights[i]; + + if (bossPatterns[i].counterType != CounterType.None) + counterWeight += weights[i]; + } + + // 빈도 상한 체크: 카운터 패턴 총 비율이 maxCounterFrequency를 넘지 않도록 + if (totalWeight > 0f && counterWeight / totalWeight > config.maxCounterFrequency) + { + float allowedCounterWeight = (totalWeight - counterWeight) * config.maxCounterFrequency / (1f - config.maxCounterFrequency); + float scale = allowedCounterWeight / counterWeight; + + for (int i = 0; i < bossPatterns.Count; i++) + { + if (bossPatterns[i].counterType != CounterType.None) + { + float bonus = weights[i] - bossPatterns[i].baseWeight; + weights[i] = bossPatterns[i].baseWeight + bonus * scale; + } + } + + // 총 가중치 재계산 + totalWeight = 0f; + for (int i = 0; i < weights.Length; i++) + totalWeight += weights[i]; + } + + // 가중치 랜덤 선택 + float roll = Random.Range(0f, totalWeight); + float cumulative = 0f; + + for (int i = 0; i < bossPatterns.Count; i++) + { + cumulative += weights[i]; + if (roll <= cumulative) + { + string selected = bossPatterns[i].patternName; + + // 카운터 패턴이면 쿨타임 기록 + if (bossPatterns[i].counterType != CounterType.None) + { + lastCounterPatternTime = Time.time; + } + + OnCounterPatternSelected?.Invoke(selected); + return selected; + } + } + + return bossPatterns[bossPatterns.Count - 1].patternName; + } + + // ═══════════════════════════════════════════ + // 외부 조회 + // ═══════════════════════════════════════════ + + /// 특정 카운터 모드가 현재 활성 상태인지 확인 + public bool IsCounterActive(CounterType type) + { + return activeCounters.ContainsKey(type) && activeCounters[type]; + } + + /// 현재 활성화된 모든 카운터 타입 반환 + public List GetActiveCounters() + { + var result = new List(); + foreach (var kvp in activeCounters) + { + if (kvp.Value) result.Add(kvp.Key); + } + return result; + } + + /// 습관 변경 보상이 활성화되었는지 확인 + public bool IsHabitChangeRewarded => habitChangeRewardGranted; +} diff --git a/Assets/Scripts/Enemy/BossAI/BossCounterSystem.cs.meta b/Assets/Scripts/Enemy/BossAI/BossCounterSystem.cs.meta new file mode 100644 index 00000000..ede5862d --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossCounterSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e36870a705f4fd44923bc5704c4a93b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossMonster.cs b/Assets/Scripts/Enemy/BossAI/BossMonster.cs new file mode 100644 index 00000000..cf2984a8 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossMonster.cs @@ -0,0 +1,222 @@ +using UnityEngine; +using System.Collections; + +public class NorcielBoss : MonsterClass +{ + [Header("--- 🧠 두뇌 연결 ---")] + [SerializeField] private BossCounterSystem counterSystem; + + [Header("--- ⚔️ 패턴 설정 ---")] + [SerializeField] private float patternInterval = 3f; // 공격 간격 + + [Header("--- 📊 UI 연결 ---")] + [SerializeField] private GameObject bossHealthBar; // 보스 체력바 UI (평소엔 꺼둠) + + // 내부 변수 + private float _timer; + private Rigidbody rb; + private bool isBattleStarted = false; // 전투 시작 여부 체크 + private Transform target; // 플레이어 타겟 + + protected override void Awake() + { + base.Awake(); + rb = GetComponent(); + } + + protected override void Init() + { + // 1. 기본 변수 초기화 + _timer = patternInterval; + + // 플레이어 찾기 (Tag: Player) + GameObject playerObj = GameObject.FindWithTag("Player"); + if (playerObj != null) + { + target = playerObj.transform; + } + else + { + var playerScript = FindObjectOfType(); + if (playerScript != null) target = playerScript.transform; + } + + // 2. 전투 시작 전 상태 설정 (봉인) + isBattleStarted = false; + + // 움직임 끄기 + if (agent != null) + { + agent.enabled = false; + agent.isStopped = true; + } + + // 체력바 숨기기 + if (bossHealthBar != null) bossHealthBar.SetActive(false); + } + + protected override void ExecuteAILogic() + { + // ⭐ 전투 미시작 or 타겟 없음 -> 정지 + if (!isBattleStarted || target == null) return; + + // 1. 공격 쿨타임 체크 + _timer -= Time.deltaTime; + + // 쿨타임 끝 + 공격중 아님 + 피격중 아님 + 살아있음 -> 공격 시도 + if (_timer <= 0 && !isAttacking && !isHit && !isDead) + { + _timer = patternInterval; + DecideAttack(); + } + + // 2. 이동 및 애니메이션 처리 (평소 상태) + if (!isAttacking && agent.enabled) + { + agent.SetDestination(target.position); + + // ──────── ⭐ [핵심] 이동 애니메이션 동기화 ──────── + if (animator != null) + { + // 현재 이동 속도를 가져와서 애니메이터에 전달 (0 ~ 3.5 ~ ...) + // Animator의 Blend Tree가 이 값을 받아 Idle/Walk/Run을 섞어줌 + float currentSpeed = agent.velocity.magnitude; + animator.SetFloat("Speed", currentSpeed); + } + // ────────────────────────────────────────────── + + // 사거리 안으로 들어왔거나 너무 가까우면 멈춤 + if (agent.remainingDistance <= agent.stoppingDistance) + { + agent.isStopped = true; + + // 몸을 플레이어 쪽으로 돌리기 + Vector3 dir = target.position - transform.position; + dir.y = 0; + if (dir != Vector3.zero) + { + transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * 5f); + } + } + else + { + agent.isStopped = false; + } + } + } + + // ════════════════════════════════════════ + // 🎬 전투 입장 시스템 (외부 호출용) + // ════════════════════════════════════════ + + public void StartBossBattle() + { + if (isBattleStarted) return; + StartCoroutine(BattleStartRoutine()); + } + + private IEnumerator BattleStartRoutine() + { + // 포효 (스트링 방식) + if (animator != null) animator.Play("Roar"); + + Debug.Log("😈 보스: 감히 내 영역에 들어오다니! (전투 시작)"); + + if (bossHealthBar != null) bossHealthBar.SetActive(true); + if (counterSystem != null) counterSystem.InitializeBattle(); + + yield return new WaitForSeconds(2.0f); // 포효 끝날 때까지 대기 + + isBattleStarted = true; + if (agent != null) agent.enabled = true; + } + + // ════════════════════════════════════════ + // 🧠 AI 판단 및 공격 실행 + // ════════════════════════════════════════ + + private void DecideAttack() + { + // 이동 애니메이션 잠시 0으로 (미끄러짐 방지) + if (animator != null) animator.SetFloat("Speed", 0f); + + string patternName = (counterSystem != null) ? counterSystem.SelectBossPattern() : "Normal"; + Debug.Log($"🤖 보스 AI 결정: {patternName}"); + + switch (patternName) + { + case "DashAttack": + StartCoroutine(Pattern_DashAttack()); + break; + case "Smash": + StartCoroutine(Pattern_SmashAttack()); + break; + case "ShieldWall": + StartCoroutine(Pattern_ShieldWall()); + break; + default: + StartCoroutine(Pattern_NormalShoot()); + break; + } + } + + // ════════════════════════════════════════ + // ⚔️ 공격 패턴 코루틴 (스트링 방식) + // ════════════════════════════════════════ + + private IEnumerator Pattern_DashAttack() + { + OnAttackStart(); + + if (animator != null) animator.Play("Skill_Dash_Ready"); + yield return new WaitForSeconds(0.5f); + + // 돌진 (물리 이동) + if (agent != null) agent.enabled = false; + if (rb != null) + { + rb.isKinematic = false; + rb.velocity = transform.forward * 20f; + } + + if (animator != null) animator.Play("Skill_Dash_Go"); + yield return new WaitForSeconds(1.0f); + + // 복구 + if (rb != null) + { + rb.velocity = Vector3.zero; + rb.isKinematic = true; + } + + if (agent != null && isBattleStarted) agent.enabled = true; + OnAttackEnd(); + } + + private IEnumerator Pattern_SmashAttack() + { + OnAttackStart(); + if (animator != null) animator.Play("Skill_Smash_Charge"); + yield return new WaitForSeconds(1.2f); + + if (animator != null) animator.Play("Skill_Smash_Impact"); + yield return new WaitForSeconds(1.0f); + OnAttackEnd(); + } + + private IEnumerator Pattern_ShieldWall() + { + OnAttackStart(); + if (animator != null) animator.Play("Skill_Shield"); + yield return new WaitForSeconds(2.0f); + OnAttackEnd(); + } + + private IEnumerator Pattern_NormalShoot() + { + OnAttackStart(); + if (animator != null) animator.Play("Attack_Shoot"); + yield return new WaitForSeconds(1.0f); + OnAttackEnd(); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Enemy/BossAI/BossMonster.cs.meta b/Assets/Scripts/Enemy/BossAI/BossMonster.cs.meta new file mode 100644 index 00000000..204d96e2 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossMonster.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 04f39bf969074e6488f84b47bd517dc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/BossZoneTrigger.cs b/Assets/Scripts/Enemy/BossAI/BossZoneTrigger.cs new file mode 100644 index 00000000..2d4677dc --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossZoneTrigger.cs @@ -0,0 +1,29 @@ +using UnityEngine; + +public class BossZoneTrigger : MonoBehaviour +{ + [SerializeField] private NorcielBoss boss; // + [SerializeField] private GameObject fogWall; // Ա Ȱ () + + private bool hasTriggered = false; + + private void OnTriggerEnter(Collider other) + { + // ̹ ߵ߰ų, ÷̾ ƴϸ + if (hasTriggered) return; + + if (other.CompareTag("Player")) + { + hasTriggered = true; + + // 1. + if (boss != null) boss.StartBossBattle(); + + // 2. Ա () + if (fogWall != null) fogWall.SetActive(true); + + // 3. ƮŴ + // gameObject.SetActive(false); // ٷ Ȱ + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Enemy/BossAI/BossZoneTrigger.cs.meta b/Assets/Scripts/Enemy/BossAI/BossZoneTrigger.cs.meta new file mode 100644 index 00000000..c35a8a33 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/BossZoneTrigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 086f3fc0675122448a8950f910dc4864 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enemy/BossAI/CounterType.cs b/Assets/Scripts/Enemy/BossAI/CounterType.cs new file mode 100644 index 00000000..cab44c60 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/CounterType.cs @@ -0,0 +1,10 @@ +/// +/// 보스 카운터 패턴 타입 열거형 +/// +public enum CounterType +{ + None, + Dodge, // 회피 남발 카운터 + Aim, // 정조준 과다 카운터 + Pierce // 관통 화살 편중 카운터 +} diff --git a/Assets/Scripts/Enemy/BossAI/CounterType.cs.meta b/Assets/Scripts/Enemy/BossAI/CounterType.cs.meta new file mode 100644 index 00000000..e39ed0d8 --- /dev/null +++ b/Assets/Scripts/Enemy/BossAI/CounterType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb38b1f2aa504c74c9f597c141d6ba47 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Player/Combat/BossCounterConfig.asset b/Assets/Scripts/Player/Combat/BossCounterConfig.asset new file mode 100644 index 00000000..1b3fd727 --- /dev/null +++ b/Assets/Scripts/Player/Combat/BossCounterConfig.asset @@ -0,0 +1,25 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 127d57ae132759d4f8233580c8075e39, type: 3} + m_Name: BossCounterConfig + m_EditorClassIdentifier: + dodgeThreshold: 5 + aimThreshold: 4 + pierceThreshold: 0.6 + minShotsForPierceCheck: 3 + unlockedThresholdMultiplier: 0.8 + counterWeightBonus: 3 + counterSubWeightBonus: 2 + counterDecayTime: 8 + maxCounterFrequency: 0.25 + counterCooldown: 5 + habitChangeRewardRatio: 0.15 diff --git a/Assets/Scripts/Player/Combat/BossCounterConfig.asset.meta b/Assets/Scripts/Player/Combat/BossCounterConfig.asset.meta new file mode 100644 index 00000000..11dabedf --- /dev/null +++ b/Assets/Scripts/Player/Combat/BossCounterConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c6a2993f687f65409c4ece370872444 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Player/Controller/PlayerBehaviorTracker.cs b/Assets/Scripts/Player/Controller/PlayerBehaviorTracker.cs new file mode 100644 index 00000000..44cb5543 --- /dev/null +++ b/Assets/Scripts/Player/Controller/PlayerBehaviorTracker.cs @@ -0,0 +1,147 @@ +using System.Collections.Generic; +using UnityEngine; + +/// +/// 플레이어의 전투 행동을 슬라이딩 윈도우(최근 N초) 기반으로 추적합니다. +/// 보스 AI가 이 데이터를 읽어 카운터 패턴 발동 여부를 판단합니다. +/// +public class PlayerBehaviorTracker : MonoBehaviour +{ + public static PlayerBehaviorTracker Instance { get; private set; } + + [Header("슬라이딩 윈도우 설정")] + [Tooltip("행동 추적 윈도우 크기(초)")] + [SerializeField] private float windowDuration = 10f; + + // ── 내부 기록용 타임스탬프 리스트 ── + private List dodgeTimestamps = new List(); + private List aimStartTimes = new List(); + private List aimEndTimes = new List(); + private List pierceShotTimestamps = new List(); + private List totalShotTimestamps = new List(); + + // ── 현재 조준 상태 ── + private bool isAiming = false; + private float currentAimStartTime; + + // ── 외부에서 읽는 프로퍼티 ── + public int DodgeCount => CountInWindow(dodgeTimestamps); + public float AimHoldTime => CalculateAimHoldTime(); + public float PierceRatio => CalculatePierceRatio(); + public int TotalShotsInWindow => CountInWindow(totalShotTimestamps); + + private void Awake() + { + if (Instance != null && Instance != this) + { + Destroy(gameObject); + return; + } + Instance = this; + } + + // ═══════════════════════════════════════════ + // 외부에서 호출하는 이벤트 기록 메서드 + // ═══════════════════════════════════════════ + + /// 플레이어가 회피(대시/구르기)를 수행했을 때 호출 + public void RecordDodge() + { + dodgeTimestamps.Add(Time.time); + } + + /// 플레이어가 조준을 시작했을 때 호출 + public void RecordAimStart() + { + if (!isAiming) + { + isAiming = true; + currentAimStartTime = Time.time; + } + } + + /// 플레이어가 조준을 해제했을 때 호출 + public void RecordAimEnd() + { + if (isAiming) + { + isAiming = false; + aimStartTimes.Add(currentAimStartTime); + aimEndTimes.Add(Time.time); + } + } + + /// 화살 발사 시 호출. isPierce=true면 관통 화살 + public void RecordShot(bool isPierce) + { + totalShotTimestamps.Add(Time.time); + if (isPierce) + { + pierceShotTimestamps.Add(Time.time); + } + } + + // ═══════════════════════════════════════════ + // 런 리셋 (새 런 시작 시 호출) + // ═══════════════════════════════════════════ + + /// 새 런 시작 시 모든 행동 기록을 초기화 + public void ResetForNewRun() + { + dodgeTimestamps.Clear(); + aimStartTimes.Clear(); + aimEndTimes.Clear(); + pierceShotTimestamps.Clear(); + totalShotTimestamps.Clear(); + isAiming = false; + } + + // ═══════════════════════════════════════════ + // 내부 계산 + // ═══════════════════════════════════════════ + + private int CountInWindow(List timestamps) + { + float cutoff = Time.time - windowDuration; + // 오래된 항목 제거 + timestamps.RemoveAll(t => t < cutoff); + return timestamps.Count; + } + + private float CalculateAimHoldTime() + { + float cutoff = Time.time - windowDuration; + float total = 0f; + + // 완료된 조준 세션 + for (int i = aimStartTimes.Count - 1; i >= 0; i--) + { + if (aimEndTimes[i] < cutoff) + { + aimStartTimes.RemoveAt(i); + aimEndTimes.RemoveAt(i); + continue; + } + float start = Mathf.Max(aimStartTimes[i], cutoff); + total += aimEndTimes[i] - start; + } + + // 현재 조준 중인 시간도 포함 + if (isAiming) + { + float start = Mathf.Max(currentAimStartTime, cutoff); + total += Time.time - start; + } + + return total; + } + + private float CalculatePierceRatio() + { + int totalShots = CountInWindow(totalShotTimestamps); + if (totalShots == 0) return 0f; + + int pierceShots = CountInWindow(pierceShotTimestamps); + return (float)pierceShots / totalShots; + } +} diff --git a/Assets/Scripts/Player/Controller/PlayerBehaviorTracker.cs.meta b/Assets/Scripts/Player/Controller/PlayerBehaviorTracker.cs.meta new file mode 100644 index 00000000..12fa47d9 --- /dev/null +++ b/Assets/Scripts/Player/Controller/PlayerBehaviorTracker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 320dac90fad4bd94dbdc466f5f2458cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/HUD/HP Ui bar.cs b/Assets/Scripts/UI/HUD/HP Ui bar.cs index 79ca770c..507a02a5 100644 --- a/Assets/Scripts/UI/HUD/HP Ui bar.cs +++ b/Assets/Scripts/UI/HUD/HP Ui bar.cs @@ -53,4 +53,4 @@ public class HPUibar : MonoBehaviour else if (healthSource is EnemyHealth eh) eh.OnHealthChanged -= UpdateUI; else if (healthSource is MonsterClass mc) mc.OnHealthChanged -= UpdateUI; } -} \ No newline at end of file +}