fix:初始化完成水晶雕像事件

This commit is contained in:
bzx
2026-03-04 16:21:00 +08:00
parent 31af18b4cf
commit 628a26508d
17 changed files with 2469 additions and 22 deletions

View File

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

View File

@ -0,0 +1,133 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-4156996225838610488
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 7
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: CrystalStatue
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap:
RenderType: Opaque
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AlphaClip: 0
- _AlphaToMask: 0
- _Blend: 0
- _BlendModePreserveSpecular: 1
- _BumpScale: 1
- _ClearCoatMask: 0
- _ClearCoatSmoothness: 0
- _Cull: 2
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _DstBlendAlpha: 0
- _EnvironmentReflections: 1
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- _Metallic: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- _Smoothness: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- _Surface: 0
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.990566, g: 0.08877712, b: 0.08877712, a: 1}
- _Color: {r: 0.99056596, g: 0.08877709, b: 0.08877709, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 20cdca2f46819714eb7ed0d7375541e8
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,503 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1059430200520042469
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5663746604466341845}
- component: {fileID: 8752757083727930548}
- component: {fileID: 1091387597045655842}
- component: {fileID: 845784839703467923}
m_Layer: 15
m_Name: heartObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &5663746604466341845
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059430200520042469}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.056, z: 0.012}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2737516825362835335}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8752757083727930548
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059430200520042469}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &1091387597045655842
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059430200520042469}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 20cdca2f46819714eb7ed0d7375541e8, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &845784839703467923
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1059430200520042469}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &2540964182298530316
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6235050325980211988}
- component: {fileID: 2687190014144004803}
- component: {fileID: 8188994267566669965}
- component: {fileID: 4698439308578055831}
m_Layer: 15
m_Name: handsObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &6235050325980211988
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2540964182298530316}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.012, z: 0.66}
m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}
m_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 2737516825362835335}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &2687190014144004803
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2540964182298530316}
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &8188994267566669965
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2540964182298530316}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 20cdca2f46819714eb7ed0d7375541e8, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &4698439308578055831
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2540964182298530316}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 2
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &4272406639046486525
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2737516825362835335}
- component: {fileID: 1789408179601768100}
m_Layer: 15
m_Name: CrystalStatue
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2737516825362835335
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4272406639046486525}
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:
- {fileID: 8900612429900914770}
- {fileID: 5663746604466341845}
- {fileID: 6235050325980211988}
- {fileID: 7004877221294803687}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1789408179601768100
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4272406639046486525}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 82ad8b365d4388b4ea81677c4eb1e3f6, type: 3}
m_Name:
m_EditorClassIdentifier:
statueType: 0
isTarget: 0
maxHealth: 3
statueRenderer: {fileID: 0}
crackMaterials: []
crackDecals: []
hitParticle: {fileID: 0}
breakParticle: {fileID: 0}
evilLaughParticle: {fileID: 0}
hitSound: 2.1
crackSound: 2.1
breakSound: 2.2
evilLaughSound: 2.3
animator: {fileID: 0}
hitAnimTrigger: Hit
breakAnimTrigger: Break
evilLaughAnimTrigger: EvilLaugh
heartObject: {fileID: 1059430200520042469}
handsObject: {fileID: 2540964182298530316}
specialEffect: {fileID: 0}
evilFaceObject: {fileID: 9167557534403199529}
breakDuration: 1
disappearDelay: 0.5
hitShakeDuration: 0.2
hitShakeStrength: 0.1
hitShakeVibrato: 10
hitShakeRandomness: 90
debugMode: 1
currentState: 0
--- !u!1 &9082512224767497446
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8900612429900914770}
- component: {fileID: 6126963059790932434}
- component: {fileID: 832597213532025554}
- component: {fileID: 5667052577272693684}
m_Layer: 15
m_Name: Cylinder
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8900612429900914770
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9082512224767497446}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2737516825362835335}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6126963059790932434
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9082512224767497446}
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &832597213532025554
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9082512224767497446}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 6c6f906bc8411ce4c9267853d7249fd3, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &5667052577272693684
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9082512224767497446}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 2
m_Radius: 0.5000001
m_Height: 2
m_Direction: 1
m_Center: {x: 0.000000059604645, y: 0, z: -0.00000008940697}
--- !u!1 &9167557534403199529
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7004877221294803687}
- component: {fileID: 1451182223167190124}
- component: {fileID: 5174011180359395949}
- component: {fileID: 7784027459399412931}
m_Layer: 15
m_Name: specialEffect
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7004877221294803687
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9167557534403199529}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.92, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2737516825362835335}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &1451182223167190124
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9167557534403199529}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &5174011180359395949
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9167557534403199529}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 20cdca2f46819714eb7ed0d7375541e8, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!135 &7784027459399412931
SphereCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9167557534403199529}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Radius: 0.5
m_Center: {x: 0, y: 0, z: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 79b5cfc4163592f43b0aac7c754b28c8
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -749,6 +749,7 @@ Transform:
- {fileID: 884666539354129915}
- {fileID: 580352712544404546}
- {fileID: 6053918926551127477}
- {fileID: 4978581575116740428}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8553229327014928926
@ -835,20 +836,123 @@ MonoBehaviour:
m_Bits: 98304
ray: {fileID: 580352712544404546}
hand: {fileID: 884666539354129916}
gems:
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
gemKeyHand: {fileID: 0}
gemKey: {fileID: 0}
gemKeyUp: {fileID: 0}
skillet: {fileID: 1971246387353709640}
skilletEx: {fileID: 0}
hit: {fileID: 0}
isTrigger: 0
triggerDis: 0
_isOpenLine: 0
puzzleId: 0
hitDistance: 1.5
hitRadius: 0.3
statueLayerMask:
serializedVersion: 2
m_Bits: 32768
normalHandObject: {fileID: 884666539354129916}
statueEventHandObject: {fileID: 6123848407032184956}
--- !u!1 &6123848407032184956
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4978581575116740428}
- component: {fileID: 2906143449434614343}
- component: {fileID: 2253440362802080129}
- component: {fileID: 1590215701971723926}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4978581575116740428
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6123848407032184956}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0.016, y: -0.0029610237, z: 0.007}
m_LocalScale: {x: 0.07, y: 0.07, z: 0.07}
m_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 6272334842578027103}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &2906143449434614343
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6123848407032184956}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &2253440362802080129
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6123848407032184956}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 6c6f906bc8411ce4c9267853d7249fd3, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &1590215701971723926
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6123848407032184956}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1001 &2684983532821258424
PrefabInstance:
m_ObjectHideFlags: 0

View File

@ -3836,7 +3836,7 @@ AudioSource:
m_Enabled: 1
serializedVersion: 4
OutputAudioMixerGroup: {fileID: 0}
m_audioClip: {fileID: 8300000, guid: 470ea6fb0446ee14badbead997d7e86e, type: 3}
m_audioClip: {fileID: 8300000, guid: b85095ef54cca454faae86e7816528ac, type: 3}
m_PlayOnAwake: 1
m_Volume: 1
m_Pitch: 1
@ -6150,6 +6150,7 @@ MonoBehaviour:
mirrorFlyDuration: 2
mirrorTransformDuration: 2
currentState: 0
nextCrystalStatueEvent: {fileID: 0}
--- !u!1 &627150162
GameObject:
m_ObjectHideFlags: 0
@ -9364,7 +9365,7 @@ Transform:
m_GameObject: {fileID: 928594066}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: -0.10000038, y: 1, z: 1.8499999}
m_LocalPosition: {x: 0, y: 1, z: 4.5}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@ -9678,7 +9679,7 @@ MonoBehaviour:
soundPlayedEventActive: 0
soundPlayedCustomEvent:
willCleanUpDelegatesAfterStop: 1
frames: 178
frames: 194
--- !u!1 &960137468
GameObject:
m_ObjectHideFlags: 0
@ -12698,12 +12699,79 @@ Transform:
m_GameObject: {fileID: 1152711577}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0.12, y: 0, z: 4.48}
m_LocalPosition: {x: 0.11, y: 0, z: 0.42}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 964738810}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1188798798
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1188798799}
- component: {fileID: 1188798800}
m_Layer: 0
m_Name: CrystalStatueEvent
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1188798799
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1188798798}
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: 1689605413}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1188798800
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1188798798}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8c1960c3bab2ab94d8e778ec1930a8cc, type: 3}
m_Name:
m_EditorClassIdentifier:
debugMode: 1
autoStart: 0
autoStartDelay: 1
crystalStatuePrefab: {fileID: 4272406639046486525, guid: 79b5cfc4163592f43b0aac7c754b28c8,
type: 3}
statueCount: 5
statueRadius: 3
statueHeight: 0
roundTimeLimit: 90
delayBetweenRounds: 3
audioRound1Intro: 1.5
audioRound1Success: 1.7
audioRound2Intro: 1.8
audioRound2Success: 1.9
audioRound3Intro: 1.10
audioRound3Success: 1.11
audioFail: 1.6
audioCrystalBreak: 2.1
audioSuccessEffect: 2.2
audioEvilLaugh: 2.3
crystalWorldEnvironment: {fileID: 1597025901}
currentState: 0
currentRound: 0
--- !u!1 &1200029317
GameObject:
m_ObjectHideFlags: 0
@ -15647,6 +15715,37 @@ MonoBehaviour:
soundPlayedCustomEvent:
willCleanUpDelegatesAfterStop: 1
frames: 178
--- !u!1 &1597025901
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1597025902}
m_Layer: 0
m_Name: crystalWorldEnvironment
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1597025902
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1597025901}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.33524713, y: -0.7949321, z: 0.44805232}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1601810288
GameObject:
m_ObjectHideFlags: 0
@ -16616,6 +16715,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 613688039}
- {fileID: 1188798799}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1706367014
@ -19470,6 +19570,37 @@ MeshFilter:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1952656331}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &1953097132
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1953097133}
m_Layer: 0
m_Name: BGMManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1953097133
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1953097132}
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: 2085135536}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1954948869
GameObject:
m_ObjectHideFlags: 0
@ -20421,6 +20552,7 @@ Transform:
m_Children:
- {fileID: 6399154517215508142}
- {fileID: 1830913920}
- {fileID: 1953097133}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2090396556
@ -20966,6 +21098,7 @@ MonoBehaviour:
type: 3}
witchPre: {fileID: 8758678282085574788, guid: f6ef5b8326d73de4ba8d829cb9e5341b,
type: 3}
crystalStatuePre: {fileID: 0}
playerRightHand: {fileID: 0}
enemy: {fileID: 0}
isStartGame: 0
@ -20975,6 +21108,7 @@ MonoBehaviour:
type: 3}
cutscenes:
- {fileID: 613688040}
- {fileID: 1188798800}
--- !u!4 &6399154517215508142
Transform:
m_ObjectHideFlags: 0
@ -21017,3 +21151,4 @@ SceneRoots:
- {fileID: 964738810}
- {fileID: 1449050322}
- {fileID: 1689605413}
- {fileID: 1597025902}

View File

@ -51,6 +51,7 @@ public class GameManager : MonoBehaviour
public GameObject gameStartDoor;
public GameObject mirrorPre;
public GameObject witchPre;
public GameObject crystalStatuePre; // 水晶雕像预制体
public RightHand playerRightHand;
public Enemy enemy;
@ -102,7 +103,12 @@ public class GameManager : MonoBehaviour
//CreateAICharacter();
//CleanupGuideArrow();
//CreateEnemy(GameLocal.Ins.enemyPos.position,GameLocal.Ins.enemyPos.eulerAngles);
cutscenes[0].StartCutscene();
StartCutscene(0);
}
public void StartCutscene(int id)
{
cutscenes[id].StartCutscene();
}
//修改处添加创建AI角色的方法
@ -163,10 +169,8 @@ public class GameManager : MonoBehaviour
public void LoginGame()
{
CreatePlayer();
//PlaySound2DRPC("1.25");
PlayBGM(0);
CreateGameStartDoor(GameLocal.Ins.startDoorPos.position);
//InitializeGuideArrow();
}
public void PlayBGM(int id)

View File

@ -0,0 +1,538 @@
using UnityEngine;
using DarkTonic.MasterAudio;
using DG.Tweening;
using System;
/// <summary>
/// 水晶雕像控制器 - 单个雕像的控制逻辑
/// 包含血量、裂痕效果、击打反馈等功能
/// </summary>
public class CrystalStatue : MonoBehaviour
{
#region
[Header("雕像类型")]
public StatueType statueType;
public bool isTarget; // 是否是目标雕像
[Header("血量配置")]
public int maxHealth = 3;
private int currentHealth;
[Header("裂痕效果")]
public Renderer statueRenderer;
public Material[] crackMaterials; // 0=正常, 1=裂痕1, 2=裂痕2, 3=碎裂前
public GameObject[] crackDecals; // 裂痕贴花对象
[Header("特效")]
public ParticleSystem hitParticle; // 击打粒子效果
public ParticleSystem breakParticle; // 碎裂粒子效果
public ParticleSystem evilLaughParticle; // 狞笑粒子效果(失败时)
[Header("音效")]
public string hitSound = "2.1"; // 击打音效
public string crackSound = "2.1"; // 裂痕音效
public string breakSound = "2.2"; // 碎裂音效
public string evilLaughSound = "2.3"; // 狞笑音效
[Header("动画")]
public Animator animator;
public string hitAnimTrigger = "Hit";
public string breakAnimTrigger = "Break";
public string evilLaughAnimTrigger = "EvilLaugh";
[Header("视觉效果")]
public GameObject heartObject; // 心脏显示对象(第三轮用)
public GameObject handsObject; // 双手显示对象(第二轮用)
public ParticleSystem specialEffect; // 特殊效果(心脏跳动/手部特效)
[Header("表情区分(第一轮用)")]
public GameObject evilFaceObject; // 邪恶表情对象
[Header("碎裂配置")]
public float breakDuration = 1f;
public float disappearDelay = 0.5f;
[Header("震动配置")]
public float hitShakeDuration = 0.2f; // 击打震动持续时间
public float hitShakeStrength = 0.1f; // 击打震动强度
public int hitShakeVibrato = 10; // 震动频率
public float hitShakeRandomness = 90f; // 震动随机性
[Header("调试")]
public bool debugMode = true;
#endregion
#region
public enum StatueType
{
Normal, // 普通雕像
EvilFace, // 邪恶表情
EvilHands, // 恶毒双手
JealousHeart // 嫉妒之心
}
public enum StatueState
{
Idle,
Hit,
Breaking,
Broken,
EvilLaugh
}
public StatueState currentState = StatueState.Idle;
// 当前裂痕等级
private int crackLevel = 0;
// 是否可以被击打
private bool canHit = true;
// 事件回调
public Action<CrystalStatue, bool> OnStatueBroken; // 雕像碎裂回调(雕像, 是否是目标)
#endregion
#region Unity生命周期
private void Awake()
{
if (animator == null)
animator = GetComponent<Animator>();
if (statueRenderer == null)
statueRenderer = GetComponentInChildren<Renderer>();
}
private void Start()
{
currentHealth = maxHealth;
crackLevel = 0;
canHit = true;
currentState = StatueState.Idle;
}
#endregion
#region
/// <summary>
/// 初始化雕像
/// </summary>
public void Initialize(StatueType type, bool isTarget)
{
this.statueType = type;
this.isTarget = isTarget;
currentHealth = maxHealth;
crackLevel = 0;
canHit = true;
currentState = StatueState.Idle;
// 根据类型设置视觉效果
SetupVisualsByType();
if (debugMode)
Debug.Log($"[CrystalStatue] 初始化雕像: {type}, 是否目标: {isTarget}");
}
/// <summary>
/// 根据类型设置视觉效果
/// </summary>
private void SetupVisualsByType()
{
// 隐藏所有特殊部件
if (heartObject != null)
heartObject.SetActive(false);
if (handsObject != null)
handsObject.SetActive(false);
if (evilFaceObject != null)
evilFaceObject.SetActive(false);
if (specialEffect != null)
specialEffect.Stop();
if (isTarget)
{
// 根据类型显示对应部件
switch (statueType)
{
case StatueType.EvilFace:
// 第一轮:邪恶表情区分
// 目标雕像显示邪恶表情,非目标显示和善表情
if (isTarget)
{
// 邪恶表情
if (evilFaceObject != null)
evilFaceObject.SetActive(true);
if (debugMode)
Debug.Log("[CrystalStatue] 设置邪恶表情(目标雕像)");
}
else
{
if (debugMode)
Debug.Log("[CrystalStatue] 设置和善表情(非目标雕像)");
}
break;
case StatueType.EvilHands:
// 第二轮:恶毒双手区分
if (handsObject != null)
handsObject.SetActive(true);
if (specialEffect != null && isTarget)
specialEffect.Play();
break;
case StatueType.JealousHeart:
// 第三轮:嫉妒之心区分
if (heartObject != null)
heartObject.SetActive(true);
if (specialEffect != null && isTarget)
specialEffect.Play();
break;
}
}
// 重置裂痕
UpdateCrackVisual(0);
}
#endregion
#region
/// <summary>
/// 玩家击中雕像
/// </summary>
public void OnPlayerHit()
{
if (!canHit || currentState == StatueState.Broken)
{
if (debugMode)
Debug.Log("[CrystalStatue] 雕像不可被击打");
return;
}
currentState = StatueState.Hit;
currentHealth--;
crackLevel = maxHealth - currentHealth;
if (debugMode)
Debug.Log($"[CrystalStatue] 雕像被击打! 剩余血量: {currentHealth}, 裂痕等级: {crackLevel}");
// 播放击打音效
PlayHitSound();
// 播放击打特效
PlayHitEffect();
// 播放击打动画
PlayHitAnimation();
// 更新裂痕视觉效果
UpdateCrackVisual(crackLevel);
// 检查是否碎裂
if (currentHealth <= 0)
{
Break();
}
else
{
// 短暂冷却
canHit = false;
DOVirtual.DelayedCall(0.2f, () =>
{
canHit = true;
if (currentHealth > 0)
currentState = StatueState.Idle;
});
}
}
/// <summary>
/// 雕像碎裂
/// </summary>
public void Break()
{
currentState = StatueState.Breaking;
canHit = false;
if (debugMode)
Debug.Log($"[CrystalStatue] 雕像碎裂! 是否目标: {isTarget}");
// 播放碎裂音效
PlayBreakSound();
// 播放碎裂特效
PlayBreakEffect();
// 播放碎裂动画
PlayBreakAnimation();
// 延迟后触发回调
DOVirtual.DelayedCall(disappearDelay, () =>
{
currentState = StatueState.Broken;
OnStatueBroken?.Invoke(this, isTarget);
});
}
/// <summary>
/// 播放邪恶狞笑(失败时)
/// </summary>
public void PlayEvilLaugh()
{
currentState = StatueState.EvilLaugh;
if (debugMode)
Debug.Log("[CrystalStatue] 播放邪恶狞笑");
// 播放狞笑音效
PlayEvilLaughSound();
// 播放狞笑特效
if (evilLaughParticle != null)
evilLaughParticle.Play();
// 播放狞笑动画
if (animator != null)
animator.SetTrigger(evilLaughAnimTrigger);
}
/// <summary>
/// 强制消失(其他雕像)
/// </summary>
public void ForceDisappear(float duration = 0.5f)
{
canHit = false;
// 缩放消失效果
transform.DOScale(Vector3.zero, duration)
.SetEase(Ease.InBack)
.OnComplete(() =>
{
currentState = StatueState.Broken;
gameObject.SetActive(false);
});
// 播放碎裂音效
PlayBreakSound();
}
#endregion
#region
private void PlayHitSound()
{
if (!string.IsNullOrEmpty(hitSound))
{
MasterAudio.PlaySound3DAtTransform(hitSound, transform);
}
}
private void PlayBreakSound()
{
if (!string.IsNullOrEmpty(breakSound))
{
MasterAudio.PlaySound3DAtTransform(breakSound, transform);
}
}
private void PlayEvilLaughSound()
{
if (!string.IsNullOrEmpty(evilLaughSound))
{
MasterAudio.PlaySound3DAtTransform(evilLaughSound, transform);
}
}
#endregion
#region
private void PlayHitEffect()
{
if (hitParticle != null)
{
hitParticle.Play();
}
// 播放受击震动效果
PlayHitShake();
}
/// <summary>
/// 播放受击震动效果
/// </summary>
private void PlayHitShake()
{
// 使用DOShakePosition实现震动
transform.DOShakePosition(
hitShakeDuration,
hitShakeStrength,
hitShakeVibrato,
hitShakeRandomness,
false, // 不震Y轴
true // 随机方向
);
// 同时添加轻微的旋转震动
transform.DOShakeRotation(
hitShakeDuration,
hitShakeStrength * 10f, // 旋转幅度稍大
hitShakeVibrato / 2,
hitShakeRandomness,
true
);
}
private void PlayBreakEffect()
{
if (breakParticle != null)
{
breakParticle.Play();
}
}
private void PlayHitAnimation()
{
if (animator != null)
{
animator.SetTrigger(hitAnimTrigger);
}
}
private void PlayBreakAnimation()
{
if (animator != null)
{
animator.SetTrigger(breakAnimTrigger);
}
// 碎裂缩放效果
transform.DOScale(Vector3.zero, breakDuration)
.SetEase(Ease.InBack)
.OnComplete(() =>
{
gameObject.SetActive(false);
});
}
/// <summary>
/// 更新裂痕视觉效果
/// </summary>
private void UpdateCrackVisual(int level)
{
// 更新裂痕贴花
for (int i = 0; i < crackDecals.Length; i++)
{
if (crackDecals[i] != null)
{
crackDecals[i].SetActive(i < level);
}
}
// 更新材质(如果有多个裂痕材质)
if (crackMaterials != null && crackMaterials.Length > level && statueRenderer != null)
{
statueRenderer.material = crackMaterials[level];
}
}
#endregion
#region
/// <summary>
/// 获取当前血量
/// </summary>
public int GetCurrentHealth()
{
return currentHealth;
}
/// <summary>
/// 获取裂痕等级
/// </summary>
public int GetCrackLevel()
{
return crackLevel;
}
/// <summary>
/// 是否已碎裂
/// </summary>
public bool IsBroken()
{
return currentState == StatueState.Broken;
}
/// <summary>
/// 重置雕像状态
/// </summary>
public void Reset()
{
currentHealth = maxHealth;
crackLevel = 0;
canHit = true;
currentState = StatueState.Idle;
// 重置缩放
transform.localScale = Vector3.one;
// 重置裂痕
UpdateCrackVisual(0);
// 显示对象
gameObject.SetActive(true);
}
/// <summary>
/// 设置可击打状态
/// </summary>
public void SetCanHit(bool value)
{
canHit = value;
}
#endregion
#region
#if UNITY_EDITOR
[ContextMenu("测试:击打雕像")]
private void TestHit()
{
OnPlayerHit();
}
[ContextMenu("测试:碎裂雕像")]
private void TestBreak()
{
Break();
}
[ContextMenu("测试:播放狞笑")]
private void TestEvilLaugh()
{
PlayEvilLaugh();
}
[ContextMenu("测试:重置雕像")]
private void TestReset()
{
Reset();
}
[ContextMenu("测试:强制消失")]
private void TestForceDisappear()
{
ForceDisappear();
}
#endif
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 82ad8b365d4388b4ea81677c4eb1e3f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,682 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using DarkTonic.MasterAudio;
using DG.Tweening;
/// <summary>
/// 水晶雕像事件 - 继承CutsceneBase
/// 管理三轮水晶雕像挑战的完整流程
/// </summary>
public class CrystalStatueEvent : CutsceneBase
{
#region
[Header("雕像预制体")]
public GameObject crystalStatuePrefab;
[Header("生成配置")]
public int statueCount = 5;
public float statueRadius = 3f; // 五角星排列半径
public float statueHeight = 0f; // 雕像高度
[Header("时间配置")]
public float roundTimeLimit = 90f; // 每轮时间限制(秒)
public float delayBetweenRounds = 3f; // 轮次间隔
[Header("音效配置")]
public string audioRound1Intro = "1.5"; // 第一轮介绍
public string audioRound1Success = "1.7"; // 第一轮成功
public string audioRound2Intro = "1.8"; // 第二轮介绍
public string audioRound2Success = "1.9"; // 第二轮成功
public string audioRound3Intro = "1.10"; // 第三轮介绍
public string audioRound3Success = "1.11"; // 第三轮成功
public string audioFail = "1.6"; // 失败提示
public string audioCrystalBreak = "2.1"; // 水晶敲碎
public string audioSuccessEffect = "2.2"; // 成功音效
public string audioEvilLaugh = "2.3"; // 狞笑音效
[Header("场景配置")]
public GameObject crystalWorldEnvironment; // 水晶世界环境
#endregion
#region
public enum CrystalEventState
{
None,
SceneTransition, // 场景切换
Round1_Intro, // 第一轮介绍
Round1_Playing, // 第一轮进行中
Round1_Success, // 第一轮成功
Round1_Fail, // 第一轮失败
Round2_Intro, // 第二轮介绍
Round2_Playing, // 第二轮进行中
Round2_Success, // 第二轮成功
Round2_Fail, // 第二轮失败
Round3_Intro, // 第三轮介绍
Round3_Playing, // 第三轮进行中
Round3_Success, // 第三轮成功
Round3_Fail, // 第三轮失败
TimeUp, // 超时失败
Complete // 全部完成
}
public CrystalEventState currentState = CrystalEventState.None;
public int currentRound = 0;
#endregion
#region
private List<CrystalStatue> spawnedStatues = new List<CrystalStatue>();
private CrystalStatue targetStatue; // 当前目标雕像
private float currentRoundTime; // 当前剩余时间
private bool isRoundActive; // 当前轮次是否激活
private bool isTimeUp; // 时间是否耗尽
private Coroutine roundTimerCoroutine;
#endregion
#region
public override void StartCutscene()
{
if (isPlaying)
{
Debug.LogWarning("[CrystalStatueEvent] 事件已在进行中");
return;
}
isPlaying = true;
currentStep = 0;
currentRound = 0;
currentState = CrystalEventState.None;
if (debugMode)
Debug.Log("[CrystalStatueEvent] ========== 开始水晶雕像事件 ==========");
// 进入雕像事件模式,切换道具
if (GameManager.Ins.playerRightHand != null)
{
GameManager.Ins.playerRightHand.EnterStatueEventMode();
}
StartCoroutine(PlayEventSequence());
}
public override string GetCurrentStateDescription()
{
return $"轮次{currentRound}: {currentState}, 剩余时间: {currentRoundTime:F1}秒";
}
#endregion
#region
private IEnumerator PlayEventSequence()
{
// ========== 场景切换 ==========
currentState = CrystalEventState.SceneTransition;
currentStep = 1;
if (debugMode)
Debug.Log("[CrystalStatueEvent] 步骤1: 场景切换到水晶世界");
// 激活水晶世界环境
if (crystalWorldEnvironment != null)
crystalWorldEnvironment.SetActive(true);
// 播放BGM
GameManager.Ins.PlayBGM(1);
yield return new WaitForSeconds(1f);
// ========== 第一轮:邪恶表情 ==========
currentRound = 1;
yield return StartCoroutine(PlayRound(1, CrystalStatue.StatueType.EvilFace,
audioRound1Intro, audioRound1Success));
if (!isPlaying) yield break;
// ========== 第二轮:恶毒双手 ==========
currentRound = 2;
yield return new WaitForSeconds(delayBetweenRounds);
yield return StartCoroutine(PlayRound(2, CrystalStatue.StatueType.EvilHands,
audioRound2Intro, audioRound2Success));
if (!isPlaying) yield break;
// ========== 第三轮:嫉妒之心 ==========
currentRound = 3;
yield return new WaitForSeconds(delayBetweenRounds);
yield return StartCoroutine(PlayRound(3, CrystalStatue.StatueType.JealousHeart,
audioRound3Intro, audioRound3Success));
if (!isPlaying) yield break;
// ========== 完成 ==========
currentState = CrystalEventState.Complete;
currentStep = 10;
if (debugMode)
Debug.Log("[CrystalStatueEvent] ========== 水晶雕像事件完成 ==========");
// 清理雕像
CleanupStatues();
TriggerComplete();
}
/// <summary>
/// 执行一轮挑战
/// </summary>
private IEnumerator PlayRound(int round, CrystalStatue.StatueType type,
string introAudio, string successAudio)
{
// 设置状态
SetRoundState(round, CrystalEventState.Round1_Intro, CrystalEventState.Round2_Intro, CrystalEventState.Round3_Intro);
// 生成雕像
SpawnStatuesForRound(round, type);
// 播放介绍语音
PlayAudio2D(introAudio);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮开始: {type}");
// 等待介绍语音播放完成
yield return StartCoroutine(WaitForAudioComplete(introAudio, 10f));
// 额外等待一小段时间
yield return new WaitForSeconds(0.5f);
// 开始游戏
SetRoundState(round, CrystalEventState.Round1_Playing, CrystalEventState.Round2_Playing, CrystalEventState.Round3_Playing);
// 启动计时器
isRoundActive = true;
isTimeUp = false;
currentRoundTime = roundTimeLimit;
roundTimerCoroutine = StartCoroutine(RoundTimer());
// 等待结果
bool roundComplete = false;
bool roundSuccess = false;
System.Action<bool> onRoundEnd = (success) =>
{
roundComplete = true;
roundSuccess = success;
};
// 注册雕像碎裂回调
foreach (var statue in spawnedStatues)
{
statue.OnStatueBroken = (s, isTarget) =>
{
if (isTarget)
{
// 击中目标,成功
onRoundEnd(true);
}
else
{
// 击中非目标,失败
onRoundEnd(false);
}
};
}
// 等待玩家操作
yield return new WaitUntil(() => roundComplete || isTimeUp);
// 停止计时器
if (roundTimerCoroutine != null)
{
StopCoroutine(roundTimerCoroutine);
roundTimerCoroutine = null;
}
isRoundActive = false;
// 处理结果
// 第三轮特殊处理:无论成功失败都结束事件
if (round == 3)
{
if (isTimeUp)
{
// 第三轮超时失败
currentState = CrystalEventState.TimeUp;
yield return StartCoroutine(HandleTimeUp());
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
if (debugMode)
Debug.Log("[CrystalStatueEvent] 第三轮超时失败,结束水晶雕像事件");
}
else if (roundSuccess)
{
// 第三轮成功
currentState = CrystalEventState.Round3_Success;
yield return StartCoroutine(AllStatuesDisappearExcept(null));
PlayAudio2D(successAudio);
PlayAudio2D(audioSuccessEffect);
if (debugMode)
Debug.Log("[CrystalStatueEvent] 第三轮成功! 播放1.11语音");
yield return StartCoroutine(WaitForAudioComplete(successAudio, 10f));
}
else
{
// 第三轮失败(击打错误)
currentState = CrystalEventState.Round3_Fail;
yield return StartCoroutine(HandleFailButContinue());
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
if (debugMode)
Debug.Log("[CrystalStatueEvent] 第三轮失败播放1.6语音,结束水晶雕像事件");
}
// 第三轮结束,清理雕像并完成事件
CleanupStatues();
currentState = CrystalEventState.Complete;
currentStep = 10;
if (debugMode)
Debug.Log("[CrystalStatueEvent] ========== 水晶雕像事件完成 ==========");
TriggerComplete();
yield break; // 直接结束,不继续后续流程
}
// 第一轮和第二轮的处理
if (isTimeUp)
{
// 超时失败
currentState = CrystalEventState.TimeUp;
yield return StartCoroutine(HandleTimeUp());
// 等待失败语音播放完成后再进入下一轮
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
yield return new WaitForSeconds(0.5f);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮超时,进入下一轮");
}
else if (roundSuccess)
{
// 成功
SetRoundState(round, CrystalEventState.Round1_Success, CrystalEventState.Round2_Success, CrystalEventState.Round3_Success);
// 所有其他雕像消失
yield return StartCoroutine(AllStatuesDisappearExcept(null));
// 播放成功语音
PlayAudio2D(successAudio);
PlayAudio2D(audioSuccessEffect);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮成功!");
// 等待成功语音播放完成后再进入下一轮
yield return StartCoroutine(WaitForAudioComplete(successAudio, 10f));
yield return new WaitForSeconds(0.5f);
}
else
{
// 失败(击打错误)- 播放失败提示,但仍进入下一轮
SetRoundState(round, CrystalEventState.Round1_Fail, CrystalEventState.Round2_Fail, CrystalEventState.Round3_Fail);
yield return StartCoroutine(HandleFailButContinue());
// 等待失败语音播放完成后再进入下一轮
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
yield return new WaitForSeconds(0.5f);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮失败(击打错误),进入下一轮");
}
// 清理雕像
CleanupStatues();
}
/// <summary>
/// 设置轮次状态
/// </summary>
private void SetRoundState(int round, CrystalEventState state1, CrystalEventState state2, CrystalEventState state3)
{
switch (round)
{
case 1: currentState = state1; break;
case 2: currentState = state2; break;
case 3: currentState = state3; break;
}
}
#endregion
#region
private IEnumerator RoundTimer()
{
while (isRoundActive && currentRoundTime > 0)
{
currentRoundTime -= Time.deltaTime;
// 更新UI如果有
UpdateTimerUI(currentRoundTime);
yield return null;
}
if (currentRoundTime <= 0)
{
isTimeUp = true;
if (debugMode)
Debug.Log("[CrystalStatueEvent] 时间耗尽!");
}
}
/// <summary>
/// 等待音频播放完成
/// </summary>
private IEnumerator WaitForAudioComplete(string audioName, float maxWaitTime = 10f)
{
float elapsedTime = 0f;
// 等待音频开始播放
yield return new WaitForSeconds(0.1f);
while (elapsedTime < maxWaitTime)
{
MasterAudioGroup audioGroup = MasterAudio.GrabGroup(audioName);
if (audioGroup == null || audioGroup.ActiveVoices <= 0)
{
// 音频播放完成
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 音频 {audioName} 播放完成,耗时: {elapsedTime:F1}秒");
yield break;
}
elapsedTime += Time.deltaTime;
yield return null;
}
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 音频 {audioName} 等待超时");
}
/// <summary>
/// 更新计时器UI子类可重写
/// </summary>
protected virtual void UpdateTimerUI(float remainingTime)
{
// TODO: 更新HUD倒计时显示
// HUDPanel.Ins.UpdateTimer(remainingTime);
}
#endregion
#region
/// <summary>
/// 为指定轮次生成雕像
/// </summary>
private void SpawnStatuesForRound(int round, CrystalStatue.StatueType type)
{
CleanupStatues();
// 生成五角星排列的位置
Vector3[] positions = GeneratePentagramPositions(GameLocal.Ins.self.transform.position, statueRadius);
// 随机选择目标位置
int targetIndex = Random.Range(0, statueCount);
for (int i = 0; i < statueCount; i++)
{
Vector3 pos = positions[i];
pos.y = statueHeight;
GameObject statueObj = Instantiate(crystalStatuePrefab, pos, Quaternion.identity);
statueObj.name = $"CrystalStatue_{i}";
// 面向中心
statueObj.transform.LookAt(GameLocal.Ins.self.transform.position);
statueObj.transform.eulerAngles = new Vector3(0, statueObj.transform.eulerAngles.y, 0);
CrystalStatue statue = statueObj.GetComponent<CrystalStatue>();
if (statue == null)
{
statue = statueObj.AddComponent<CrystalStatue>();
}
// 初始化雕像
bool isTarget = (i == targetIndex);
statue.Initialize(type, isTarget);
if (isTarget)
{
targetStatue = statue;
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 目标雕像: 位置{i}");
}
spawnedStatues.Add(statue);
}
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 生成{statueCount}个雕像, 类型: {type}");
}
/// <summary>
/// 生成五角星排列位置
/// </summary>
private Vector3[] GeneratePentagramPositions(Vector3 center, float radius)
{
Vector3[] positions = new Vector3[statueCount];
for (int i = 0; i < statueCount; i++)
{
// 五角星角度,从顶部开始
float angle = i * (360f / statueCount) * Mathf.Deg2Rad - 90f * Mathf.Deg2Rad;
positions[i] = center + new Vector3(
Mathf.Cos(angle) * radius,
0,
Mathf.Sin(angle) * radius
);
}
return positions;
}
#endregion
#region
/// <summary>
/// 处理超时
/// </summary>
private IEnumerator HandleTimeUp()
{
if (debugMode)
Debug.Log("[CrystalStatueEvent] 处理超时失败");
// 所有雕像消失
yield return StartCoroutine(AllStatuesDisappear());
// 播放失败语音
PlayAudio2D(audioFail);
}
/// <summary>
/// 处理失败
/// </summary>
private IEnumerator HandleFail()
{
if (debugMode)
Debug.Log("[CrystalStatueEvent] 处理失败");
// 所有雕像狞笑
foreach (var statue in spawnedStatues)
{
if (!statue.IsBroken())
{
statue.PlayEvilLaugh();
}
}
// 播放狞笑音效
PlayAudio2D(audioEvilLaugh);
yield return new WaitForSeconds(1f);
// 所有雕像消失
yield return StartCoroutine(AllStatuesDisappear());
// 播放失败语音
PlayAudio2D(audioFail);
}
/// <summary>
/// 处理失败但继续进入下一轮
/// </summary>
private IEnumerator HandleFailButContinue()
{
if (debugMode)
Debug.Log("[CrystalStatueEvent] 处理失败(继续下一轮)");
// 所有雕像狞笑
foreach (var statue in spawnedStatues)
{
if (!statue.IsBroken())
{
statue.PlayEvilLaugh();
}
}
// 播放狞笑音效
PlayAudio2D(audioEvilLaugh);
yield return new WaitForSeconds(1f);
// 所有雕像消失
yield return StartCoroutine(AllStatuesDisappear());
// 播放失败提示语音
PlayAudio2D(audioFail);
}
/// <summary>
/// 所有雕像消失
/// </summary>
private IEnumerator AllStatuesDisappear()
{
foreach (var statue in spawnedStatues)
{
if (!statue.IsBroken())
{
statue.ForceDisappear(0.5f);
}
}
yield return new WaitForSeconds(0.6f);
}
/// <summary>
/// 除指定雕像外所有雕像消失
/// </summary>
private IEnumerator AllStatuesDisappearExcept(CrystalStatue exception)
{
foreach (var statue in spawnedStatues)
{
if (statue != exception && !statue.IsBroken())
{
statue.ForceDisappear(0.5f);
}
}
yield return new WaitForSeconds(0.6f);
}
#endregion
#region
/// <summary>
/// 清理所有雕像
/// </summary>
private void CleanupStatues()
{
foreach (var statue in spawnedStatues)
{
if (statue != null)
{
Destroy(statue.gameObject);
}
}
spawnedStatues.Clear();
targetStatue = null;
}
public override void Cleanup()
{
CleanupStatues();
if (crystalWorldEnvironment != null)
crystalWorldEnvironment.SetActive(false);
// 退出雕像事件模式,恢复道具
if (GameManager.Ins.playerRightHand != null)
{
GameManager.Ins.playerRightHand.ExitStatueEventMode();
}
base.Cleanup();
}
#endregion
#region
#if UNITY_EDITOR
[ContextMenu("开始事件")]
private void TestStartEvent()
{
StartCutscene();
}
[ContextMenu("停止事件")]
private void TestStopEvent()
{
StopCutscene();
}
[ContextMenu("清理雕像")]
private void TestCleanup()
{
CleanupStatues();
}
[ContextMenu("测试:生成第一轮雕像")]
private void TestSpawnRound1()
{
SpawnStatuesForRound(1, CrystalStatue.StatueType.EvilFace);
}
[ContextMenu("测试:生成第二轮雕像")]
private void TestSpawnRound2()
{
SpawnStatuesForRound(2, CrystalStatue.StatueType.EvilHands);
}
[ContextMenu("测试:生成第三轮雕像")]
private void TestSpawnRound3()
{
SpawnStatuesForRound(3, CrystalStatue.StatueType.JealousHeart);
}
#endif
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c1960c3bab2ab94d8e778ec1930a8cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,6 +2,7 @@ using UnityEngine;
using BehaviorDesigner.Runtime;
using DG.Tweening;
using DarkTonic.MasterAudio;
using DragonLi.Core;
/// <summary>
/// 魔镜控制器 - 挂载到魔镜预制体上
@ -264,6 +265,14 @@ public class Mirror : MonoBehaviour
currentState = MirrorState.Portal;
onComplete?.Invoke();
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
FadeOut(2, () =>
{
GameManager.Ins.StartCutscene(1);
});
}, 2f);
}
/// <summary>
@ -374,7 +383,7 @@ public class Mirror : MonoBehaviour
if (currentTween != null)
currentTween.Kill();
StopAudio();
//StopAudio();
if (portalParticles != null && portalParticles.isPlaying)
portalParticles.Stop();

View File

@ -351,6 +351,36 @@ public class Scene1Cutscene : CutsceneBase
#endregion
#region
/// <summary>
/// 下一个事件(水晶雕像事件)
/// </summary>
[Header("事件链")]
public CrystalStatueEvent nextCrystalStatueEvent;
/// <summary>
/// 重写完成方法,触发下一个事件
/// </summary>
protected virtual void TriggerComplete()
{
base.TriggerComplete();
// 触发水晶雕像事件
if (nextCrystalStatueEvent != null)
{
if (debugMode)
Debug.Log("[Scene1Cutscene] 触发水晶雕像事件...");
DOVirtual.DelayedCall(1f, () =>
{
nextCrystalStatueEvent.StartCutscene();
});
}
}
#endregion
#region
#if UNITY_EDITOR
@ -374,4 +404,4 @@ public class Scene1Cutscene : CutsceneBase
#endif
#endregion
}
}

View File

@ -284,8 +284,6 @@ public class Witch : MonoBehaviour
{
if (currentTween != null)
currentTween.Kill();
StopAudio();
}
/// <summary>

View File

@ -9,6 +9,17 @@ using DragonLi.Core;
using UnityEngine.XR.Interaction.Toolkit;
using TrackedPoseDriver = UnityEngine.SpatialTracking.TrackedPoseDriver;
/// <summary>
/// 击打结果
/// </summary>
public enum HitResult
{
None, // 无效击打
Hit, // 击中雕像
TargetBreak, // 击碎目标雕像
WrongBreak // 击碎错误雕像
}
public class RightHand : MonoBehaviour
{
public TrackedPoseDriver tracked;
@ -63,6 +74,7 @@ public class RightHand : MonoBehaviour
public void Init()
{
hand.SetActive(true);
statueEventHandObject.SetActive(false);
_isOpenLine = true;
}
@ -104,6 +116,49 @@ public class RightHand : MonoBehaviour
}
}
// 雕像事件击打检测
if (isInStatueEventMode && enableStatueHitDetection)
{
UpdateStatueHitDetection();
}
// 更新手部速度(用于挥拳检测)
handVelocity = Vector3.Distance(transform.position, lastPosition) / Time.deltaTime;
lastPosition = transform.position;
}
/// <summary>
/// 更新雕像击打检测
/// </summary>
private void UpdateStatueHitDetection()
{
// 检查击打时间间隔
if (Time.time - lastHitTime < hitInterval)
{
return; // 还在冷却时间内
}
// 方法1基于手部速度的挥拳检测
if (handVelocity > swingVelocityThreshold)
{
HitResult result = CheckAndHitStatue();
if (result != HitResult.None)
{
lastHitTime = Time.time; // 更新上次击打时间
Debug.Log($"[RightHand] 挥拳击打雕像结果: {result}");
}
}
// 方法2如果当前有碰撞的雕像按扳机键击打
if (currentHitStatue != null && isTrigger)
{
HitResult result = HitCurrentStatue();
if (result != HitResult.None)
{
lastHitTime = Time.time; // 更新上次击打时间
Debug.Log($"[RightHand] 扳机击打雕像结果: {result}");
}
}
}
public void ClickRrightTrigger()
@ -132,4 +187,215 @@ public class RightHand : MonoBehaviour
hand.SetActive(true);
_isOpenLine = true;
}
#region
[Header("雕像击打配置")]
public float hitDistance = 1.5f; // 击打检测距离
public float hitRadius = 0.3f; // 击打检测半径
public LayerMask statueLayerMask; // 雕像层级
/// <summary>
/// 当前击中的雕像
/// </summary>
private CrystalStatue currentHitStatue;
/// <summary>
/// 检测并击打水晶雕像
/// </summary>
public HitResult CheckAndHitStatue()
{
// 使用球形检测
Collider[] hits = Physics.OverlapSphere(transform.position, hitRadius, statueLayerMask);
if (hits.Length > 0)
{
foreach (var collider in hits)
{
CrystalStatue statue = collider.transform.parent.GetComponent<CrystalStatue>();
if (statue != null && !statue.IsBroken())
{
return HitStatue(statue);
}
}
}
return HitResult.None;
}
/// <summary>
/// 击打指定水晶雕像
/// </summary>
public HitResult HitStatue(CrystalStatue statue)
{
if (statue == null || statue.IsBroken())
{
return HitResult.None;
}
int healthBefore = statue.GetCurrentHealth();
statue.OnPlayerHit();
int healthAfter = statue.GetCurrentHealth();
// 判断击打结果
if (healthAfter <= 0)
{
// 雕像碎裂
if (statue.isTarget)
{
return HitResult.TargetBreak;
}
else
{
return HitResult.WrongBreak;
}
}
else if (healthAfter < healthBefore)
{
// 成功击打但未碎裂
return HitResult.Hit;
}
return HitResult.None;
}
/// <summary>
/// 获取视线前方的水晶雕像
/// </summary>
public CrystalStatue GetStatueInFront()
{
if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hitInfo, hitDistance, statueLayerMask))
{
CrystalStatue statue = hitInfo.collider.GetComponent<CrystalStatue>();
if (statue != null && !statue.IsBroken())
{
return statue;
}
}
return null;
}
/// <summary>
/// 挥拳检测击打雕像(基于手部速度)
/// </summary>
/// <param name="velocityThreshold">速度阈值</param>
public HitResult CheckSwingHit(float velocityThreshold = 2f)
{
// 检测手部速度是否超过阈值
float handSpeed = tracked ? tracked.transform.GetComponent<Rigidbody>()?.velocity.magnitude ?? 0f : 0f;
if (handSpeed < velocityThreshold)
{
return HitResult.None;
}
return CheckAndHitStatue();
}
/// <summary>
/// 设置当前击中的雕像(用于碰撞检测)
/// </summary>
public void SetCurrentHitStatue(CrystalStatue statue)
{
currentHitStatue = statue;
}
/// <summary>
/// 击打当前碰撞的雕像
/// </summary>
public HitResult HitCurrentStatue()
{
if (currentHitStatue != null)
{
return HitStatue(currentHitStatue);
}
return HitResult.None;
}
#endregion
#region
[Header("道具配置")]
public GameObject normalHandObject; // 普通手部道具
public GameObject statueEventHandObject; // 雕像事件专用道具(如手套)
[Header("击打检测配置")]
public bool enableStatueHitDetection = false; // 是否启用雕像击打检测
public float swingVelocityThreshold = 2f; // 挥拳速度阈值
public float hitInterval = 0.5f; // 击打时间间隔(秒)
/// <summary>
/// 是否处于雕像事件模式
/// </summary>
private bool isInStatueEventMode = false;
/// <summary>
/// 上次击打时间
/// </summary>
private float lastHitTime = 0f;
/// <summary>
/// 上一次的位置(用于计算速度)
/// </summary>
private Vector3 lastPosition;
/// <summary>
/// 手部速度
/// </summary>
private float handVelocity;
/// <summary>
/// 进入水晶雕像事件模式
/// </summary>
public void EnterStatueEventMode()
{
isInStatueEventMode = true;
enableStatueHitDetection = true;
// 隐藏射线
_isOpenLine = false;
if (ray != null)
ray.gameObject.SetActive(false);
// 切换道具
if (normalHandObject != null)
normalHandObject.SetActive(false);
if (statueEventHandObject != null)
statueEventHandObject.SetActive(true);
// 初始化位置追踪
lastPosition = transform.position;
handVelocity = 0f;
Debug.Log("[RightHand] 进入雕像事件模式,启用击打检测");
}
/// <summary>
/// 退出水晶雕像事件模式
/// </summary>
public void ExitStatueEventMode()
{
isInStatueEventMode = false;
enableStatueHitDetection = false;
// 清空当前碰撞的雕像
currentHitStatue = null;
// 恢复射线
_isOpenLine = true;
if (ray != null)
ray.gameObject.SetActive(true);
// 切换道具
if (statueEventHandObject != null)
statueEventHandObject.SetActive(false);
if (normalHandObject != null)
normalHandObject.SetActive(true);
Debug.Log("[RightHand] 退出雕像事件模式,禁用击打检测");
}
#endregion
}

View File

@ -37,8 +37,8 @@ TagManager:
- Player
- Air
- Door
- Gem
- Puzzle
- CrystalStatue
-
-
-
-