diff --git a/Assets/_Project/Animations/Pet/Pet_Devil.controller b/Assets/_Project/Animations/Pet/Pet_Devil.controller index 7b83beab..39126020 100644 --- a/Assets/_Project/Animations/Pet/Pet_Devil.controller +++ b/Assets/_Project/Animations/Pet/Pet_Devil.controller @@ -59,7 +59,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Interact_BesideDoor + m_Name: Interact_LookAround m_Speed: 1 m_CycleOffset: 0 m_Transitions: [] @@ -85,7 +85,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Interact_Read + m_Name: Interact_DevilSleep m_Speed: 1 m_CycleOffset: 0 m_Transitions: [] @@ -98,7 +98,7 @@ AnimatorState: m_MirrorParameterActive: 0 m_CycleOffsetParameterActive: 0 m_TimeParameterActive: 0 - m_Motion: {fileID: 7400000, guid: e0f487d465d84c6c82e7e56e39cd0309, type: 2} + m_Motion: {fileID: 7400000, guid: a976212022ce4b658fa0814dfcfb1aed, type: 2} m_Tag: m_SpeedParameter: m_MirrorParameter: @@ -130,32 +130,6 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: ---- !u!1102 &-5650042031450080012 -AnimatorState: - serializedVersion: 6 - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Interact_Flower - m_Speed: 1 - m_CycleOffset: 0 - m_Transitions: [] - 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: 7400000, guid: 4f5a2cb8f6de4f8bbf3b0d0011aa1001, type: 2} - m_Tag: - m_SpeedParameter: - m_MirrorParameter: - m_CycleOffsetParameter: - m_TimeParameter: --- !u!1102 &-4650042031450080012 AnimatorState: serializedVersion: 6 @@ -163,7 +137,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Interact_PlayingMusic + m_Name: Interact_PlayGame m_Speed: 1 m_CycleOffset: 0 m_Transitions: [] @@ -189,7 +163,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Interact_Write + m_Name: Interact_Draw m_Speed: 1 m_CycleOffset: 0 m_Transitions: [] @@ -398,9 +372,6 @@ AnimatorStateMachine: - serializedVersion: 1 m_State: {fileID: -6650042031450080012} m_Position: {x: 450, y: 190, z: 0} - - serializedVersion: 1 - m_State: {fileID: -5650042031450080012} - m_Position: {x: 630, y: 30, z: 0} - serializedVersion: 1 m_State: {fileID: -4650042031450080012} m_Position: {x: 630, y: 110, z: 0} @@ -446,32 +417,6 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: ---- !u!1102 &5662408786982249231 -AnimatorState: - serializedVersion: 6 - m_ObjectHideFlags: 1 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Idle_Front - m_Speed: 1 - m_CycleOffset: 0 - m_Transitions: [] - 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: 7400000, guid: dabe4249caa546a88cbd5d97d1b95144, type: 2} - m_Tag: - m_SpeedParameter: - m_MirrorParameter: - m_CycleOffsetParameter: - m_TimeParameter: --- !u!1101 &8581778968068380458 AnimatorStateTransition: m_ObjectHideFlags: 1 @@ -500,3 +445,29 @@ AnimatorStateTransition: m_InterruptionSource: 0 m_OrderedInterruption: 1 m_CanTransitionToSelf: 0 +--- !u!1102 &5662408786982249231 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Idle_Front + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: [] + 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: 7400000, guid: dabe4249caa546a88cbd5d97d1b95144, type: 2} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: diff --git a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_BesideDoor.anim "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\345\267\246\345\217\263\347\234\213.anim" similarity index 98% rename from Assets/_Project/Animations/Pet/Pet_Devil_Interact_BesideDoor.anim rename to "Assets/_Project/Animations/Pet/Pet_Devil_Interact_\345\267\246\345\217\263\347\234\213.anim" index bf29b630..48fe7c1b 100644 --- a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_BesideDoor.anim +++ "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\345\267\246\345\217\263\347\234\213.anim" @@ -6,7 +6,7 @@ AnimationClip: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Pet_Devil_Interact_BesideDoor + m_Name: Pet_Devil_Interact_左右看 serializedVersion: 7 m_Legacy: 0 m_Compressed: 0 diff --git a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_BesideDoor.anim.meta "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\345\267\246\345\217\263\347\234\213.anim.meta" similarity index 100% rename from Assets/_Project/Animations/Pet/Pet_Devil_Interact_BesideDoor.anim.meta rename to "Assets/_Project/Animations/Pet/Pet_Devil_Interact_\345\267\246\345\217\263\347\234\213.anim.meta" diff --git a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_PlayingMusic.anim "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\216\251\346\216\214\346\234\272.anim" similarity index 99% rename from Assets/_Project/Animations/Pet/Pet_Devil_Interact_PlayingMusic.anim rename to "Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\216\251\346\216\214\346\234\272.anim" index b3ecbc94..1375fc39 100644 --- a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_PlayingMusic.anim +++ "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\216\251\346\216\214\346\234\272.anim" @@ -6,7 +6,7 @@ AnimationClip: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Pet_Devil_Interact_PlayingMusic + m_Name: Pet_Devil_Interact_玩掌机 serializedVersion: 7 m_Legacy: 0 m_Compressed: 0 diff --git a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_PlayingMusic.anim.meta "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\216\251\346\216\214\346\234\272.anim.meta" similarity index 100% rename from Assets/_Project/Animations/Pet/Pet_Devil_Interact_PlayingMusic.anim.meta rename to "Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\216\251\346\216\214\346\234\272.anim.meta" diff --git a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_Write.anim "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\224\273\347\224\273.anim" similarity index 99% rename from Assets/_Project/Animations/Pet/Pet_Devil_Interact_Write.anim rename to "Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\224\273\347\224\273.anim" index 9eb89dd5..70c3b242 100644 --- a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_Write.anim +++ "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\224\273\347\224\273.anim" @@ -6,7 +6,7 @@ AnimationClip: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Pet_Devil_Interact_Write + m_Name: Pet_Devil_Interact_画画 serializedVersion: 7 m_Legacy: 0 m_Compressed: 0 diff --git a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_Write.anim.meta "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\224\273\347\224\273.anim.meta" similarity index 100% rename from Assets/_Project/Animations/Pet/Pet_Devil_Interact_Write.anim.meta rename to "Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\224\273\347\224\273.anim.meta" diff --git "a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\235\241\350\247\211.anim" "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\235\241\350\247\211.anim" new file mode 100644 index 00000000..3981d8ad --- /dev/null +++ "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\235\241\350\247\211.anim" @@ -0,0 +1,99 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!74 &7400000 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Pet_Devil_Interact_睡觉 + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: [] + m_ScaleCurves: [] + m_FloatCurves: [] + m_PPtrCurves: + - serializedVersion: 2 + curve: + - time: 0 + value: {fileID: 21300000, guid: 2cc7a08223cd37d48a59d08cbb27d84d, type: 3} + - time: 0.08333333 + value: {fileID: 21300000, guid: fee560669016980429b6220f4cb96036, type: 3} + - time: 0.16666667 + value: {fileID: 21300000, guid: db0ae75b126aa9248a66d7f011480107, type: 3} + - time: 0.25 + value: {fileID: 21300000, guid: 46b5161c95402b546b31a22396e632f7, type: 3} + - time: 0.33333333 + value: {fileID: 21300000, guid: ed265137c45dceb4bae4f08ac0c3455e, type: 3} + - time: 0.41666667 + value: {fileID: 21300000, guid: a383699d71bcb4a4e9cf623692926176, type: 3} + - time: 0.5 + value: {fileID: 21300000, guid: 737fe7edd84ae164da6bdc6031493503, type: 3} + - time: 0.58333333 + value: {fileID: 21300000, guid: 7aaabe06485e83d40a2bd31ef9448722, type: 3} + - time: 0.66666667 + value: {fileID: 21300000, guid: 48fd6435f1c90384fa7e79514cf80888, type: 3} + - time: 0.75 + value: {fileID: 21300000, guid: 3bb71457e9820a2458b70f995dab641e, type: 3} + attribute: m_Sprite + path: + classID: 212 + script: {fileID: 0} + flags: 2 + m_SampleRate: 12 + m_WrapMode: 0 + m_Bounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 0, y: 0, z: 0} + m_ClipBindingConstant: + genericBindings: + - serializedVersion: 2 + path: 0 + attribute: 0 + script: {fileID: 0} + typeID: 212 + customType: 23 + isPPtrCurve: 1 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: + - {fileID: 21300000, guid: 2cc7a08223cd37d48a59d08cbb27d84d, type: 3} + - {fileID: 21300000, guid: fee560669016980429b6220f4cb96036, type: 3} + - {fileID: 21300000, guid: db0ae75b126aa9248a66d7f011480107, type: 3} + - {fileID: 21300000, guid: 46b5161c95402b546b31a22396e632f7, type: 3} + - {fileID: 21300000, guid: ed265137c45dceb4bae4f08ac0c3455e, type: 3} + - {fileID: 21300000, guid: a383699d71bcb4a4e9cf623692926176, type: 3} + - {fileID: 21300000, guid: 737fe7edd84ae164da6bdc6031493503, type: 3} + - {fileID: 21300000, guid: 7aaabe06485e83d40a2bd31ef9448722, type: 3} + - {fileID: 21300000, guid: 48fd6435f1c90384fa7e79514cf80888, type: 3} + - {fileID: 21300000, guid: 3bb71457e9820a2458b70f995dab641e, type: 3} + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0.83333333 + m_OrientationOffsetY: 0 + m_Level: 0 + m_CycleOffset: 0 + m_HasAdditiveReferencePose: 0 + m_LoopTime: 1 + m_LoopBlend: 0 + m_LoopBlendOrientation: 0 + m_LoopBlendPositionY: 0 + m_LoopBlendPositionXZ: 0 + m_KeepOriginalOrientation: 0 + m_KeepOriginalPositionY: 1 + m_KeepOriginalPositionXZ: 0 + m_HeightFromFeet: 0 + m_Mirror: 0 + m_EditorCurves: [] + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: [] diff --git "a/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\235\241\350\247\211.anim.meta" "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\235\241\350\247\211.anim.meta" new file mode 100644 index 00000000..38448bc8 --- /dev/null +++ "b/Assets/_Project/Animations/Pet/Pet_Devil_Interact_\347\235\241\350\247\211.anim.meta" @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a976212022ce4b658fa0814dfcfb1aed +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Scenes/Apartment/Apartment_Main.unity b/Assets/_Project/Scenes/Apartment/Apartment_Main.unity index 1ff8e494..bc2588f3 100644 --- a/Assets/_Project/Scenes/Apartment/Apartment_Main.unity +++ b/Assets/_Project/Scenes/Apartment/Apartment_Main.unity @@ -1,5 +1,3 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: --- !u!29 &1 OcclusionCullingSettings: m_ObjectHideFlags: 0 @@ -9332,6 +9330,8 @@ GameObject: - component: {fileID: 483894550} - component: {fileID: 483894547} - component: {fileID: 483894546} + - component: {fileID: 483894552} + - component: {fileID: 483894551} m_Layer: 0 m_Name: Pet_Angel m_TagString: Untagged @@ -9348,7 +9348,7 @@ Transform: m_GameObject: {fileID: 483894544} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 12.95, y: 0.41, z: 0} + m_LocalPosition: {x: 5.52, y: -1.51, z: 0} m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} m_ConstrainProportionsScale: 0 m_Children: @@ -9368,13 +9368,24 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: _config: {fileID: 0} - _personality: {fileID: 11400000, guid: 1ecede15733b42244a1305f7645463bd, type: 2} + _personality: {fileID: 0} _movementController: {fileID: 9100000, guid: ba46f117e79c2504888c585f53d1ecf8, type: 2} _sideFramesFaceLeft: 1 - _movementBounds: {fileID: 0} + _movementBounds: {fileID: 2102000002} _sortingAnchor: {fileID: 0} _sortingOrderOffset: 0 _petId: 0 + _interactionVisualStrategy: + _useDetachedVisualByDefault: 0 + _rules: + - _animatorStateName: Sleep + _useDetachedVisual: 1 + - _animatorStateName: Interact_Flower + _useDetachedVisual: 1 + - _animatorStateName: Interact_PlayingMusic + _useDetachedVisual: 1 + - _animatorStateName: Interact_Write + _useDetachedVisual: 1 --- !u!212 &483894547 SpriteRenderer: m_ObjectHideFlags: 0 @@ -9416,7 +9427,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 1000 - m_Sprite: {fileID: 21300000, guid: 74ef4f3a2a4302f4a88cb11ecd3891d1, type: 3} + m_Sprite: {fileID: 21300000, guid: d27e8a1d91de943479607e3c32a01287, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 m_FlipY: 0 @@ -9424,7 +9435,7 @@ SpriteRenderer: m_Size: {x: 10, y: 10} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 - m_WasSpriteAssigned: 0 + m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!114 &483894548 @@ -9443,7 +9454,7 @@ MonoBehaviour: _preferControlOnEnable: 0 _acceptWasd: 1 _acceptArrowKeys: 1 - _moveSpeed: 2.5 + _moveSpeed: 30 --- !u!114 &483894549 MonoBehaviour: m_ObjectHideFlags: 0 @@ -9461,13 +9472,18 @@ MonoBehaviour: _bindings: - _label: "\u95E8\u8FB9" _target: {fileID: 0} + _poseTarget: {fileID: 0} _fallbackTargetName: "\u4E2D\u592E\u5206\u9694\u9762" + _fallbackPoseTargetName: _useFallbackWorldPoint: 1 _fallbackWorldPoint: {x: 0, y: 0} _activationDistance: 2 _hideTargetWhileInteracting: 0 _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: _useTargetSortingWhileInteracting: 0 + _sortingOrderOffsetWhileInteracting: 0 _usePetPoseOverride: 0 _useTargetPositionForPetPose: 0 _petInteractionLocalOffset: {x: 0, y: 0} @@ -9483,52 +9499,100 @@ MonoBehaviour: _variantKey: beside door - _label: "\u76C6\u683D" _target: {fileID: 0} + _poseTarget: {fileID: 0} _fallbackTargetName: "\u5BB6\u5177_\u88C5\u9970_\u76C6\u683D_\u5929\u4F7F_02" + _fallbackPoseTargetName: _useFallbackWorldPoint: 1 - _fallbackWorldPoint: {x: 5.81, y: -6.07} - _activationDistance: 1.6 - _hideTargetWhileInteracting: 0 + _fallbackWorldPoint: {x: 6.75, y: -6.05} + _activationDistance: 2 + _hideTargetWhileInteracting: 1 _additionalHideTargets: [] - _useTargetSortingWhileInteracting: 0 - _usePetPoseOverride: 0 - _useTargetPositionForPetPose: 0 - _petInteractionLocalOffset: {x: 0, y: 0} + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: + _useTargetSortingWhileInteracting: 1 + _sortingOrderOffsetWhileInteracting: 0 + _usePetPoseOverride: 1 + _useTargetPositionForPetPose: 1 + _petInteractionLocalOffset: {x: 0.35, y: 1.8} _petInteractionWorldPoint: {x: 0, y: 0} - _petInteractionScale: {x: 1, y: 1, z: 1} + _petInteractionScale: {x: 0.5, y: 0.5, z: 1} _category: 4 _interactionType: 13 _animationVariant: 1 - _interactionDurationSeconds: 1.6 - _animationOptions: [] + _interactionDurationSeconds: 2.4 + _animationOptions: + - _label: "\u76C6\u683D_\u52A8\u753B" + _animatorStateName: Interact_Flower + _variantKey: flower - _label: "\u7AD6\u7434" _target: {fileID: 0} - _fallbackTargetName: "\u5BB6\u5177_\u7AD6\u7434_\u5929\u4F7F_\u573A\u666F\u5C42_01" + _poseTarget: {fileID: 0} + _fallbackTargetName: "\u5BB6\u5177_\u7AD6\u7434_\u5929\u4F7F_01" + _fallbackPoseTargetName: "\u5BB6\u5177_\u88C5\u9970_\u51F3\u5B50_\u5929\u4F7F_01" _useFallbackWorldPoint: 1 - _fallbackWorldPoint: {x: 13.87, y: -4.03} - _activationDistance: 1.8 - _hideTargetWhileInteracting: 0 + _fallbackWorldPoint: {x: 13.55, y: -4.54} + _activationDistance: 3 + _hideTargetWhileInteracting: 1 _additionalHideTargets: [] - _useTargetSortingWhileInteracting: 0 - _usePetPoseOverride: 0 - _useTargetPositionForPetPose: 0 - _petInteractionLocalOffset: {x: 0, y: 0} + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: "\u5BB6\u5177_\u88C5\u9970_\u51F3\u5B50_\u5929\u4F7F_01" + _useTargetSortingWhileInteracting: 1 + _sortingOrderOffsetWhileInteracting: 1 + _usePetPoseOverride: 1 + _useTargetPositionForPetPose: 1 + _petInteractionLocalOffset: {x: 0.75, y: 1.65} _petInteractionWorldPoint: {x: 0, y: 0} - _petInteractionScale: {x: 1, y: 1, z: 1} + _petInteractionScale: {x: 0.425, y: 0.425, z: 1} _category: 3 _interactionType: 9 _animationVariant: 2 - _interactionDurationSeconds: 2.2 - _animationOptions: [] + _interactionDurationSeconds: 2 + _animationOptions: + - _label: "\u7AD6\u7434_\u52A8\u753B" + _animatorStateName: Interact_PlayingMusic + _variantKey: playing music + - _label: "\u5199\u5B57" + _target: {fileID: 0} + _poseTarget: {fileID: 0} + _fallbackTargetName: "\u5BB6\u5177_\u5DE5\u4F5C\u684C_\u5706\u684C\u4E66\u5199_\u5929\u4F7F_01" + _fallbackPoseTargetName: + _useFallbackWorldPoint: 1 + _fallbackWorldPoint: {x: 5.24, y: 0.63} + _activationDistance: 2 + _hideTargetWhileInteracting: 1 + _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: + _useTargetSortingWhileInteracting: 1 + _sortingOrderOffsetWhileInteracting: 0 + _usePetPoseOverride: 1 + _useTargetPositionForPetPose: 1 + _petInteractionLocalOffset: {x: -0.17, y: 1.1} + _petInteractionWorldPoint: {x: 0, y: 0} + _petInteractionScale: {x: 0.5, y: 0.5, z: 1} + _category: 1 + _interactionType: 1 + _animationVariant: 3 + _interactionDurationSeconds: 6.9 + _animationOptions: + - _label: "\u5199\u5B57_\u52A8\u753B" + _animatorStateName: Interact_Write + _variantKey: write - _label: "\u4E66\u67DC" _target: {fileID: 0} + _poseTarget: {fileID: 0} _fallbackTargetName: "\u5BB6\u5177_\u88C5\u9970_\u4E66\u67DC_\u5929\u4F7F_01 (1)" + _fallbackPoseTargetName: _useFallbackWorldPoint: 1 _fallbackWorldPoint: {x: 2.376638, y: 3.4349914} _activationDistance: 1.8 _hideTargetWhileInteracting: 0 _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: _useTargetSortingWhileInteracting: 0 + _sortingOrderOffsetWhileInteracting: 0 _usePetPoseOverride: 0 _useTargetPositionForPetPose: 0 _petInteractionLocalOffset: {x: 0, y: 0} @@ -9540,19 +9604,24 @@ MonoBehaviour: _interactionDurationSeconds: 2.2 _animationOptions: [] - _label: "\u5929\u4F7F\u5E8A" - _target: {fileID: 748356469} - _fallbackTargetName: "\u5BB6\u5177_\u5E8A_\u5929\u4F7F\u5E8A_\u573A\u666F\u5C42_01" + _target: {fileID: 0} + _poseTarget: {fileID: 0} + _fallbackTargetName: "\u5BB6\u5177_\u5E8A_\u5929\u4F7F\u5E8A_01" + _fallbackPoseTargetName: _useFallbackWorldPoint: 1 _fallbackWorldPoint: {x: 14.2, y: 0.65} _activationDistance: 3.2 _hideTargetWhileInteracting: 1 _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: _useTargetSortingWhileInteracting: 1 + _sortingOrderOffsetWhileInteracting: 0 _usePetPoseOverride: 1 - _useTargetPositionForPetPose: 0 + _useTargetPositionForPetPose: 1 _petInteractionLocalOffset: {x: 0, y: 0} - _petInteractionWorldPoint: {x: 15.38, y: 1.51} - _petInteractionScale: {x: 0.48, y: 0.48, z: 1} + _petInteractionWorldPoint: {x: 0, y: 0} + _petInteractionScale: {x: 0.39, y: 0.39, z: 1} _category: 2 _interactionType: 5 _animationVariant: 4 @@ -9577,7 +9646,7 @@ MonoBehaviour: _bubbleDurationSeconds: 3 _bubbleLocalOffset: {x: 0, y: 2.8, z: 0} _bubbleCharacterSize: 0.14 - _bubbleFontSize: 44 + _bubbleFontSize: 37 _bubbleMinWidth: 3.6 _bubbleMaxWidth: 8.2 _bubbleMinHeight: 1.1 @@ -9604,6 +9673,68 @@ MonoBehaviour: - "\u5BB3\u7F9E" - "\u671F\u5F85" _clickReactionAnimations: [] +--- !u!50 &483894551 +Rigidbody2D: + serializedVersion: 4 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 483894544} + m_BodyType: 0 + m_Simulated: 1 + m_UseFullKinematicContacts: 0 + m_UseAutoMass: 0 + m_Mass: 1 + m_LinearDrag: 0 + m_AngularDrag: 0.05 + m_GravityScale: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_Interpolate: 0 + m_SleepingMode: 1 + m_CollisionDetection: 0 + m_Constraints: 0 +--- !u!70 &483894552 +CapsuleCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 483894544} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: -0.030552387, y: -3.1079504} + m_Size: {x: 1.6204271, y: 1.7951312} + m_Direction: 0 --- !u!1001 &490600893 PrefabInstance: m_ObjectHideFlags: 0 @@ -16281,6 +16412,364 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 925793353} m_CullTransparentMesh: 1 +--- !u!1 &910500001 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 910500002} + - component: {fileID: 910500005} + - component: {fileID: 910500006} + - component: {fileID: 910500007} + - component: {fileID: 910500004} + - component: {fileID: 910500003} + - component: {fileID: 910500009} + - component: {fileID: 910500008} + m_Layer: 0 + m_Name: Pet_Devil + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &910500002 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -9.05, y: -0.93, z: 0} + m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1549237633} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &910500003 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a313c8d962bc67d4594340dda94bec83, type: 3} + m_Name: + m_EditorClassIdentifier: + _config: {fileID: 0} + _personality: {fileID: 0} + _movementController: {fileID: 9100000, guid: 49dff8841cae4cc7ae3247d5c623213b, type: 2} + _sideFramesFaceLeft: 1 + _movementBounds: {fileID: 2102000012} + _sortingAnchor: {fileID: 0} + _sortingOrderOffset: 0 + _petId: 1 + _interactionVisualStrategy: + _useDetachedVisualByDefault: 0 + _rules: [] +--- !u!212 &910500004 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 1000 + m_Sprite: {fileID: 21300000, guid: d7459834ed41ce34d845c43da72af023, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 10, y: 10} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!114 &910500005 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0ef7ac582fd3496d8f8b77d28d8e6fa3, type: 3} + m_Name: + m_EditorClassIdentifier: + _enableInput: 1 + _preferControlOnEnable: 1 + _acceptWasd: 1 + _acceptArrowKeys: 1 + _moveSpeed: 30 +--- !u!114 &910500006 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2752e5847d124f0bb5d94220c6b6b3e3, type: 3} + m_Name: + m_EditorClassIdentifier: + _enableInteraction: 1 + _interactKey: 102 + _bindings: + - _label: "\u95E8\u8FB9" + _target: {fileID: 0} + _poseTarget: {fileID: 0} + _fallbackTargetName: "\u4E2D\u592E\u5206\u9694\u9762" + _fallbackPoseTargetName: + _useFallbackWorldPoint: 1 + _fallbackWorldPoint: {x: 0, y: 0} + _activationDistance: 5 + _hideTargetWhileInteracting: 0 + _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: + _useTargetSortingWhileInteracting: 0 + _sortingOrderOffsetWhileInteracting: 0 + _usePetPoseOverride: 0 + _useTargetPositionForPetPose: 0 + _petInteractionLocalOffset: {x: 0, y: 0} + _petInteractionWorldPoint: {x: 0, y: 0} + _petInteractionScale: {x: 1, y: 1, z: 1} + _category: 4 + _interactionType: 3 + _animationVariant: 5 + _interactionDurationSeconds: 1.5 + _animationOptions: + - _label: "\u95E8\u8FB9_\u52A8\u753B" + _animatorStateName: Interact_LookAround + _variantKey: look around + - _label: "\u73A9\u638C\u673A" + _target: {fileID: 1218279209} + _poseTarget: {fileID: 1004439067} + _fallbackTargetName: "\u5BB6\u5177_\u88C5\u9970_\u6C99\u53D1_\u6076\u9B54_02" + _fallbackPoseTargetName: "\u5BB6\u5177_\u88C5\u9970_\u6C99\u53D1_\u6076\u9B54_02" + _useFallbackWorldPoint: 1 + _fallbackWorldPoint: {x: -10.748915, y: 2.140191} + _activationDistance: 3 + _hideTargetWhileInteracting: 0 + _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: + _useTargetSortingWhileInteracting: 0 + _sortingOrderOffsetWhileInteracting: 0 + _usePetPoseOverride: 1 + _useTargetPositionForPetPose: 1 + _petInteractionLocalOffset: {x: 0, y: 0} + _petInteractionWorldPoint: {x: 0, y: 0} + _petInteractionScale: {x: 0.45, y: 0.45, z: 1} + _category: 4 + _interactionType: 19 + _animationVariant: 6 + _interactionDurationSeconds: 1.4 + _animationOptions: + - _label: "\u73A9\u638C\u673A_\u52A8\u753B" + _animatorStateName: Interact_PlayGame + _variantKey: play game + - _label: "\u753B\u753B" + _target: {fileID: 861896228} + _poseTarget: {fileID: 1435894323} + _fallbackTargetName: "\u5BB6\u5177_\u4F11\u95F2_\u753B\u67B6_\u6076\u9B54_01" + _fallbackPoseTargetName: "\u5BB6\u5177_\u88C5\u9970_\u6905\u5B50_\u6076\u9B54_01" + _useFallbackWorldPoint: 1 + _fallbackWorldPoint: {x: -4.79, y: 1.23} + _activationDistance: 2 + _hideTargetWhileInteracting: 0 + _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: "\u5BB6\u5177_\u88C5\u9970_\u6905\u5B50_\u6076\u9B54_01" + _useTargetSortingWhileInteracting: 1 + _sortingOrderOffsetWhileInteracting: 1 + _usePetPoseOverride: 1 + _useTargetPositionForPetPose: 1 + _petInteractionLocalOffset: {x: -1.5, y: 0} + _petInteractionWorldPoint: {x: 0, y: 0} + _petInteractionScale: {x: 0.4, y: 0.4, z: 1} + _category: 3 + _interactionType: 11 + _animationVariant: 7 + _interactionDurationSeconds: 1.5 + _animationOptions: + - _label: "\u753B\u753B_\u52A8\u753B" + _animatorStateName: Interact_Draw + _variantKey: draw + - _label: "\u5E8A" + _target: {fileID: 77329430} + _poseTarget: {fileID: 923403115} + _fallbackTargetName: "\u5BB6\u5177_\u5E8A_\u6076\u9B54\u5E8A_01 (1)" + _fallbackPoseTargetName: + _useFallbackWorldPoint: 1 + _fallbackWorldPoint: {x: -15.15, y: -4.77} + _activationDistance: 6 + _hideTargetWhileInteracting: 1 + _additionalHideTargets: [] + _sortingTarget: {fileID: 0} + _fallbackSortingTargetName: + _useTargetSortingWhileInteracting: 1 + _sortingOrderOffsetWhileInteracting: 0 + _usePetPoseOverride: 1 + _useTargetPositionForPetPose: 1 + _petInteractionLocalOffset: {x: 0, y: 0} + _petInteractionWorldPoint: {x: 0, y: 0} + _petInteractionScale: {x: 0.45, y: 0.45, z: 1} + _category: 2 + _interactionType: 5 + _animationVariant: 8 + _interactionDurationSeconds: 2.8 + _animationOptions: + - _label: "\u6076\u9B54\u5E8A_\u52A8\u753B" + _animatorStateName: Interact_DevilSleep + _variantKey: devil sleep +--- !u!114 &910500007 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 790cfaf3c6494183873730f5f64cc34d, type: 3} + m_Name: + m_EditorClassIdentifier: + _enableClickReaction: 1 + _bubbleDurationSeconds: 3 + _bubbleLocalOffset: {x: 0, y: 2.8, z: 0} + _bubbleCharacterSize: 0.14 + _bubbleFontSize: 37 + _bubbleMinWidth: 3.6 + _bubbleMaxWidth: 8.2 + _bubbleMinHeight: 1.1 + _bubbleLineHeight: 0.46 + _bubbleHorizontalPadding: 0.6 + _bubbleVerticalPadding: 0.4 + _bubbleOutlineThickness: 0.12 + _bubbleMaxCharactersPerLine: 9 + _responseCorpus: + - "\u6211\u5728\u8FD9\u91CC\u5462\uFF0C\u8981\u4E00\u8D77\u770B\u770B\u623F\u95F4\u5417\uFF1F" + - "\u4ECA\u5929\u7684\u98CE\u597D\u50CF\u5F88\u6E29\u67D4\uFF0C\u6211\u6709\u70B9\u5F00\u5FC3\u3002" + - "\u88AB\u4F60\u70B9\u5230\u5566\uFF0C\u6211\u4F1A\u8BA4\u771F\u542C\u4F60\u8BF4\u8BDD\u7684\u3002" + - "\u6211\u521A\u521A\u5728\u53D1\u5446\uFF0C\u4E0D\u8FC7\u73B0\u5728\u6CE8\u610F\u5230\u4F60\u4E86\u3002" + - "\u5982\u679C\u4F60\u613F\u610F\uFF0C\u6211\u53EF\u4EE5\u7EE7\u7EED\u966A\u4F60\u5728\u516C\u5BD3\u91CC\u901B\u901B\u3002" + - "\u6211\u73B0\u5728\u5FC3\u60C5\u8FD8\u4E0D\u9519\uFF0C\u60F3\u548C\u4F60\u591A\u5F85\u4E00\u4F1A\u513F\u3002" + - "\u4F60\u4E00\u78B0\u6211\uFF0C\u6211\u5C31\u4F1A\u89C9\u5F97\u4ECA\u5929\u6CA1\u6709\u90A3\u4E48\u65E0\u804A\u3002" + - "\u6211\u8FD8\u5728\u6162\u6162\u719F\u6089\u8FD9\u91CC\uFF0C\u4E0D\u8FC7\u6709\u4F60\u5728\u5C31\u5B89\u5FC3\u4E00\u70B9\u3002" + - "\u4F60\u60F3\u8BA9\u6211\u53BB\u54EA\u91CC\u770B\u770B\uFF1F\u6211\u53EF\u4EE5\u8DDF\u7740\u4F60\u8D70\u3002" + - "\u867D\u7136\u73B0\u5728\u8FD8\u4E0D\u4F1A\u771F\u6B63\u8BF4\u5F88\u591A\u8BDD\uFF0C\u4F46\u6211\u5DF2\u7ECF\u60F3\u56DE\u5E94\u4F60\u4E86\u3002" + _expressionLabels: + - "\u5F00\u5FC3" + - "\u597D\u5947" + - "\u653E\u677E" + - "\u5BB3\u7F9E" + - "\u671F\u5F85" + _clickReactionAnimations: [] +--- !u!50 &910500008 +Rigidbody2D: + serializedVersion: 4 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_BodyType: 0 + m_Simulated: 1 + m_UseFullKinematicContacts: 0 + m_UseAutoMass: 0 + m_Mass: 1 + m_LinearDrag: 0 + m_AngularDrag: 0.05 + m_GravityScale: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_Interpolate: 0 + m_SleepingMode: 1 + m_CollisionDetection: 0 + m_Constraints: 0 +--- !u!70 &910500009 +CapsuleCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 910500001} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: -0.030552387, y: -3.1079504} + m_Size: {x: 1.6204271, y: 1.7951312} + m_Direction: 0 --- !u!1 &926480495 GameObject: m_ObjectHideFlags: 0 @@ -35611,6 +36100,160 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &2102000000 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2102000001} + - component: {fileID: 2102000002} + m_Layer: 0 + m_Name: PetMovementBounds + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2102000001 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2102000000} + 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!61 &2102000002 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2102000000} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 1 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: 8.898991, y: -1.2467494} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0.5, y: 0.5} + oldSize: {x: 0, y: 0} + newSize: {x: 0, y: 0} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 16.350216, y: 12.013003} + m_EdgeRadius: 0 +--- !u!1 &2102000010 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2102000011} + - component: {fileID: 2102000012} + m_Layer: 0 + m_Name: PetMovementBounds_Devil + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2102000011 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2102000010} + 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!61 &2102000012 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2102000010} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 1 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: -8.9, y: -1.25} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0.5, y: 0.5} + oldSize: {x: 0, y: 0} + newSize: {x: 0, y: 0} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 16.35, y: 12.01} + m_EdgeRadius: 0 --- !u!1001 &2120036260 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/_Project/Scripts/Modules/Furniture/Furniture.cs b/Assets/_Project/Scripts/Modules/Furniture/Furniture.cs index f4193669..cd1c5af3 100644 --- a/Assets/_Project/Scripts/Modules/Furniture/Furniture.cs +++ b/Assets/_Project/Scripts/Modules/Furniture/Furniture.cs @@ -106,6 +106,14 @@ public void SetSceneFurniture(bool isSceneFurniture) private void EnsurePresentation() { + if (TryGetComponent(out SortingGroup sg) && sg != null + && TryGetComponent(out SpriteRenderer sr) && sr != null + && sg.sortingOrder == sr.sortingOrder + && sg.sortingOrder != 0) + { + sr.sortingOrder = 0; + } + bool preserveScenePresentation = ShouldPreserveScenePresentation(); if (_useDynamicSortingRule || preserveScenePresentation) { diff --git a/Assets/_Project/Scripts/Modules/Pet/PetController.cs b/Assets/_Project/Scripts/Modules/Pet/PetController.cs index b8b141ab..d578d1d8 100644 --- a/Assets/_Project/Scripts/Modules/Pet/PetController.cs +++ b/Assets/_Project/Scripts/Modules/Pet/PetController.cs @@ -22,7 +22,13 @@ public sealed class PetController : MonoBehaviour "家具_竖琴_天使_01", "家具_装饰_盆栽_天使_02", "家具_装饰_凳子_天使_01", - "家具_装饰_桌面雕塑左_天使_01" + "家具_装饰_桌面雕塑左_天使_01", + "家具_装饰_床头柜镜台_天使_01" + }; + + private static readonly HashSet AlwaysOnTopFurnitureDefinitionIds = new() + { + "家具_装饰_床头柜镜台_天使_01" }; private const string MoveFrontStateName = "Move_Front"; @@ -36,6 +42,12 @@ public sealed class PetController : MonoBehaviour private const string InteractFlowerStateName = "Interact_Flower"; private const string InteractPlayingMusicStateName = "Interact_PlayingMusic"; private const string InteractWriteStateName = "Interact_Write"; + private const string InteractLookAroundStateName = "Interact_LookAround"; + private const string InteractPlayGameStateName = "Interact_PlayGame"; + private const string InteractDrawStateName = "Interact_Draw"; + private const string InteractSleepStateName = "Interact_DevilSleep"; + private const string BaseLayerStatePrefix = "Base Layer."; + private const string DevilFTracePrefix = "[DEVIL_F_TRACE]"; private static readonly int IsMovingHash = Animator.StringToHash("IsMoving"); private static readonly int MoveXHash = Animator.StringToHash("MoveX"); @@ -53,6 +65,7 @@ public sealed class PetController : MonoBehaviour [SerializeField] private Transform? _sortingAnchor; [SerializeField] private int _sortingOrderOffset; [SerializeField] private PetId _petId = PetId.Angel; + [SerializeField] private PetInteractionVisualStrategy _interactionVisualStrategy = new(); public PetId PetId => _petId; @@ -78,6 +91,13 @@ public sealed class PetController : MonoBehaviour private bool _hasStoredInteractionPose; private Vector3 _storedInteractionPosition; private Vector3 _storedInteractionScale; + private bool _hasInteractionPoseRuntimeOverride; + private bool _hasInteractionPhysicsOverride; + private bool _storedInteractionRigidbodySimulated = true; + private bool _storedInteractionCapsuleColliderEnabled = true; + private const int DevilPoseTickTraceFrameInterval = 5; + private int _lastDevilPoseUpdateTraceFrame = -9999; + private int _lastDevilPoseFixedTraceFrame = -9999; private bool _hasStoredInteractionSorting; private int _storedInteractionSortingLayerId; private int _storedInteractionSortingOrder; @@ -169,7 +189,16 @@ private void Update() return; } - _context.RuntimeData.Position = GetCurrentWorldPosition(); + if (_hasInteractionPoseRuntimeOverride) + { + _context.RuntimeData.Position = ClampToMovementBounds(_context.RuntimeData.Position); + _context.RuntimeData.TargetPosition = _context.RuntimeData.Position; + } + else + { + _context.RuntimeData.Position = GetCurrentWorldPosition(); + } + RefreshLateBoundServices(_context); if (IsInactivePlayerPet()) { @@ -192,6 +221,7 @@ private void Update() _tickService.Tick(_context, Time.deltaTime); _stateMachine.Tick(Time.deltaTime); UpdateMovementAnimation(); + TraceDevilInteractionTickIfNeeded("Update", ref _lastDevilPoseUpdateTraceFrame); PublishSnapshotIfChanged(_context); } @@ -208,6 +238,7 @@ private void FixedUpdate() } _stateMachine?.FixedTick(Time.fixedDeltaTime); + TraceDevilInteractionTickIfNeeded("FixedUpdate", ref _lastDevilPoseFixedTraceFrame); } private void LateUpdate() @@ -245,11 +276,18 @@ private void UpdateDynamicSortingOrder() int resolvedSortingOrder = _defaultSortingOrder + _sortingOrderOffset; if (TryGetDynamicOcclusionFurniture(out GeminiLab.Modules.Furniture.Furniture? furniture)) { - float petAnchorY = ResolveSortingAnchorY(); int furnitureSortingOrder = furniture.CurrentSortingOrder; - resolvedSortingOrder = petAnchorY <= furniture.SortingAnchorY - ? furnitureSortingOrder + 1 - : furnitureSortingOrder - 1; + if (IsAlwaysOnTopFurniture(furniture)) + { + resolvedSortingOrder = furnitureSortingOrder + 1; + } + else + { + float petAnchorY = ResolveSortingAnchorY(); + resolvedSortingOrder = petAnchorY <= furniture.SortingAnchorY + ? furnitureSortingOrder + 1 + : furnitureSortingOrder - 1; + } } _spriteRenderer.sortingOrder = resolvedSortingOrder; @@ -319,9 +357,11 @@ private bool TryGetDynamicOcclusionFurniture(out GeminiLab.Modules.Furniture.Fur continue; } + bool isAlwaysOnTopFurniture = IsAlwaysOnTopFurniture(furniture); + bool overlapsHorizontally = - petBounds.max.x >= furnitureBounds.min.x - 0.2f && - petBounds.min.x <= furnitureBounds.max.x + 0.2f; + petBounds.max.x >= furnitureBounds.min.x - GetHorizontalCandidatePadding(isAlwaysOnTopFurniture) && + petBounds.min.x <= furnitureBounds.max.x + GetHorizontalCandidatePadding(isAlwaysOnTopFurniture); if (!overlapsHorizontally) { continue; @@ -329,15 +369,27 @@ private bool TryGetDynamicOcclusionFurniture(out GeminiLab.Modules.Furniture.Fur float furnitureAnchorY = furniture.SortingAnchorY; float verticalDistance = Mathf.Abs(petAnchorY - furnitureAnchorY); - float maxVerticalDistance = petBounds.extents.y + furnitureBounds.extents.y + 0.8f; + float maxVerticalDistance = petBounds.extents.y + furnitureBounds.extents.y + GetVerticalCandidatePadding(isAlwaysOnTopFurniture); if (verticalDistance > maxVerticalDistance) { continue; } - Vector2 closestPoint = furnitureBounds.ClosestPoint(petCenter); + Bounds scoringBounds = furnitureBounds; + if (isAlwaysOnTopFurniture) + { + // Keep small seat/table props competitive even when a nearby large bed or instrument also overlaps. + scoringBounds.Expand(new Vector3(0.8f, 0.8f, 0f)); + } + + Vector2 closestPoint = scoringBounds.ClosestPoint(petCenter); float distanceScore = Vector2.SqrMagnitude(petCenter - closestPoint); + if (isAlwaysOnTopFurniture) + { + distanceScore *= 0.0001f; + } + if (distanceScore < bestScore) { bestScore = distanceScore; @@ -375,6 +427,23 @@ private static bool ShouldUseDynamicOcclusionFurniture(GeminiLab.Modules.Furnitu DynamicOcclusionFurnitureDefinitionIds.Contains(definitionId); } + private static bool IsAlwaysOnTopFurniture(GeminiLab.Modules.Furniture.Furniture furniture) + { + string definitionId = furniture.DefinitionId; + return !string.IsNullOrWhiteSpace(definitionId) && + AlwaysOnTopFurnitureDefinitionIds.Contains(definitionId); + } + + private static float GetHorizontalCandidatePadding(bool isAlwaysOnTopFurniture) + { + return isAlwaysOnTopFurniture ? 0.9f : 0.2f; + } + + private static float GetVerticalCandidatePadding(bool isAlwaysOnTopFurniture) + { + return isAlwaysOnTopFurniture ? 1.4f : 0.8f; + } + private void TryAutoBindSortingAnchor() { if (_sortingAnchor != null) @@ -599,8 +668,27 @@ private void TickInactivePlayerControlled(PetContext context, float deltaTime) public bool TryStartPlayerInteraction(PetPlayerInteractionRequest request) { - if (_context is null || !IsPlayerControlled() || _context.RuntimeData.IsPlayerInteractionActive) + if (_context is null) + { + LogDevilFTraceWarning( + $"TryStartPlayerInteraction rejected: context null, target='{request.TargetName}', variant='{request.AnimationVariant}', state='{request.AnimatorStateNameOverride}'"); + Debug.LogWarning("[PetInteraction] TryStartPlayerInteraction failed: _context is null."); + return false; + } + + if (!IsPlayerControlled()) + { + LogDevilFTraceWarning( + $"TryStartPlayerInteraction rejected: not player controlled, target='{request.TargetName}', variant='{request.AnimationVariant}', state='{request.AnimatorStateNameOverride}'"); + Debug.LogWarning("[PetInteraction] TryStartPlayerInteraction failed: IsPlayerControlled is false."); + return false; + } + + if (_context.RuntimeData.IsPlayerInteractionActive) { + LogDevilFTraceWarning( + $"TryStartPlayerInteraction rejected: already interacting, target='{request.TargetName}', variant='{request.AnimationVariant}', state='{request.AnimatorStateNameOverride}'"); + Debug.LogWarning("[PetInteraction] TryStartPlayerInteraction failed: already interacting."); return false; } @@ -620,6 +708,9 @@ public bool TryStartPlayerInteraction(PetPlayerInteractionRequest request) ApplyInteractionSortingOverride(request); ApplyInteractionPoseOverride(request); ApplySpecialInteractionVisualOverride(request); + LogDevilFTrace( + $"TryStartPlayerInteraction accepted: target='{request.TargetName}', variant='{request.AnimationVariant}', " + + $"state='{request.AnimatorStateNameOverride}', duration={_context.RuntimeData.PlayerInteractionRemainingSeconds:F2}"); Debug.Log($"[PetInteraction] Triggered player interaction target='{request.TargetName}' variant='{request.AnimationVariant}'."); return true; } @@ -632,6 +723,7 @@ private bool TickPlayerInteraction(PetContext context, float deltaTime) } SetPlayerControlledState(context, InteractingState.StateName); + Debug.Log($"[PetInteraction] TickPlayerInteraction: state=Interacting, remainingSeconds={context.RuntimeData.PlayerInteractionRemainingSeconds:F2}, animState='{context.RuntimeData.PlayerInteractionAnimatorStateName}', variant='{context.RuntimeData.PlayerInteractionAnimationVariant}'"); context.Advance(deltaTime); _tickService?.Tick(context, deltaTime); context.RuntimeData.WorkRequested = false; @@ -771,12 +863,22 @@ private void HideInteractionRenderers(GameObject target) private void ApplySpecialInteractionVisualOverride(PetPlayerInteractionRequest request) { RestoreSleepInteractionVisual(); - if (!RequiresDetachedInteractionVisual(request.AnimationVariant) || - request.VisualHideTarget == null) + if (!UsesDetachedInteractionVisual(request)) { return; } + GameObject? poseTarget = request.VisualPoseTarget ?? request.VisualHideTarget; + if (poseTarget == null) + { + LogDevilFTrace( + $"PoseTrace branch='detached' skipped='poseTarget null' state='{ResolveInteractionAnimatorStateName(request)}' " + + $"localOffset={FormatVector2(request.PetInteractionLocalOffset)} worldPoint={FormatVector2(request.PetInteractionWorldPoint)}"); + return; + } + + GameObject sortingTarget = request.VisualSortingTarget ?? poseTarget; + EnsureSleepInteractionVisual(); if (_sleepInteractionVisualTransform == null || _sleepInteractionVisualAnimator == null || @@ -786,18 +888,25 @@ private void ApplySpecialInteractionVisualOverride(PetPlayerInteractionRequest r } Vector2 posePoint = request.UseTargetPositionForPetPose - ? ResolveInteractionPosePoint(request.VisualHideTarget.transform, request.PetInteractionLocalOffset) + ? ResolveInteractionPosePoint(poseTarget.transform, request.PetInteractionLocalOffset) : request.PetInteractionWorldPoint; + LogDevilFTrace( + $"PoseTrace branch='detached' state='{ResolveInteractionAnimatorStateName(request)}' " + + $"poseTarget='{DescribeObject(poseTarget)}' sortingTarget='{DescribeObject(sortingTarget)}' " + + $"positionSource='{(request.UseTargetPositionForPetPose ? "target+offset" : "worldPoint")}' " + + $"localOffset={FormatVector2(request.PetInteractionLocalOffset)} worldPoint={FormatVector2(request.PetInteractionWorldPoint)} " + + $"finalPosePoint={FormatVector2(posePoint)} scale={FormatVector3(request.PetInteractionScale)}"); + _sleepInteractionVisualTransform.position = new Vector3( posePoint.x, posePoint.y, transform.position.z); _sleepInteractionVisualTransform.localScale = request.PetInteractionScale; - ApplySleepInteractionVisualSorting(request.VisualHideTarget); + ApplySleepInteractionVisualSorting(sortingTarget, request.SortingOrderOffsetWhileInteracting); _sleepInteractionVisualSpriteRenderer.enabled = true; _sleepInteractionVisualAnimator.Play( - ResolvePlayerInteractionStateName(request.AnimationVariant), + ResolveInteractionAnimatorStateName(request), 0, 0f); @@ -863,26 +972,22 @@ private void EnsureSleepInteractionVisual() { _sleepInteractionVisualAnimator.runtimeAnimatorController = _movementController; } + + _sleepInteractionVisualAnimator.cullingMode = AnimatorCullingMode.AlwaysAnimate; } - private void ApplySleepInteractionVisualSorting(GameObject sortingTarget) + private void ApplySleepInteractionVisualSorting(GameObject sortingTarget, int sortingOrderOffset) { if (_sleepInteractionVisualSpriteRenderer == null) { return; } - if (sortingTarget.TryGetComponent(out SortingGroup sortingGroup)) + int resolvedOffset = sortingOrderOffset != 0 ? sortingOrderOffset : 1; + if (TryResolveSortingReference(sortingTarget, out int sortingLayerId, out int sortingOrder)) { - _sleepInteractionVisualSpriteRenderer.sortingLayerID = sortingGroup.sortingLayerID; - _sleepInteractionVisualSpriteRenderer.sortingOrder = sortingGroup.sortingOrder; - return; - } - - if (sortingTarget.TryGetComponent(out SpriteRenderer targetRenderer)) - { - _sleepInteractionVisualSpriteRenderer.sortingLayerID = targetRenderer.sortingLayerID; - _sleepInteractionVisualSpriteRenderer.sortingOrder = targetRenderer.sortingOrder; + _sleepInteractionVisualSpriteRenderer.sortingLayerID = sortingLayerId; + _sleepInteractionVisualSpriteRenderer.sortingOrder = sortingOrder + resolvedOffset; } } @@ -891,11 +996,15 @@ private void ApplyInteractionPoseOverride(PetPlayerInteractionRequest request) RestoreInteractionPose(); if (!request.UsePetPoseOverride) { + LogDevilFTrace( + $"PoseTrace branch='main' skipped='UsePetPoseOverride=false' state='{ResolveInteractionAnimatorStateName(request)}'"); return; } - if (RequiresDetachedInteractionVisual(request.AnimationVariant)) + if (UsesDetachedInteractionVisual(request)) { + LogDevilFTrace( + $"PoseTrace branch='main' skipped='detached visual branch' state='{ResolveInteractionAnimatorStateName(request)}'"); return; } @@ -903,9 +1012,25 @@ private void ApplyInteractionPoseOverride(PetPlayerInteractionRequest request) _storedInteractionPosition = GetCurrentWorldPosition(); _storedInteractionScale = transform.localScale; Vector2 posePoint = request.PetInteractionWorldPoint; - if (request.UseTargetPositionForPetPose && request.VisualHideTarget != null) + GameObject? poseTarget = request.VisualPoseTarget ?? request.VisualHideTarget; + if (request.UseTargetPositionForPetPose && poseTarget != null) { - posePoint = ResolveInteractionPosePoint(request.VisualHideTarget.transform, request.PetInteractionLocalOffset); + posePoint = ResolveInteractionPosePoint(poseTarget.transform, request.PetInteractionLocalOffset); + } + + posePoint = ClampToMovementBounds(posePoint); + LogDevilFTrace( + $"PoseTrace branch='main' state='{ResolveInteractionAnimatorStateName(request)}' " + + $"poseTarget='{DescribeObject(poseTarget)}' positionSource='{(request.UseTargetPositionForPetPose && poseTarget != null ? "target+offset" : "worldPoint")}' " + + $"localOffset={FormatVector2(request.PetInteractionLocalOffset)} worldPoint={FormatVector2(request.PetInteractionWorldPoint)} " + + $"finalPosePoint={FormatVector2(posePoint)} storedPosition={FormatVector2(_storedInteractionPosition)} " + + $"scale={FormatVector3(request.PetInteractionScale)}"); + ApplyInteractionPhysicsOverride(); + _hasInteractionPoseRuntimeOverride = true; + if (_context != null) + { + _context.RuntimeData.Position = posePoint; + _context.RuntimeData.TargetPosition = posePoint; } ApplyRuntimePosition(posePoint); @@ -933,12 +1058,23 @@ private void RestoreInteractionPose() { if (!_hasStoredInteractionPose) { + _hasInteractionPoseRuntimeOverride = false; + RestoreInteractionPhysicsOverride(); return; } - ApplyRuntimePosition(_storedInteractionPosition); + Vector2 restoredPosition = ClampToMovementBounds(_storedInteractionPosition); + if (_context != null) + { + _context.RuntimeData.Position = restoredPosition; + _context.RuntimeData.TargetPosition = restoredPosition; + } + + ApplyRuntimePosition(restoredPosition); transform.localScale = _storedInteractionScale; _hasStoredInteractionPose = false; + _hasInteractionPoseRuntimeOverride = false; + RestoreInteractionPhysicsOverride(); } private void ApplyInteractionSortingOverride(PetPlayerInteractionRequest request) @@ -953,17 +1089,13 @@ private void ApplyInteractionSortingOverride(PetPlayerInteractionRequest request _storedInteractionSortingLayerId = _spriteRenderer.sortingLayerID; _storedInteractionSortingOrder = _spriteRenderer.sortingOrder; - if (request.VisualSortingTarget.TryGetComponent(out SortingGroup sortingGroup)) + if (TryResolveSortingReference( + request.VisualSortingTarget, + out int sortingLayerId, + out int sortingOrder)) { - _spriteRenderer.sortingLayerID = sortingGroup.sortingLayerID; - _spriteRenderer.sortingOrder = sortingGroup.sortingOrder; - return; - } - - if (request.VisualSortingTarget.TryGetComponent(out SpriteRenderer targetRenderer)) - { - _spriteRenderer.sortingLayerID = targetRenderer.sortingLayerID; - _spriteRenderer.sortingOrder = targetRenderer.sortingOrder; + _spriteRenderer.sortingLayerID = sortingLayerId; + _spriteRenderer.sortingOrder = sortingOrder + request.SortingOrderOffsetWhileInteracting; } } @@ -1130,7 +1262,7 @@ private string ResolveInteractionStateName() return _context?.RuntimeData.TargetFurnitureInteractionType switch { - FurnitureInteractionType.PlayHarp => InteractReadStateName, + FurnitureInteractionType.PlayHarp => InteractPlayingMusicStateName, FurnitureInteractionType.PlayGuitar => InteractReadStateName, FurnitureInteractionType.PaintAtEasel => InteractReadStateName, FurnitureInteractionType.ViewPhotoBoard => InteractReadStateName, @@ -1165,20 +1297,63 @@ private static string ResolvePlayerInteractionStateName(string variant) "read" => InteractReadStateName, "write" => InteractWriteStateName, "sleep" => SleepStateName, + "look around" => InteractLookAroundStateName, + "play game" => InteractPlayGameStateName, + "draw" => InteractDrawStateName, + "devil sleep" => InteractSleepStateName, _ => MoveFrontStateName }; } - private static bool RequiresDetachedInteractionVisual(string variant) + private static string ResolveInteractionAnimatorStateName(PetPlayerInteractionRequest request) { - return variant switch + return !string.IsNullOrWhiteSpace(request.AnimatorStateNameOverride) + ? request.AnimatorStateNameOverride + : ResolvePlayerInteractionStateName(request.AnimationVariant); + } + + private bool UsesDetachedInteractionVisual(PetPlayerInteractionRequest request) + { + return _interactionVisualStrategy.UsesDetachedVisual( + ResolveInteractionAnimatorStateName(request), + _petId); + } + + private static bool TryResolveSortingReference(GameObject target, out int sortingLayerId, out int sortingOrder) + { + if (target.TryGetComponent(out SortingGroup directSortingGroup)) { - "sleep" => true, - "flower" => true, - "playing music" => true, - "write" => true, - _ => false - }; + sortingLayerId = directSortingGroup.sortingLayerID; + sortingOrder = directSortingGroup.sortingOrder; + return true; + } + + if (target.TryGetComponent(out SpriteRenderer directSpriteRenderer)) + { + sortingLayerId = directSpriteRenderer.sortingLayerID; + sortingOrder = directSpriteRenderer.sortingOrder; + return true; + } + + SortingGroup? childSortingGroup = target.GetComponentInChildren(true); + if (childSortingGroup != null) + { + sortingLayerId = childSortingGroup.sortingLayerID; + sortingOrder = childSortingGroup.sortingOrder; + return true; + } + + SpriteRenderer? childSpriteRenderer = target.GetComponentInChildren(true); + if (childSpriteRenderer != null) + { + sortingLayerId = childSpriteRenderer.sortingLayerID; + sortingOrder = childSpriteRenderer.sortingOrder; + return true; + } + + sortingLayerId = 0; + sortingOrder = 0; + return false; } private static string ResolveIdleStateName(Vector2 direction) @@ -1192,9 +1367,214 @@ private static string ResolveIdleStateName(Vector2 direction) }; } + private bool TryResolveAnimatorPlaybackStateName( + string requestedStateName, + out string resolvedStateName, + out string fallbackStateName) + { + fallbackStateName = requestedStateName.StartsWith( + BaseLayerStatePrefix, + System.StringComparison.Ordinal) + ? requestedStateName + : $"{BaseLayerStatePrefix}{requestedStateName}"; + + resolvedStateName = string.Empty; + if (_animator == null) + { + return false; + } + + if (_animator.HasState(0, Animator.StringToHash(requestedStateName))) + { + resolvedStateName = requestedStateName; + return true; + } + + if (!string.Equals( + fallbackStateName, + requestedStateName, + System.StringComparison.Ordinal) && + _animator.HasState(0, Animator.StringToHash(fallbackStateName))) + { + resolvedStateName = fallbackStateName; + return true; + } + + return false; + } + + private bool ShouldTraceDevilInteraction() + { + return _petId == PetId.Devil; + } + + private bool ShouldTraceDevilAnimatorState(string stateName) + { + return ShouldTraceDevilInteraction() && + ((_context?.RuntimeData.IsPlayerInteractionActive ?? false) || + stateName.StartsWith("Interact_", System.StringComparison.Ordinal)); + } + + private void LogDevilFTrace(string message) + { + if (!ShouldTraceDevilInteraction()) + { + return; + } + + Debug.Log($"{DevilFTracePrefix} {message}"); + } + + private void ApplyInteractionPhysicsOverride() + { + if (_hasInteractionPhysicsOverride) + { + return; + } + + _hasInteractionPhysicsOverride = true; + if (_rigidbody2D != null) + { + _storedInteractionRigidbodySimulated = _rigidbody2D.simulated; + _rigidbody2D.velocity = Vector2.zero; + _rigidbody2D.angularVelocity = 0f; + _rigidbody2D.simulated = false; + } + + if (_capsuleCollider2D != null) + { + _storedInteractionCapsuleColliderEnabled = _capsuleCollider2D.enabled; + _capsuleCollider2D.enabled = false; + } + + LogDevilFTrace( + $"InteractionPhysicsOverride enabled: rigidbodySimulated={_storedInteractionRigidbodySimulated} " + + $"capsuleEnabled={_storedInteractionCapsuleColliderEnabled}"); + } + + private void RestoreInteractionPhysicsOverride() + { + if (!_hasInteractionPhysicsOverride) + { + return; + } + + if (_capsuleCollider2D != null) + { + _capsuleCollider2D.enabled = _storedInteractionCapsuleColliderEnabled; + } + + if (_rigidbody2D != null) + { + _rigidbody2D.simulated = _storedInteractionRigidbodySimulated; + _rigidbody2D.velocity = Vector2.zero; + _rigidbody2D.angularVelocity = 0f; + } + + _hasInteractionPhysicsOverride = false; + LogDevilFTrace( + $"InteractionPhysicsOverride restored: rigidbodySimulated={_storedInteractionRigidbodySimulated} " + + $"capsuleEnabled={_storedInteractionCapsuleColliderEnabled}"); + } + + private void TraceDevilInteractionTickIfNeeded(string phase, ref int lastTraceFrame) + { + if (!ShouldTraceDevilInteraction() || + _context == null || + !_context.RuntimeData.IsPlayerInteractionActive) + { + return; + } + + int currentFrame = Time.frameCount; + if (currentFrame - lastTraceFrame < DevilPoseTickTraceFrameInterval) + { + return; + } + + lastTraceFrame = currentFrame; + TraceDevilInteractionTick(phase); + } + + private void TraceDevilInteractionTick(string phase) + { + if (_context == null || !ShouldTraceDevilInteraction()) + { + return; + } + + PetRuntimeData runtimeData = _context.RuntimeData; + string currentState = runtimeData.CurrentState; + string interactionState = runtimeData.PlayerInteractionAnimatorStateName; + string transformPosition = FormatVector3(transform.position); + string rigidbodyPosition = _rigidbody2D != null + ? FormatVector2(_rigidbody2D.position) + : "null"; + string worldPosition = FormatVector2(GetCurrentWorldPosition()); + string runtimePosition = FormatVector2(runtimeData.Position); + string targetPosition = FormatVector2(runtimeData.TargetPosition); + bool petSpriteVisible = _spriteRenderer != null && _spriteRenderer.enabled; + bool detachedVisible = _sleepInteractionVisualSpriteRenderer != null && + _sleepInteractionVisualSpriteRenderer.enabled; + string detachedPosition = _sleepInteractionVisualTransform != null + ? FormatVector3(_sleepInteractionVisualTransform.position) + : "null"; + bool detachedObjectActive = _sleepInteractionVisualObject != null && + _sleepInteractionVisualObject.activeInHierarchy; + bool detachedAnimatorEnabled = _sleepInteractionVisualAnimator != null && + _sleepInteractionVisualAnimator.enabled; + + LogDevilFTrace( + $"PoseTick phase='{phase}' frame={Time.frameCount} " + + $"state='{currentState}' interactionState='{interactionState}' " + + $"forcedState='{_lastForcedAnimatorStateName}' poseOverride={_hasInteractionPoseRuntimeOverride} " + + $"physicsOverride={_hasInteractionPhysicsOverride} " + + $"transform={transformPosition} rigidbody={rigidbodyPosition} world={worldPosition} " + + $"runtime={runtimePosition} target={targetPosition} " + + $"petSpriteVisible={petSpriteVisible} detachedVisible={detachedVisible} " + + $"detachedActive={detachedObjectActive} detachedAnimatorEnabled={detachedAnimatorEnabled} " + + $"detachedPosition={detachedPosition}"); + } + + private static string DescribeObject(GameObject? target) + { + return target != null ? target.name : "null"; + } + + private static string FormatVector2(Vector2 value) + { + return $"({value.x:F2}, {value.y:F2})"; + } + + private static string FormatVector3(Vector3 value) + { + return $"({value.x:F2}, {value.y:F2}, {value.z:F2})"; + } + + private void LogDevilFTraceWarning(string message) + { + if (!ShouldTraceDevilInteraction()) + { + return; + } + + Debug.LogWarning($"{DevilFTracePrefix} {message}"); + } + private void PlayForcedAnimatorState(string stateName) { - if (_animator == null || string.IsNullOrWhiteSpace(stateName)) + if (_animator == null) + { + if (ShouldTraceDevilAnimatorState(stateName)) + { + LogDevilFTraceWarning($"PlayForcedAnimatorState failed: _animator is null, state='{stateName}'"); + } + + Debug.LogWarning($"[PetAnimation] PlayForcedAnimatorState failed: _animator is null. stateName='{stateName}'"); + return; + } + + if (string.IsNullOrWhiteSpace(stateName)) { return; } @@ -1204,7 +1584,38 @@ private void PlayForcedAnimatorState(string stateName) return; } - _animator.Play(stateName, 0, 0f); + if (!TryResolveAnimatorPlaybackStateName( + stateName, + out string resolvedStateName, + out string fallbackStateName)) + { + string controllerName = _animator.runtimeAnimatorController != null + ? _animator.runtimeAnimatorController.name + : "null"; + if (ShouldTraceDevilAnimatorState(stateName)) + { + LogDevilFTraceWarning( + $"Animator state missing. requested='{stateName}', fallback='{fallbackStateName}', controller='{controllerName}'"); + } + + Debug.LogWarning( + $"[PetAnimation] Animator state missing on '{gameObject.name}'. " + + $"requested='{stateName}', fallback='{fallbackStateName}', controller='{controllerName}'"); + _lastForcedAnimatorStateName = stateName; + return; + } + + if (ShouldTraceDevilAnimatorState(stateName)) + { + LogDevilFTrace( + $"PlayForcedAnimatorState requested='{stateName}', resolved='{resolvedStateName}', " + + $"interactionActive={_context?.RuntimeData.IsPlayerInteractionActive == true}"); + } + + Debug.Log( + $"[PetAnimation] Playing animator state '{stateName}' on '{gameObject.name}' " + + $"(resolved='{resolvedStateName}')"); + _animator.Play(resolvedStateName, 0, 0f); _lastForcedAnimatorStateName = stateName; } @@ -1323,6 +1734,12 @@ private void EnsurePhysicsBinding() private void ApplyRuntimePosition(Vector2 position) { position = ClampToMovementBounds(position); + if (_hasInteractionPhysicsOverride) + { + ApplyDirectRuntimePosition(position); + return; + } + if (_rigidbody2D != null) { _rigidbody2D.MovePosition(position); @@ -1332,6 +1749,18 @@ private void ApplyRuntimePosition(Vector2 position) transform.position = new Vector3(position.x, position.y, transform.position.z); } + private void ApplyDirectRuntimePosition(Vector2 position) + { + Vector3 worldPosition = new(position.x, position.y, transform.position.z); + transform.position = worldPosition; + if (_rigidbody2D != null) + { + _rigidbody2D.position = position; + _rigidbody2D.velocity = Vector2.zero; + _rigidbody2D.angularVelocity = 0f; + } + } + private Vector2 GetCurrentWorldPosition() { if (_rigidbody2D != null) diff --git a/Assets/_Project/Scripts/Modules/Pet/PetInteractionVisualStrategy.cs b/Assets/_Project/Scripts/Modules/Pet/PetInteractionVisualStrategy.cs new file mode 100644 index 00000000..591c6f6d --- /dev/null +++ b/Assets/_Project/Scripts/Modules/Pet/PetInteractionVisualStrategy.cs @@ -0,0 +1,70 @@ +#nullable enable +using System; +using UnityEngine; + +namespace GeminiLab.Modules.Pet +{ + /// + /// Per-pet policy for choosing whether an interaction animation should be + /// shown on the main renderer or via a detached visual overlay. + /// + [Serializable] + public sealed class PetInteractionVisualStrategy + { + [Serializable] + private sealed class AnimatorStateRule + { + [SerializeField] private string _animatorStateName = string.Empty; + [SerializeField] private bool _useDetachedVisual = true; + + public string AnimatorStateName => _animatorStateName; + public bool UseDetachedVisual => _useDetachedVisual; + } + + [SerializeField] private bool _useDetachedVisualByDefault; + [SerializeField] private AnimatorStateRule[] _rules = Array.Empty(); + + public bool UsesDetachedVisual(string animatorStateName, PetId petId) + { + if (string.IsNullOrWhiteSpace(animatorStateName)) + { + return false; + } + + for (int i = 0; i < _rules.Length; i++) + { + AnimatorStateRule rule = _rules[i]; + if (!string.Equals(rule.AnimatorStateName, animatorStateName, StringComparison.Ordinal)) + { + continue; + } + + return rule.UseDetachedVisual; + } + + if (_rules.Length > 0 || _useDetachedVisualByDefault) + { + return _useDetachedVisualByDefault; + } + + return UsesPetDefaults(animatorStateName, petId); + } + + private static bool UsesPetDefaults(string animatorStateName, PetId petId) + { + if (petId != PetId.Angel) + { + return false; + } + + return animatorStateName switch + { + "Sleep" => true, + "Interact_Flower" => true, + "Interact_PlayingMusic" => true, + "Interact_Write" => true, + _ => false + }; + } + } +} diff --git a/Assets/_Project/Scripts/Modules/Pet/PetInteractionVisualStrategy.cs.meta b/Assets/_Project/Scripts/Modules/Pet/PetInteractionVisualStrategy.cs.meta new file mode 100644 index 00000000..bd2244b2 --- /dev/null +++ b/Assets/_Project/Scripts/Modules/Pet/PetInteractionVisualStrategy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26118272cefbb944cb9db82aa295e5af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_Project/Scripts/Modules/Pet/PetPlayerFurnitureInteractionController.cs b/Assets/_Project/Scripts/Modules/Pet/PetPlayerFurnitureInteractionController.cs index e406470e..1219afec 100644 --- a/Assets/_Project/Scripts/Modules/Pet/PetPlayerFurnitureInteractionController.cs +++ b/Assets/_Project/Scripts/Modules/Pet/PetPlayerFurnitureInteractionController.cs @@ -12,6 +12,8 @@ namespace GeminiLab.Modules.Pet [DisallowMultipleComponent] public sealed class PetPlayerFurnitureInteractionController : MonoBehaviour { + private const string DevilFTracePrefix = "[DEVIL_F_TRACE]"; + [Serializable] public sealed class InteractionAnimationOption { @@ -29,13 +31,18 @@ private sealed class InteractionBinding { [SerializeField] private string _label = string.Empty; [SerializeField] private GameObject? _target; + [SerializeField] private GameObject? _poseTarget; [SerializeField] private string _fallbackTargetName = string.Empty; + [SerializeField] private string _fallbackPoseTargetName = string.Empty; [SerializeField] private bool _useFallbackWorldPoint; [SerializeField] private Vector2 _fallbackWorldPoint; [SerializeField] private float _activationDistance = 1.5f; [SerializeField] private bool _hideTargetWhileInteracting; [SerializeField] private GameObject[] _additionalHideTargets = Array.Empty(); + [SerializeField] private GameObject? _sortingTarget; + [SerializeField] private string _fallbackSortingTargetName = string.Empty; [SerializeField] private bool _useTargetSortingWhileInteracting; + [SerializeField] private int _sortingOrderOffsetWhileInteracting; [SerializeField] private bool _usePetPoseOverride; [SerializeField] private bool _useTargetPositionForPetPose; [SerializeField] private Vector2 _petInteractionLocalOffset; @@ -49,13 +56,18 @@ private sealed class InteractionBinding public string Label => _label; public GameObject? Target => _target; + public GameObject? PoseTarget => _poseTarget; public string FallbackTargetName => _fallbackTargetName; + public string FallbackPoseTargetName => _fallbackPoseTargetName; public bool UseFallbackWorldPoint => _useFallbackWorldPoint; public Vector2 FallbackWorldPoint => _fallbackWorldPoint; public float ActivationDistance => Mathf.Max(0.1f, _activationDistance); public bool HideTargetWhileInteracting => _hideTargetWhileInteracting; public GameObject[] AdditionalHideTargets => _additionalHideTargets; + public GameObject? SortingTarget => _sortingTarget; + public string FallbackSortingTargetName => _fallbackSortingTargetName; public bool UseTargetSortingWhileInteracting => _useTargetSortingWhileInteracting; + public int SortingOrderOffsetWhileInteracting => _sortingOrderOffsetWhileInteracting; public bool UsePetPoseOverride => _usePetPoseOverride; public bool UseTargetPositionForPetPose => _useTargetPositionForPetPose; public Vector2 PetInteractionLocalOffset => _petInteractionLocalOffset; @@ -72,6 +84,16 @@ public void SetResolvedTarget(GameObject target) _target = target; } + public void SetResolvedPoseTarget(GameObject poseTarget) + { + _poseTarget = poseTarget; + } + + public void SetResolvedSortingTarget(GameObject sortingTarget) + { + _sortingTarget = sortingTarget; + } + public bool TryGetPreferredAnimation(out string animatorStateName, out string variantKey) { for (int i = 0; i < _animationOptions.Length; i++) @@ -98,6 +120,7 @@ public bool TryGetPreferredAnimation(out string animatorStateName, out string va [SerializeField] private KeyCode _interactKey = KeyCode.F; [SerializeField] private InteractionBinding[] _bindings = Array.Empty(); + private static int s_lastProcessedInteractFrame = -1; private PetController? _petController; private void Awake() @@ -112,115 +135,303 @@ private void Update() return; } + if (s_lastProcessedInteractFrame == Time.frameCount) + { + return; + } + + s_lastProcessedInteractFrame = Time.frameCount; + if (!TryHandleGlobalInteractKey(_interactKey)) + { + Debug.LogWarning($"[PetPlayerFurnitureInteraction] No eligible binding found for key '{_interactKey}' on frame {Time.frameCount}."); + } + } + + public bool TryHandleWorldPoint(Vector2 worldPoint) + { + if (!_enableInteraction || !isActiveAndEnabled) + { + return false; + } + if (_petController == null) { _petController = GetComponent(); } - if (_petController == null || !_petController.IsPlayerControlEnabled) + if (!TryGetBindingForWorldPoint(transform.position, worldPoint, out InteractionBinding? binding, out string targetName, out GameObject? targetObject)) + { + return false; + } + + return TryStartResolvedInteraction(binding, targetName, targetObject, "world point"); + } + + private bool TryGetClosestBinding(Vector2 petPosition, out InteractionBinding? bestBinding, out string bestTargetName, out GameObject? bestTargetObject) + { + return TryGetClosestBinding( + petPosition, + out bestBinding, + out bestTargetName, + out bestTargetObject, + out _); + } + + private bool TryGetClosestBinding( + Vector2 petPosition, + out InteractionBinding? bestBinding, + out string bestTargetName, + out GameObject? bestTargetObject, + out float bestBindingDistance) + { + bestBinding = null; + bestTargetName = string.Empty; + bestTargetObject = null; + bestBindingDistance = float.MaxValue; + + for (int i = 0; i < _bindings.Length; i++) + { + InteractionBinding binding = _bindings[i]; + if (!TryResolveInteractionPoint(binding, out Vector2 interactionPoint, out string targetName, out GameObject? targetObject)) + { + continue; + } + + float distance = Vector2.Distance(petPosition, interactionPoint); + if (distance > binding.ActivationDistance || distance >= bestBindingDistance) + { + continue; + } + + bestBindingDistance = distance; + bestBinding = binding; + bestTargetName = targetName; + bestTargetObject = targetObject; + } + + return bestBinding != null && !string.IsNullOrWhiteSpace(bestTargetName); + } + + private bool TryEnsurePetController(out PetController? petController) + { + if (_petController == null) + { + _petController = GetComponent(); + } + + petController = _petController; + return petController != null; + } + + private bool ShouldTraceDevilInteraction() + { + return TryEnsurePetController(out PetController? petController) && + petController.PetId == PetId.Devil; + } + + private void LogDevilTrace(string message) + { + if (!ShouldTraceDevilInteraction()) { return; } - if (!TryGetClosestBinding(transform.position, out InteractionBinding? binding, out string targetName, out GameObject? targetObject)) + Debug.Log($"{DevilFTracePrefix} {message}"); + } + + private void LogDevilTraceWarning(string message) + { + if (!ShouldTraceDevilInteraction()) { return; } - PetPlayerInteractionRequest request = new( - targetName: !string.IsNullOrWhiteSpace(binding.Label) ? binding.Label : targetName, - category: binding.Category, - interactionType: binding.InteractionType, - animationVariant: ResolveAnimationVariant(binding), - animatorStateNameOverride: ResolveAnimatorStateOverride(binding), - hideTargetWhileInteracting: binding.HideTargetWhileInteracting, - visualHideTarget: binding.HideTargetWhileInteracting ? targetObject : null, - additionalVisualHideTargets: binding.AdditionalHideTargets, - useTargetSortingWhileInteracting: binding.UseTargetSortingWhileInteracting, - visualSortingTarget: binding.UseTargetSortingWhileInteracting ? targetObject : null, - usePetPoseOverride: binding.UsePetPoseOverride, - useTargetPositionForPetPose: binding.UseTargetPositionForPetPose, - petInteractionLocalOffset: binding.PetInteractionLocalOffset, - petInteractionWorldPoint: binding.PetInteractionWorldPoint, - petInteractionScale: binding.PetInteractionScale, - interactionDurationSeconds: binding.InteractionDurationSeconds); + Debug.LogWarning($"{DevilFTracePrefix} {message}"); + } - Debug.Log($"[PetPlayerFurnitureInteraction] Selected binding label='{binding.Label}' target='{targetName}' variant='{request.AnimationVariant}' animatorState='{request.AnimatorStateNameOverride}'."); - _ = _petController.TryStartPlayerInteraction(request); + private bool IsPetCurrentlyControlled() + { + return TryEnsurePetController(out PetController? petController) && + petController.IsPlayerControlEnabled; } - public bool TryHandleWorldPoint(Vector2 worldPoint) + private bool TryPromoteToActiveController() { - if (!_enableInteraction || !isActiveAndEnabled) + if (!TryGetComponent(out PetPlayerInputController inputController)) { return false; } - if (_petController == null) + inputController.TakeControl(); + return inputController.IsActiveController; + } + + private bool TryStartResolvedInteraction( + InteractionBinding binding, + string targetName, + GameObject? targetObject, + string triggerSource) + { + if (!TryEnsurePetController(out PetController? petController)) { - _petController = GetComponent(); + Debug.LogWarning($"[PetPlayerFurnitureInteraction] Missing PetController on '{gameObject.name}' for {triggerSource} trigger."); + return false; } - if (_petController == null || !_petController.IsPlayerControlEnabled) + if (!petController.IsPlayerControlEnabled) { - return false; + if (!TryPromoteToActiveController() || !petController.IsPlayerControlEnabled) + { + LogDevilTraceWarning( + $"Failed to acquire active control. trigger='{triggerSource}', label='{binding.Label}', target='{targetName}'"); + Debug.LogWarning( + $"[PetPlayerFurnitureInteraction] '{gameObject.name}' could not acquire active control for {triggerSource} trigger."); + return false; + } + + LogDevilTrace( + $"Auto-took control. trigger='{triggerSource}', label='{binding.Label}', target='{targetName}'"); + Debug.Log($"[PetPlayerFurnitureInteraction] '{gameObject.name}' auto-took control for {triggerSource} trigger."); } - if (!TryGetBindingForWorldPoint(transform.position, worldPoint, out InteractionBinding? binding, out string targetName, out GameObject? targetObject)) + PetPlayerInteractionRequest request = BuildInteractionRequest(binding, targetName, targetObject); + Debug.Log( + $"[PetPlayerFurnitureInteraction] TriggerSource='{triggerSource}' label='{binding.Label}' target='{targetName}' " + + $"variant='{request.AnimationVariant}' animatorState='{request.AnimatorStateNameOverride}'."); + bool started = petController.TryStartPlayerInteraction(request); + LogDevilTrace( + $"TryStartResolvedInteraction trigger='{triggerSource}', label='{binding.Label}', target='{targetName}', " + + $"variant='{request.AnimationVariant}', animatorState='{request.AnimatorStateNameOverride}', started={started}"); + return started; + } + + private static bool TryHandleGlobalInteractKey(KeyCode interactKey) + { + if (!TrySelectInteractionCandidate( + interactKey, + out PetPlayerFurnitureInteractionController? controller, + out InteractionBinding? binding, + out string targetName, + out GameObject? targetObject, + out bool selectedFromActivePet)) { return false; } - PetPlayerInteractionRequest request = new( - targetName: !string.IsNullOrWhiteSpace(binding.Label) ? binding.Label : targetName, - category: binding.Category, - interactionType: binding.InteractionType, - animationVariant: ResolveAnimationVariant(binding), - animatorStateNameOverride: ResolveAnimatorStateOverride(binding), - hideTargetWhileInteracting: binding.HideTargetWhileInteracting, - visualHideTarget: binding.HideTargetWhileInteracting ? targetObject : null, - additionalVisualHideTargets: binding.AdditionalHideTargets, - useTargetSortingWhileInteracting: binding.UseTargetSortingWhileInteracting, - visualSortingTarget: binding.UseTargetSortingWhileInteracting ? targetObject : null, - usePetPoseOverride: binding.UsePetPoseOverride, - useTargetPositionForPetPose: binding.UseTargetPositionForPetPose, - petInteractionLocalOffset: binding.PetInteractionLocalOffset, - petInteractionWorldPoint: binding.PetInteractionWorldPoint, - petInteractionScale: binding.PetInteractionScale, - interactionDurationSeconds: binding.InteractionDurationSeconds); - - Debug.Log($"[PetPlayerFurnitureInteraction] Viewport binding label='{binding.Label}' target='{targetName}' variant='{request.AnimationVariant}' animatorState='{request.AnimatorStateNameOverride}'."); - return _petController.TryStartPlayerInteraction(request); + Debug.Log( + $"[PetPlayerFurnitureInteraction] Key '{interactKey}' selected pet '{controller.gameObject.name}' " + + $"via {(selectedFromActivePet ? "active" : "fallback")} candidate."); + controller.LogDevilTrace( + $"Selected by F key. label='{binding.Label}', target='{targetName}', " + + $"via={(selectedFromActivePet ? "active" : "fallback")}"); + return controller.TryStartResolvedInteraction(binding, targetName, targetObject, "F key"); } - private bool TryGetClosestBinding(Vector2 petPosition, out InteractionBinding? bestBinding, out string bestTargetName, out GameObject? bestTargetObject) + private static bool TrySelectInteractionCandidate( + KeyCode interactKey, + out PetPlayerFurnitureInteractionController? bestController, + out InteractionBinding? bestBinding, + out string bestTargetName, + out GameObject? bestTargetObject, + out bool selectedFromActivePet) { + bestController = null; bestBinding = null; bestTargetName = string.Empty; bestTargetObject = null; + selectedFromActivePet = false; float bestDistance = float.MaxValue; + bool foundActivePetCandidate = false; - for (int i = 0; i < _bindings.Length; i++) + PetPlayerFurnitureInteractionController[] controllers = + FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); + + for (int i = 0; i < controllers.Length; i++) { - InteractionBinding binding = _bindings[i]; - if (!TryResolveInteractionPoint(binding, out Vector2 interactionPoint, out string targetName, out GameObject? targetObject)) + PetPlayerFurnitureInteractionController controller = controllers[i]; + if (controller == null || + !controller.isActiveAndEnabled || + !controller._enableInteraction || + controller._interactKey != interactKey || + !controller.TryEnsurePetController(out _)) { continue; } - float distance = Vector2.Distance(petPosition, interactionPoint); - if (distance > binding.ActivationDistance || distance >= bestDistance) + if (!controller.TryGetClosestBinding( + controller.transform.position, + out InteractionBinding? binding, + out string targetName, + out GameObject? targetObject, + out float distance)) + { + continue; + } + + bool isActivePet = controller.IsPetCurrentlyControlled(); + if (isActivePet) + { + if (!foundActivePetCandidate || distance < bestDistance) + { + foundActivePetCandidate = true; + bestDistance = distance; + bestController = controller; + bestBinding = binding; + bestTargetName = targetName; + bestTargetObject = targetObject; + selectedFromActivePet = true; + } + + continue; + } + + if (foundActivePetCandidate || distance >= bestDistance) { continue; } bestDistance = distance; + bestController = controller; bestBinding = binding; bestTargetName = targetName; bestTargetObject = targetObject; + selectedFromActivePet = false; } - return bestBinding != null && !string.IsNullOrWhiteSpace(bestTargetName); + return bestController != null && + bestBinding != null && + !string.IsNullOrWhiteSpace(bestTargetName); + } + + private static PetPlayerInteractionRequest BuildInteractionRequest( + InteractionBinding binding, + string targetName, + GameObject? targetObject) + { + GameObject? poseTarget = ResolvePoseTarget(binding, targetObject); + GameObject? sortingTarget = binding.UseTargetSortingWhileInteracting + ? ResolveSortingTarget(binding, poseTarget ?? targetObject) + : null; + + return new PetPlayerInteractionRequest( + targetName: !string.IsNullOrWhiteSpace(binding.Label) ? binding.Label : targetName, + category: binding.Category, + interactionType: binding.InteractionType, + animationVariant: ResolveAnimationVariant(binding), + animatorStateNameOverride: ResolveAnimatorStateOverride(binding), + hideTargetWhileInteracting: binding.HideTargetWhileInteracting, + visualHideTarget: binding.HideTargetWhileInteracting ? targetObject : null, + visualPoseTarget: poseTarget, + additionalVisualHideTargets: binding.AdditionalHideTargets, + useTargetSortingWhileInteracting: binding.UseTargetSortingWhileInteracting, + visualSortingTarget: sortingTarget, + sortingOrderOffsetWhileInteracting: binding.SortingOrderOffsetWhileInteracting, + usePetPoseOverride: binding.UsePetPoseOverride, + useTargetPositionForPetPose: binding.UseTargetPositionForPetPose, + petInteractionLocalOffset: binding.PetInteractionLocalOffset, + petInteractionWorldPoint: binding.PetInteractionWorldPoint, + petInteractionScale: binding.PetInteractionScale, + interactionDurationSeconds: binding.InteractionDurationSeconds); } private bool TryGetBindingForWorldPoint( @@ -286,12 +497,40 @@ private static string ResolveAnimatorStateOverride(InteractionBinding binding) private static GameObject? ResolveTarget(InteractionBinding binding) { - if (binding.Target != null) + return ResolveSceneObject(binding.Target, binding.FallbackTargetName, binding.SetResolvedTarget); + } + + private static GameObject? ResolvePoseTarget(InteractionBinding binding, GameObject? defaultTargetObject) + { + GameObject? poseTarget = ResolveSceneObject( + binding.PoseTarget, + binding.FallbackPoseTargetName, + binding.SetResolvedPoseTarget); + + return poseTarget ?? defaultTargetObject; + } + + private static GameObject? ResolveSortingTarget(InteractionBinding binding, GameObject? defaultTargetObject) + { + GameObject? sortingTarget = ResolveSceneObject( + binding.SortingTarget, + binding.FallbackSortingTargetName, + binding.SetResolvedSortingTarget); + + return sortingTarget ?? defaultTargetObject; + } + + private static GameObject? ResolveSceneObject( + GameObject? directTarget, + string fallbackTargetName, + Action? cacheResolvedTarget) + { + if (directTarget != null) { - return binding.Target; + return directTarget; } - if (string.IsNullOrWhiteSpace(binding.FallbackTargetName)) + if (string.IsNullOrWhiteSpace(fallbackTargetName)) { return null; } @@ -301,23 +540,23 @@ private static string ResolveAnimatorStateOverride(InteractionBinding binding) { GameObject candidate = sceneObjects[i]; if (candidate.TryGetComponent(out SceneFurnitureDefinitionHint hint) && - string.Equals(hint.DefinitionId, binding.FallbackTargetName, StringComparison.Ordinal)) + string.Equals(hint.DefinitionId, fallbackTargetName, StringComparison.Ordinal)) { - binding.SetResolvedTarget(candidate); + cacheResolvedTarget?.Invoke(candidate); return candidate; } if (candidate.TryGetComponent(out SpriteRenderer renderer) && renderer.sprite != null && - string.Equals(renderer.sprite.name, binding.FallbackTargetName, StringComparison.Ordinal)) + string.Equals(renderer.sprite.name, fallbackTargetName, StringComparison.Ordinal)) { - binding.SetResolvedTarget(candidate); + cacheResolvedTarget?.Invoke(candidate); return candidate; } - if (string.Equals(candidate.name, binding.FallbackTargetName, StringComparison.Ordinal)) + if (string.Equals(candidate.name, fallbackTargetName, StringComparison.Ordinal)) { - binding.SetResolvedTarget(candidate); + cacheResolvedTarget?.Invoke(candidate); return candidate; } } @@ -326,23 +565,23 @@ private static string ResolveAnimatorStateOverride(InteractionBinding binding) { GameObject candidate = sceneObjects[i]; if (candidate.TryGetComponent(out SceneFurnitureDefinitionHint hint) && - hint.DefinitionId.Contains(binding.FallbackTargetName, StringComparison.Ordinal)) + hint.DefinitionId.Contains(fallbackTargetName, StringComparison.Ordinal)) { - binding.SetResolvedTarget(candidate); + cacheResolvedTarget?.Invoke(candidate); return candidate; } if (candidate.TryGetComponent(out SpriteRenderer renderer) && renderer.sprite != null && - renderer.sprite.name.Contains(binding.FallbackTargetName, StringComparison.Ordinal)) + renderer.sprite.name.Contains(fallbackTargetName, StringComparison.Ordinal)) { - binding.SetResolvedTarget(candidate); + cacheResolvedTarget?.Invoke(candidate); return candidate; } - if (candidate.name.Contains(binding.FallbackTargetName, StringComparison.Ordinal)) + if (candidate.name.Contains(fallbackTargetName, StringComparison.Ordinal)) { - binding.SetResolvedTarget(candidate); + cacheResolvedTarget?.Invoke(candidate); return candidate; } } @@ -417,9 +656,11 @@ public PetPlayerInteractionRequest( string animatorStateNameOverride, bool hideTargetWhileInteracting, GameObject? visualHideTarget, + GameObject? visualPoseTarget, GameObject[]? additionalVisualHideTargets, bool useTargetSortingWhileInteracting, GameObject? visualSortingTarget, + int sortingOrderOffsetWhileInteracting, bool usePetPoseOverride, bool useTargetPositionForPetPose, Vector2 petInteractionLocalOffset, @@ -434,9 +675,11 @@ public PetPlayerInteractionRequest( AnimatorStateNameOverride = animatorStateNameOverride; HideTargetWhileInteracting = hideTargetWhileInteracting; VisualHideTarget = visualHideTarget; + VisualPoseTarget = visualPoseTarget; AdditionalVisualHideTargets = additionalVisualHideTargets ?? Array.Empty(); UseTargetSortingWhileInteracting = useTargetSortingWhileInteracting; VisualSortingTarget = visualSortingTarget; + SortingOrderOffsetWhileInteracting = sortingOrderOffsetWhileInteracting; UsePetPoseOverride = usePetPoseOverride; UseTargetPositionForPetPose = useTargetPositionForPetPose; PetInteractionLocalOffset = petInteractionLocalOffset; @@ -452,9 +695,11 @@ public PetPlayerInteractionRequest( public string AnimatorStateNameOverride { get; } public bool HideTargetWhileInteracting { get; } public GameObject? VisualHideTarget { get; } + public GameObject? VisualPoseTarget { get; } public GameObject[] AdditionalVisualHideTargets { get; } public bool UseTargetSortingWhileInteracting { get; } public GameObject? VisualSortingTarget { get; } + public int SortingOrderOffsetWhileInteracting { get; } public bool UsePetPoseOverride { get; } public bool UseTargetPositionForPetPose { get; } public Vector2 PetInteractionLocalOffset { get; } @@ -469,7 +714,11 @@ public enum PetSelfInteractionVariant Flower = 1, PlayingMusic = 2, Read = 3, - Sleep = 4 + Sleep = 4, + LookAround = 5, + PlayGame = 6, + Draw = 7, + DevilSleep = 8 } public static class PetSelfInteractionVariantExtensions @@ -483,6 +732,10 @@ public static string ToVariantKey(this PetSelfInteractionVariant variant) PetSelfInteractionVariant.PlayingMusic => "playing music", PetSelfInteractionVariant.Read => "read", PetSelfInteractionVariant.Sleep => "sleep", + PetSelfInteractionVariant.LookAround => "look around", + PetSelfInteractionVariant.PlayGame => "play game", + PetSelfInteractionVariant.Draw => "draw", + PetSelfInteractionVariant.DevilSleep => "devil sleep", _ => "read" }; } diff --git a/Assets/_Project/Scripts/Modules/Pet/PetPlayerInputController.cs b/Assets/_Project/Scripts/Modules/Pet/PetPlayerInputController.cs index 15f3fa1c..c0820397 100644 --- a/Assets/_Project/Scripts/Modules/Pet/PetPlayerInputController.cs +++ b/Assets/_Project/Scripts/Modules/Pet/PetPlayerInputController.cs @@ -36,11 +36,13 @@ public void TakeControl() private void Awake() { TryBecomeActiveController(); + Debug.Log($"[PetInput] Awake on '{gameObject.name}' — IsActiveController={IsActiveController}"); } private void OnEnable() { TryBecomeActiveController(); + Debug.Log($"[PetInput] OnEnable on '{gameObject.name}' — IsActiveController={IsActiveController}, _preferControlOnEnable={_preferControlOnEnable}"); } private void OnDisable()