From b7db292987a9c3f874b8382e396c133c7be78f24 Mon Sep 17 00:00:00 2001 From: Luis Gonzalez Date: Mon, 6 Jul 2026 20:44:21 -0700 Subject: [PATCH] Blender-authored clips: real death fall, fire thrust, dash lean, hit-react (Phase 1 anim triage) Four clips authored programmatically in Blender on the PolygonSyntyCharacter skeleton (full-body keys per pose, numeric world-space verification of the fall: hips 0.88->0.14m) and exported per-action FBX (Key All Bones, Force Start/End Keying, FBX Units Scale). Imported as HUMANOID - the project's pipeline is Human rigs (CharactersAvatar isHuman=true; CLAUDE.md's 'Generic' note was stale), so muscle-space retargeting plays these on the player AND every monster rig with zero bone-path matching. CopyFromOther failed on the Blender-added 'Armature' node (hierarchy mismatch) -> CreateFromThisModel; root motion fully baked into pose (the CC owns the transform). - A_Death_FallBack (0.90s = exactly the 54-tick corpse window): recoil -> fall -> flat on the back -> settle. Wired as the Death state on BOTH controllers, replacing the crouch-idle placeholder. - A_Fire_OneHand (0.4s): new IsFiring param + Fire state on the player controller; PlayerAnimationDriveSystem routes FireActive to it (melee owns IsAttacking again). - A_Dash_Lean (0.33s): new IsDashing param + Dash state; driven from the local player's predicted DashState window (not replicated -> remotes skip). - A_HitReact (0.27s): imported + avatar'd, wiring deferred (needs a replicated hit-tick source; body flash covers the read today). 456/456 EditMode; Play-validated: forced IsDead renders the soldier flat on the ground in-game (Blender->FBX->Humanoid->Rukhanka chain proven), Fire state enters and plays; console clean. Co-Authored-By: Claude Fable 5 --- Assets/Screenshots/iter_anim_death.png | 3 + Assets/Screenshots/iter_anim_death.png.meta | 117 ++++++++++++ Assets/Screenshots/iter_anim_fire.png | 3 + Assets/Screenshots/iter_anim_fire.png.meta | 117 ++++++++++++ .../Animation/AC_EnemyTopDown.controller | 2 +- .../Animation/AC_PlayerTopDown.controller | 176 +++++++++++++++++- Assets/_Project/Animation/Authored.meta | 8 + .../Animation/Authored/A_Dash_Lean.fbx | 3 + .../Animation/Authored/A_Dash_Lean.fbx.meta | 143 ++++++++++++++ .../Animation/Authored/A_Death_FallBack.fbx | 3 + .../Authored/A_Death_FallBack.fbx.meta | 143 ++++++++++++++ .../Animation/Authored/A_Fire_OneHand.fbx | 3 + .../Authored/A_Fire_OneHand.fbx.meta | 143 ++++++++++++++ .../Animation/Authored/A_HitReact.fbx | 3 + .../Animation/Authored/A_HitReact.fbx.meta | 143 ++++++++++++++ .../PlayerAnimationDriveSystem.cs | 35 +++- 16 files changed, 1033 insertions(+), 12 deletions(-) create mode 100644 Assets/Screenshots/iter_anim_death.png create mode 100644 Assets/Screenshots/iter_anim_death.png.meta create mode 100644 Assets/Screenshots/iter_anim_fire.png create mode 100644 Assets/Screenshots/iter_anim_fire.png.meta create mode 100644 Assets/_Project/Animation/Authored.meta create mode 100644 Assets/_Project/Animation/Authored/A_Dash_Lean.fbx create mode 100644 Assets/_Project/Animation/Authored/A_Dash_Lean.fbx.meta create mode 100644 Assets/_Project/Animation/Authored/A_Death_FallBack.fbx create mode 100644 Assets/_Project/Animation/Authored/A_Death_FallBack.fbx.meta create mode 100644 Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx create mode 100644 Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx.meta create mode 100644 Assets/_Project/Animation/Authored/A_HitReact.fbx create mode 100644 Assets/_Project/Animation/Authored/A_HitReact.fbx.meta diff --git a/Assets/Screenshots/iter_anim_death.png b/Assets/Screenshots/iter_anim_death.png new file mode 100644 index 000000000..e76f1a08b --- /dev/null +++ b/Assets/Screenshots/iter_anim_death.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e38bd913be9bab4a2dd2d04c1e2d19cfef5869141a0bc830cf2443433f265b6f +size 122798 diff --git a/Assets/Screenshots/iter_anim_death.png.meta b/Assets/Screenshots/iter_anim_death.png.meta new file mode 100644 index 000000000..c7a6e5f53 --- /dev/null +++ b/Assets/Screenshots/iter_anim_death.png.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 9a1ffecfe52c3d545b34ad532c50dc18 +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: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Screenshots/iter_anim_fire.png b/Assets/Screenshots/iter_anim_fire.png new file mode 100644 index 000000000..c87fc2f4c --- /dev/null +++ b/Assets/Screenshots/iter_anim_fire.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac2f5adc068d2d2c29009fecdd45a54c80840b68905d3aad570af9264679c38d +size 182778 diff --git a/Assets/Screenshots/iter_anim_fire.png.meta b/Assets/Screenshots/iter_anim_fire.png.meta new file mode 100644 index 000000000..1cb7d1d1e --- /dev/null +++ b/Assets/Screenshots/iter_anim_fire.png.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 0e8b1c1ac1882ff4fbc5c5357c98bc6a +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: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Animation/AC_EnemyTopDown.controller b/Assets/_Project/Animation/AC_EnemyTopDown.controller index 0c0c36d84..c0ebb4589 100644 --- a/Assets/_Project/Animation/AC_EnemyTopDown.controller +++ b/Assets/_Project/Animation/AC_EnemyTopDown.controller @@ -289,7 +289,7 @@ AnimatorState: m_MirrorParameterActive: 0 m_CycleOffsetParameterActive: 0 m_TimeParameterActive: 0 - m_Motion: {fileID: 1827226128182048838, guid: 52a2eb3158000934eb33267c807b8b15, type: 3} + m_Motion: {fileID: -623603649343465320, guid: 65d8851d683f4784b9f64c2f37c952c7, type: 3} m_Tag: m_SpeedParameter: m_MirrorParameter: diff --git a/Assets/_Project/Animation/AC_PlayerTopDown.controller b/Assets/_Project/Animation/AC_PlayerTopDown.controller index b61afe024..6f24b3a14 100644 --- a/Assets/_Project/Animation/AC_PlayerTopDown.controller +++ b/Assets/_Project/Animation/AC_PlayerTopDown.controller @@ -52,6 +52,135 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 0 +--- !u!1101 &-7234718347717616583 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 2 + m_ConditionEvent: IsDashing + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 0} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 1 + serializedVersion: 3 + m_TransitionDuration: 0.08 + m_TransitionOffset: 0 + m_ExitTime: 0.9 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 +--- !u!1102 &-6549861468947298911 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Fire + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: -1232926890831217747} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: -623603649343465320, guid: 921743812b4898b4c89cc5f637e26889, type: 3} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!1101 &-6440685791176414979 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 1 + m_ConditionEvent: IsFiring + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -6549861468947298911} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0.05 + m_TransitionOffset: 0 + m_ExitTime: 0.75 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 0 +--- !u!1101 &-6300955673352805084 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 1 + m_ConditionEvent: IsDashing + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: -6118587240689107635} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0.03 + m_TransitionOffset: 0 + m_ExitTime: 0.75 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 0 +--- !u!1102 &-6118587240689107635 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Dash + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: + - {fileID: -7234718347717616583} + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: -623603649343465320, guid: ea8f7b0efaae2b9409e642adac0a3ec8, type: 3} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: --- !u!1101 &-1505565898738729052 AnimatorStateTransition: m_ObjectHideFlags: 1 @@ -77,6 +206,31 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 1 +--- !u!1101 &-1232926890831217747 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 2 + m_ConditionEvent: IsFiring + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 0} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 1 + serializedVersion: 3 + m_TransitionDuration: 0.1 + m_TransitionOffset: 0 + m_ExitTime: 0.9 + m_HasExitTime: 0 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 --- !u!206 &-481359581180607483 BlendTree: m_ObjectHideFlags: 0 @@ -203,6 +357,18 @@ AnimatorController: m_DefaultInt: 0 m_DefaultBool: 0 m_Controller: {fileID: 9100000} + - m_Name: IsFiring + m_Type: 4 + m_DefaultFloat: 0 + m_DefaultInt: 0 + m_DefaultBool: 0 + m_Controller: {fileID: 9100000} + - m_Name: IsDashing + m_Type: 4 + m_DefaultFloat: 0 + m_DefaultInt: 0 + m_DefaultBool: 0 + m_Controller: {fileID: 9100000} m_AnimatorLayers: - serializedVersion: 5 m_Name: Base Layer @@ -262,7 +428,7 @@ AnimatorState: m_MirrorParameterActive: 0 m_CycleOffsetParameterActive: 0 m_TimeParameterActive: 0 - m_Motion: {fileID: 1827226128182048838, guid: 52a2eb3158000934eb33267c807b8b15, type: 3} + m_Motion: {fileID: -623603649343465320, guid: 65d8851d683f4784b9f64c2f37c952c7, type: 3} m_Tag: m_SpeedParameter: m_MirrorParameter: @@ -341,10 +507,18 @@ AnimatorStateMachine: - serializedVersion: 1 m_State: {fileID: 4550302468649108848} m_Position: {x: 305, y: 195, z: 0} + - serializedVersion: 1 + m_State: {fileID: -6549861468947298911} + m_Position: {x: 340, y: 260, z: 0} + - serializedVersion: 1 + m_State: {fileID: -6118587240689107635} + m_Position: {x: 375, y: 325, z: 0} m_ChildStateMachines: [] m_AnyStateTransitions: - {fileID: 5014557051428573475} - {fileID: -7833896337878999491} + - {fileID: -6440685791176414979} + - {fileID: -6300955673352805084} m_EntryTransitions: [] m_StateMachineTransitions: {} m_StateMachineBehaviours: [] diff --git a/Assets/_Project/Animation/Authored.meta b/Assets/_Project/Animation/Authored.meta new file mode 100644 index 000000000..874675326 --- /dev/null +++ b/Assets/_Project/Animation/Authored.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1ec4145aa41b2cc4c8cac412d547982b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Animation/Authored/A_Dash_Lean.fbx b/Assets/_Project/Animation/Authored/A_Dash_Lean.fbx new file mode 100644 index 000000000..8880c744e --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_Dash_Lean.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34e35bbfec919d2b13c78c0f56348d878dfde30cffe07e5d8dabf0f43176579e +size 312780 diff --git a/Assets/_Project/Animation/Authored/A_Dash_Lean.fbx.meta b/Assets/_Project/Animation/Authored/A_Dash_Lean.fbx.meta new file mode 100644 index 000000000..e65e696d8 --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_Dash_Lean.fbx.meta @@ -0,0 +1,143 @@ +fileFormatVersion: 2 +guid: ea8f7b0efaae2b9409e642adac0a3ec8 +ModelImporter: + serializedVersion: 24501 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: A_Dash_Lean + takeName: Scene + internalID: -623603649343465320 + firstFrame: 0 + lastFrame: 10 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 1 + loopBlendPositionY: 1 + loopBlendPositionXZ: 1 + 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 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + importUVs: -1 + importVertexColors: 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 + calculateBlendshapeNormalsDeltaFromImportedNormals: 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/_Project/Animation/Authored/A_Death_FallBack.fbx b/Assets/_Project/Animation/Authored/A_Death_FallBack.fbx new file mode 100644 index 000000000..50d183d26 --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_Death_FallBack.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3517215fce1f0daabcf2cb7896c2b86aa42b55271ed30a0bcf435e0c0f6eeee +size 315964 diff --git a/Assets/_Project/Animation/Authored/A_Death_FallBack.fbx.meta b/Assets/_Project/Animation/Authored/A_Death_FallBack.fbx.meta new file mode 100644 index 000000000..fe7dde58e --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_Death_FallBack.fbx.meta @@ -0,0 +1,143 @@ +fileFormatVersion: 2 +guid: 65d8851d683f4784b9f64c2f37c952c7 +ModelImporter: + serializedVersion: 24501 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: A_Death_FallBack + takeName: Scene + internalID: -623603649343465320 + firstFrame: 0 + lastFrame: 27 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 1 + loopBlendPositionY: 1 + loopBlendPositionXZ: 1 + 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 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + importUVs: -1 + importVertexColors: 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 + calculateBlendshapeNormalsDeltaFromImportedNormals: 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/_Project/Animation/Authored/A_Fire_OneHand.fbx b/Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx new file mode 100644 index 000000000..b95577baa --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3bbf144d3e931eac3e2704bc9d064be9d0e56469b45b9b71f4a2a1403c525e12 +size 312508 diff --git a/Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx.meta b/Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx.meta new file mode 100644 index 000000000..340be9060 --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_Fire_OneHand.fbx.meta @@ -0,0 +1,143 @@ +fileFormatVersion: 2 +guid: 921743812b4898b4c89cc5f637e26889 +ModelImporter: + serializedVersion: 24501 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: A_Fire_OneHand + takeName: Scene + internalID: -623603649343465320 + firstFrame: 0 + lastFrame: 12 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 1 + loopBlendPositionY: 1 + loopBlendPositionXZ: 1 + 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 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + importUVs: -1 + importVertexColors: 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 + calculateBlendshapeNormalsDeltaFromImportedNormals: 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/_Project/Animation/Authored/A_HitReact.fbx b/Assets/_Project/Animation/Authored/A_HitReact.fbx new file mode 100644 index 000000000..f21f9bebe --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_HitReact.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bccc579f761fe40ea4730953a1831da8f4ea3ae1f04fda3a0c06a9c33e7a98b3 +size 312108 diff --git a/Assets/_Project/Animation/Authored/A_HitReact.fbx.meta b/Assets/_Project/Animation/Authored/A_HitReact.fbx.meta new file mode 100644 index 000000000..fa5972d14 --- /dev/null +++ b/Assets/_Project/Animation/Authored/A_HitReact.fbx.meta @@ -0,0 +1,143 @@ +fileFormatVersion: 2 +guid: 0f2461f6c2e61884790171b7755833c8 +ModelImporter: + serializedVersion: 24501 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + searchTexturesGlobally: 0 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: + - serializedVersion: 16 + name: A_HitReact + takeName: Scene + internalID: -623603649343465320 + firstFrame: 0 + lastFrame: 8 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 0 + loopBlend: 0 + loopBlendOrientation: 1 + loopBlendPositionY: 1 + loopBlendPositionXZ: 1 + 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 + generateMeshLods: 0 + meshLodGenerationFlags: 0 + maximumMeshLod: -1 + importUVs: -1 + importVertexColors: 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 + calculateBlendshapeNormalsDeltaFromImportedNormals: 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/_Project/Scripts/Client/Presentation/PlayerAnimationDriveSystem.cs b/Assets/_Project/Scripts/Client/Presentation/PlayerAnimationDriveSystem.cs index 5c4cf1ea4..2e6d9eef6 100644 --- a/Assets/_Project/Scripts/Client/Presentation/PlayerAnimationDriveSystem.cs +++ b/Assets/_Project/Scripts/Client/Presentation/PlayerAnimationDriveSystem.cs @@ -44,6 +44,8 @@ namespace ProjectM.Client static readonly FastAnimatorParameter k_Speed = new FastAnimatorParameter("Speed"); static readonly FastAnimatorParameter k_IsDead = new FastAnimatorParameter("IsDead"); static readonly FastAnimatorParameter k_IsAttacking = new FastAnimatorParameter("IsAttacking"); + static readonly FastAnimatorParameter k_IsFiring = new FastAnimatorParameter("IsFiring"); // Blender-authored A_Fire_OneHand (B7) + static readonly FastAnimatorParameter k_IsDashing = new FastAnimatorParameter("IsDashing"); // Blender-authored A_Dash_Lean (local player only - DashState is not replicated) // Ticks after a swing-start that IsAttacking stays true (drives the MeleeSwing state). Kept < the swing lock // (MeleeRecoverTicks ~16) so a CHAINED swing re-pulses the bool false->true and re-triggers the Any State @@ -75,7 +77,8 @@ namespace ProjectM.Client var localJob = new LocalDriveJob { moveX = k_MoveX, moveZ = k_MoveZ, speed = k_Speed, isDead = k_IsDead, - isAttacking = k_IsAttacking, serverTick = serverTick, attackTicks = k_AttackAnimTicks, + isAttacking = k_IsAttacking, isFiring = k_IsFiring, isDashing = k_IsDashing, + serverTick = serverTick, attackTicks = k_AttackAnimTicks, }; Dependency = localJob.ScheduleParallel(Dependency); @@ -84,7 +87,8 @@ namespace ProjectM.Client var remoteJob = new RemoteDriveJob { moveX = k_MoveX, moveZ = k_MoveZ, speed = k_Speed, isDead = k_IsDead, - isAttacking = k_IsAttacking, serverTick = serverTick, attackTicks = k_AttackAnimTicks, + isAttacking = k_IsAttacking, isFiring = k_IsFiring, isDashing = k_IsDashing, + serverTick = serverTick, attackTicks = k_AttackAnimTicks, dt = dt, prevPos = _prevPos, seen = seen, @@ -135,7 +139,7 @@ namespace ProjectM.Client [WithPresent(typeof(Dead))] partial struct LocalDriveJob : IJobEntity { - public FastAnimatorParameter moveX, moveZ, speed, isDead, isAttacking; + public FastAnimatorParameter moveX, moveZ, speed, isDead, isAttacking, isFiring, isDashing; public NetworkTick serverTick; public uint attackTicks; @@ -148,14 +152,24 @@ namespace ProjectM.Client in MeleeCombo melee, in AbilityCooldown fireCooldown, in EffectiveAbilityStats abilityStats, + in DashState dashState, EnabledRefRO dead) { var a = new AnimatorParametersAspect(parametersArr, indexTable); float3 p = AnimParamMath.LocomotionParams(body.RelativeVelocity, facing.Direction, stats.MoveSpeed); Write(ref a, p, dead.ValueRO, moveX, moveZ, speed, isDead); - if (a.HasParameter(isAttacking)) a.SetParameterValue(isAttacking, - SwingActive(melee, serverTick, attackTicks) - || FireActive(fireCooldown.NextFireTick, abilityStats.CooldownTicks, serverTick, attackTicks)); + if (a.HasParameter(isAttacking)) a.SetParameterValue(isAttacking, SwingActive(melee, serverTick, attackTicks)); + if (a.HasParameter(isFiring)) a.SetParameterValue(isFiring, + FireActive(fireCooldown.NextFireTick, abilityStats.CooldownTicks, serverTick, attackTicks)); + // Dash lean: the LOCAL player's predicted DashState window [StartTick, IFrameUntilTick+tail). + bool dashActive = false; + if (dashState.StartTick != 0u && dashState.IFrameUntilTick != 0u && serverTick.IsValid) + { + var dStart = new NetworkTick(dashState.StartTick); + var dEnd = new NetworkTick(TickUtil.NonZero(dashState.IFrameUntilTick + 6u)); + dashActive = dStart.IsValid && dEnd.IsValid && !dStart.IsNewerThan(serverTick) && dEnd.IsNewerThan(serverTick); + } + if (a.HasParameter(isDashing)) a.SetParameterValue(isDashing, dashActive); } } @@ -166,7 +180,7 @@ namespace ProjectM.Client [WithPresent(typeof(Dead))] partial struct RemoteDriveJob : IJobEntity { - public FastAnimatorParameter moveX, moveZ, speed, isDead, isAttacking; + public FastAnimatorParameter moveX, moveZ, speed, isDead, isAttacking, isFiring, isDashing; public NetworkTick serverTick; public uint attackTicks; public float dt; @@ -195,9 +209,10 @@ namespace ProjectM.Client var a = new AnimatorParametersAspect(parametersArr, indexTable); float3 p = AnimParamMath.LocomotionParams(vel, facing.Direction, stats.MoveSpeed); Write(ref a, p, dead.ValueRO, moveX, moveZ, speed, isDead); - if (a.HasParameter(isAttacking)) a.SetParameterValue(isAttacking, - SwingActive(melee, serverTick, attackTicks) - || FireActive(fireCooldown.NextFireTick, abilityStats.CooldownTicks, serverTick, attackTicks)); + if (a.HasParameter(isAttacking)) a.SetParameterValue(isAttacking, SwingActive(melee, serverTick, attackTicks)); + if (a.HasParameter(isFiring)) a.SetParameterValue(isFiring, + FireActive(fireCooldown.NextFireTick, abilityStats.CooldownTicks, serverTick, attackTicks)); + if (a.HasParameter(isDashing)) a.SetParameterValue(isDashing, false); // DashState is not replicated to remotes } }