From d432c468b12674c9401ee35464a0f4f45e5d9e67 Mon Sep 17 00:00:00 2001 From: "Bob.Song" Date: Sun, 26 Apr 2026 14:42:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5=E6=96=B0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Conflicts: # Assets/Scenes/RopeTest.unity # Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs # Assets/Scripts/Fishing/Rope/Rope.cs # Assets/Scripts/Fishing/Rope/Rope.cs.meta --- Assets/Scenes/RopeTest.unity | 4348 +++-------------- Assets/Scripts/Editor/RopeEditor.cs | 29 - Assets/Scripts/Editor/RopeEditor.cs.meta | 3 - .../New/View/FishingLine/FLineLogicNode.cs | 138 + .../View/FishingLine/FLineLogicNode.cs.meta | 3 + .../New/View/FishingLine/FLineRenderer.cs | 1006 ++++ .../View/FishingLine/FLineRenderer.cs.meta | 3 + .../Fishing/New/View/FishingLine/FLineTest.cs | 349 ++ .../New/View/FishingLine/FLineTest.cs.meta | 2 + .../New/View/FishingLine/Provider.meta | 3 + .../Provider/FLineNodeBobberProvider.cs | 1539 ++++++ .../Provider/FLineNodeBobberProvider.cs.meta | 3 + .../SimpleWaterSurfaceProvider.cs | 3 +- .../SimpleWaterSurfaceProvider.cs.meta | 0 .../View/Player/Mono/JointPinchController.cs | 7 +- .../Player/States/IPlayerThrowAnimation.cs | 2 +- .../States/ParabolaPlayerThrowAnimation.cs | 8 +- .../View/Player/States/PlayerStageViewBase.cs | 13 +- .../Player/States/PlayerStageViewThrow.cs | 9 +- .../Fishing/New/View/Player/Tackle/FBobber.cs | 3 +- .../Fishing/New/View/Player/Tackle/FHook.cs | 11 +- .../Fishing/New/View/Player/Tackle/FLine.cs | 1117 ++++- .../New/View/Player/Tackle/FLine.cs.meta | 4 +- .../Fishing/New/View/Player/Tackle/FLure.cs | 4 +- .../Fishing/New/View/Player/Tackle/FRod.cs | 24 +- Assets/Scripts/Fishing/Rope/Rope.cs | 1069 ---- Assets/Scripts/Fishing/Rope/Rope.cs.meta | 3 - Assets/Scripts/Test.meta | 3 - Assets/Scripts/Test/BuoyancyCapsuleSphere.cs | 209 - .../Test/BuoyancyCapsuleSphere.cs.meta | 3 - Assets/Scripts/Test/BuoyancyWaterProvider.cs | 24 - .../Test/BuoyancyWaterProvider.cs.meta | 3 - Assets/Scripts/Test/CapsuleBuoyancyStable.cs | 268 - .../Test/CapsuleBuoyancyStable.cs.meta | 3 - Assets/Scripts/Test/CollisionTest.cs | 16 - Assets/Scripts/Test/CollisionTest.cs.meta | 3 - .../Scripts/Test/FishingLineTensionModel.cs | 337 -- .../Test/FishingLineTensionModel.cs.meta | 3 - Assets/Scripts/Test/New.meta | 3 - .../Test/New/BobberPresentationController.cs | 936 ---- .../New/BobberPresentationController.cs.meta | 3 - Assets/TerrainDef.mat | 229 + Assets/TerrainDef.mat.meta | 8 + Assets/TerrainDef_keywords.asset | 16 + Assets/TerrainDef_keywords.asset.meta | 8 + Assets/TerrainDef_propdata.asset | 1153 +++++ Assets/TerrainDef_propdata.asset.meta | 8 + ProjectSettings/URPProjectSettings.asset | 1 + 48 files changed, 6150 insertions(+), 6790 deletions(-) delete mode 100644 Assets/Scripts/Editor/RopeEditor.cs delete mode 100644 Assets/Scripts/Editor/RopeEditor.cs.meta create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs.meta create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs.meta create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs.meta create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/Provider.meta create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs create mode 100644 Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs.meta rename Assets/Scripts/{Test/New => Fishing/New/View/FishingLine}/SimpleWaterSurfaceProvider.cs (90%) rename Assets/Scripts/{Test/New => Fishing/New/View/FishingLine}/SimpleWaterSurfaceProvider.cs.meta (100%) delete mode 100644 Assets/Scripts/Fishing/Rope/Rope.cs delete mode 100644 Assets/Scripts/Fishing/Rope/Rope.cs.meta delete mode 100644 Assets/Scripts/Test.meta delete mode 100644 Assets/Scripts/Test/BuoyancyCapsuleSphere.cs delete mode 100644 Assets/Scripts/Test/BuoyancyCapsuleSphere.cs.meta delete mode 100644 Assets/Scripts/Test/BuoyancyWaterProvider.cs delete mode 100644 Assets/Scripts/Test/BuoyancyWaterProvider.cs.meta delete mode 100644 Assets/Scripts/Test/CapsuleBuoyancyStable.cs delete mode 100644 Assets/Scripts/Test/CapsuleBuoyancyStable.cs.meta delete mode 100644 Assets/Scripts/Test/CollisionTest.cs delete mode 100644 Assets/Scripts/Test/CollisionTest.cs.meta delete mode 100644 Assets/Scripts/Test/FishingLineTensionModel.cs delete mode 100644 Assets/Scripts/Test/FishingLineTensionModel.cs.meta delete mode 100644 Assets/Scripts/Test/New.meta delete mode 100644 Assets/Scripts/Test/New/BobberPresentationController.cs delete mode 100644 Assets/Scripts/Test/New/BobberPresentationController.cs.meta create mode 100644 Assets/TerrainDef.mat create mode 100644 Assets/TerrainDef.mat.meta create mode 100644 Assets/TerrainDef_keywords.asset create mode 100644 Assets/TerrainDef_keywords.asset.meta create mode 100644 Assets/TerrainDef_propdata.asset create mode 100644 Assets/TerrainDef_propdata.asset.meta diff --git a/Assets/Scenes/RopeTest.unity b/Assets/Scenes/RopeTest.unity index f10f7393f..9c0c265f9 100644 --- a/Assets/Scenes/RopeTest.unity +++ b/Assets/Scenes/RopeTest.unity @@ -119,6 +119,17 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!114 &145783537 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + m_PrefabInstance: {fileID: 1672280511} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78dc478e56ff48849761861244c93535, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::NBF.FishingLineSolver --- !u!1 &203844586 GameObject: m_ObjectHideFlags: 0 @@ -174,14 +185,14 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 203844586} m_Enabled: 1 - serializedVersion: 11 + serializedVersion: 13 m_Type: 1 m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} m_Intensity: 1 m_Range: 10 m_SpotAngle: 30 m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 + m_CookieSize2D: {x: 10, y: 10} m_Shadows: m_Type: 2 m_Resolution: -1 @@ -226,7 +237,7 @@ Light: m_UseBoundingSphereOverride: 0 m_UseViewFrustumForShadowCasterCull: 1 m_ForceVisible: 0 - m_ShadowRadius: 0 + m_ShapeRadius: 0 m_ShadowAngle: 0 m_LightUnit: 1 m_LuxAtDistance: 1 @@ -246,7 +257,7 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &337505875 +--- !u!1 &305036003 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -254,150 +265,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 337505879} - - component: {fileID: 337505878} - - component: {fileID: 337505877} - - component: {fileID: 337505876} - m_Layer: 0 - m_Name: FloatRope + - component: {fileID: 305036004} + - component: {fileID: 305036007} + - component: {fileID: 305036006} + - component: {fileID: 305036005} + m_Layer: 15 + m_Name: Cube m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!114 &337505876 -MonoBehaviour: +--- !u!4 &305036004 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 337505875} + m_GameObject: {fileID: 305036003} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1972679229} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &305036005 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 305036003} + 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 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8d8b3d7293da4ed8736330164944ddd3, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::PhysicsTools.Rope - ropeGameplayType: 0 - startJointSpringy: 0 - startJtSpring: - spring: 30000 - damper: 30000 - endJointSpringy: 0 - endJtSpring: - spring: 30000 - damper: 30000 - strStaticBones: - ropeMaterial: {fileID: 0} - lstComponentsCreated: [] - HideChildren: 0 - loggingType: 1 - ropeType: 0 - numControlPoints: 2 - controlPoints: - - obj: {fileID: 0} - localPos: {x: 0, y: 0, z: 0} - slackFraction: 1 - attached: 1 - - obj: {fileID: 0} - localPos: {x: 0, y: 0, z: 0} - slackFraction: 1 - attached: 1 - startPosition: {fileID: 0} - rate: 0 - gravity: 1 - kinematic: 0 - firstBone: {fileID: 0} - lastBone: {fileID: 0} - sendRopeEvents: 0 - rendererType: 1 - linkMesh: - modifiedMesh: {fileID: 0} - transform: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - defaultMesh: {fileID: 0} - defaultMeshMaterial: {fileID: 0} - defaultTransform: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} - meshMaterial: {fileID: 0} - position: {x: 0, y: 0, z: 0} - rotation: {x: 0, y: 0, z: 0} - scale: {x: 1, y: 1, z: 1} - continuousMaterial: {fileID: 2100000, guid: 7d04b7fb130c2c843a3545164f56e8f4, type: 2} - meshRenderer: {fileID: 0} - meshFilter: {fileID: 0} - useColliders: 1 - radiusFactor: 0.1 - segmentBordersScaleFactor: 1.75 - useSegmentBordersOffset: 1 - segPropertyType: 0 - segPropertiesBox: - massPerUnitLength: 10 - solverCount: 255 - length: 1 - linearDamping: 0.01 - angularDamping: 0.01 - width: 0.05 - height: 0.2 - segPropertiesCylinder: - massPerUnitLength: 0.1 - solverCount: 255 - length: 0.2 - linearDamping: 0.1 - angularDamping: 1 - radius: 0.03 - jointProp: - type: 0 - twistLimitDeg: 180 - swingLimitDeg: 70 - offsetScale: 0 - twistOffsetDeg: 0 - breakingForce: 0 - projectionDistance: 0.02 - projectionDistanceFirst: 0.02 - totalLengthGet: 0 - tensionGet: 0 - totalLength: 0 - totalLengthColliders: 0 - ropeStretchThreshold: -1 - textureLength: 0.33 ---- !u!23 &337505877 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &305036006 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 337505875} + m_GameObject: {fileID: 305036003} m_Enabled: 1 m_CastShadows: 1 m_ReceiveShadows: 1 @@ -416,7 +337,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 0} + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -438,30 +359,16 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &337505878 +--- !u!33 &305036007 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 337505875} - m_Mesh: {fileID: 0} ---- !u!4 &337505879 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 337505875} - 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} + m_GameObject: {fileID: 305036003} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} --- !u!1 &961739749 GameObject: m_ObjectHideFlags: 0 @@ -599,7 +506,7 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1264227897 +--- !u!1 &1069029757 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -607,150 +514,89 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1264227901} - - component: {fileID: 1264227900} - - component: {fileID: 1264227899} - - component: {fileID: 1264227898} + - component: {fileID: 1069029758} + - component: {fileID: 1069029763} + - component: {fileID: 1069029762} + - component: {fileID: 1069029761} + - component: {fileID: 1069029760} + - component: {fileID: 1069029764} m_Layer: 0 - m_Name: NormalRope + m_Name: Cube2 m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!114 &1264227898 -MonoBehaviour: +--- !u!4 &1069029758 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1264227897} + m_GameObject: {fileID: 1069029757} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: -0.5, z: 0} + m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2071328906} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!54 &1069029760 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1069029757} + serializedVersion: 5 + m_Mass: 1 + m_LinearDamping: 0 + m_AngularDamping: 0.05 + m_CenterOfMass: {x: 0, y: 0, z: 0} + m_InertiaTensor: {x: 1, y: 1, z: 1} + m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ImplicitCom: 1 + m_ImplicitTensor: 1 + m_UseGravity: 1 + m_IsKinematic: 0 + m_Interpolate: 1 + m_Constraints: 0 + m_CollisionDetection: 2 +--- !u!65 &1069029761 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1069029757} + 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 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8d8b3d7293da4ed8736330164944ddd3, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::PhysicsTools.Rope - ropeGameplayType: 0 - startJointSpringy: 0 - startJtSpring: - spring: 30000 - damper: 30000 - endJointSpringy: 0 - endJtSpring: - spring: 30000 - damper: 30000 - strStaticBones: - ropeMaterial: {fileID: 0} - lstComponentsCreated: [] - HideChildren: 0 - loggingType: 1 - ropeType: 0 - numControlPoints: 2 - controlPoints: - - obj: {fileID: 0} - localPos: {x: 0, y: 0, z: 0} - slackFraction: 1 - attached: 1 - - obj: {fileID: 0} - localPos: {x: 0, y: 0, z: 0} - slackFraction: 1 - attached: 1 - startPosition: {fileID: 2055159199} - rate: 0 - gravity: 5 - kinematic: 0 - firstBone: {fileID: 0} - lastBone: {fileID: 0} - sendRopeEvents: 0 - rendererType: 1 - linkMesh: - modifiedMesh: {fileID: 0} - transform: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - defaultMesh: {fileID: 0} - defaultMeshMaterial: {fileID: 0} - defaultTransform: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} - meshMaterial: {fileID: 0} - position: {x: 0, y: 0, z: 0} - rotation: {x: 0, y: 0, z: 0} - scale: {x: 1, y: 1, z: 1} - continuousMaterial: {fileID: 2100000, guid: 7d04b7fb130c2c843a3545164f56e8f4, type: 2} - meshRenderer: {fileID: 1264227899} - meshFilter: {fileID: 1264227900} - useColliders: 0 - radiusFactor: 0.1 - segmentBordersScaleFactor: 0.5 - useSegmentBordersOffset: 1 - segPropertyType: 0 - segPropertiesBox: - massPerUnitLength: 10 - solverCount: 255 - length: 1 - linearDamping: 0.01 - angularDamping: 0.01 - width: 0.05 - height: 0.2 - segPropertiesCylinder: - massPerUnitLength: 0.05 - solverCount: 255 - length: 0.75 - linearDamping: 1 - angularDamping: 4 - radius: 0.03 - jointProp: - type: 0 - twistLimitDeg: 180 - swingLimitDeg: 10 - offsetScale: 0 - twistOffsetDeg: 0 - breakingForce: 0 - projectionDistance: 0.04 - projectionDistanceFirst: 0.002 - totalLengthGet: 0 - tensionGet: 0 - totalLength: 0 - totalLengthColliders: 0 - ropeStretchThreshold: -1 - textureLength: 0.33 ---- !u!23 &1264227899 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1069029762 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1264227897} + m_GameObject: {fileID: 1069029757} m_Enabled: 1 m_CastShadows: 1 m_ReceiveShadows: 1 @@ -769,7 +615,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 0} + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -791,31 +637,119 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &1264227900 +--- !u!33 &1069029763 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1264227897} - m_Mesh: {fileID: 0} ---- !u!4 &1264227901 -Transform: + m_GameObject: {fileID: 1069029757} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!153 &1069029764 +ConfigurableJoint: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1264227897} - 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!1 &1482833884 + m_GameObject: {fileID: 1069029757} + serializedVersion: 4 + m_ConnectedBody: {fileID: 1629566070} + m_ConnectedArticulationBody: {fileID: 0} + m_Anchor: {x: 0, y: 0.5, z: 0} + m_Axis: {x: 1, y: 0, z: 0} + m_AutoConfigureConnectedAnchor: 1 + m_ConnectedAnchor: {x: 0, y: 0, z: 0} + m_SecondaryAxis: {x: 0, y: 1, z: 0} + m_XMotion: 1 + m_YMotion: 1 + m_ZMotion: 1 + m_AngularXMotion: 2 + m_AngularYMotion: 2 + m_AngularZMotion: 2 + m_LinearLimitSpring: + spring: 0 + damper: 0 + m_LinearLimit: + limit: 0.5 + bounciness: 0 + contactDistance: 0 + m_AngularXLimitSpring: + spring: 0 + damper: 0 + m_LowAngularXLimit: + limit: 0 + bounciness: 0 + contactDistance: 0 + m_HighAngularXLimit: + limit: 0 + bounciness: 0 + contactDistance: 0 + m_AngularYZLimitSpring: + spring: 0 + damper: 0 + m_AngularYLimit: + limit: 0 + bounciness: 0 + contactDistance: 0 + m_AngularZLimit: + limit: 0 + bounciness: 0 + contactDistance: 0 + m_TargetPosition: {x: 0, y: 0, z: 0} + m_TargetVelocity: {x: 0, y: 0, z: 0} + m_XDrive: + serializedVersion: 4 + positionSpring: 0 + positionDamper: 0 + maximumForce: 3.4028233e+38 + useAcceleration: 0 + m_YDrive: + serializedVersion: 4 + positionSpring: 0 + positionDamper: 0 + maximumForce: 3.4028233e+38 + useAcceleration: 0 + m_ZDrive: + serializedVersion: 4 + positionSpring: 0 + positionDamper: 0 + maximumForce: 3.4028233e+38 + useAcceleration: 0 + m_TargetRotation: {x: 0, y: 0, z: 0, w: 1} + m_TargetAngularVelocity: {x: 0, y: 0, z: 0} + m_RotationDriveMode: 0 + m_AngularXDrive: + serializedVersion: 4 + positionSpring: 0 + positionDamper: 0 + maximumForce: 3.4028233e+38 + useAcceleration: 0 + m_AngularYZDrive: + serializedVersion: 4 + positionSpring: 0 + positionDamper: 0 + maximumForce: 3.4028233e+38 + useAcceleration: 0 + m_SlerpDrive: + serializedVersion: 4 + positionSpring: 0 + positionDamper: 0 + maximumForce: 3.4028233e+38 + useAcceleration: 0 + m_ProjectionMode: 1 + m_ProjectionDistance: 0 + m_ProjectionAngle: 0 + m_ConfiguredInWorldSpace: 0 + m_SwapBodies: 0 + m_BreakForce: Infinity + m_BreakTorque: Infinity + m_EnableCollision: 0 + m_EnablePreprocessing: 1 + m_MassScale: 1 + m_ConnectedMassScale: 1 +--- !u!1 &1181671545 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -823,449 +757,298 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1482833885} - - component: {fileID: 1482833888} - - component: {fileID: 1482833887} - - component: {fileID: 1482833886} - m_Layer: 7 - m_Name: Sphere (1) + - component: {fileID: 1181671548} + - component: {fileID: 1181671547} + - component: {fileID: 1181671546} + m_Layer: 3 + m_Name: Terrain m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 + m_StaticEditorFlags: 2147483647 m_IsActive: 1 ---- !u!4 &1482833885 +--- !u!154 &1181671546 +TerrainCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1181671545} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 2 + m_TerrainData: {fileID: 15600000, guid: e5b77e954e13d8644859b63f2252924f, type: 2} + m_EnableTreeColliders: 1 +--- !u!218 &1181671547 +Terrain: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1181671545} + m_Enabled: 1 + serializedVersion: 6 + m_TerrainData: {fileID: 15600000, guid: e5b77e954e13d8644859b63f2252924f, type: 2} + m_TreeDistance: 5000 + m_TreeBillboardDistance: 50 + m_TreeCrossFadeLength: 5 + m_TreeMaximumFullLODCount: 50 + m_DetailObjectDistance: 80 + m_DetailObjectDensity: 1 + m_HeightmapPixelError: 5 + m_SplatMapDistance: 1000 + m_HeightmapMinimumLODSimplification: 0 + m_HeightmapMaximumLOD: 0 + m_ShadowCastingMode: 2 + m_DrawHeightmap: 1 + m_DrawInstanced: 0 + m_DrawTreesAndFoliage: 1 + m_StaticShadowCaster: 0 + m_IgnoreQualitySettings: 0 + m_ReflectionProbeUsage: 1 + m_MaterialTemplate: {fileID: 2100000, guid: 95965ffe54835394fbe1c387dac39df6, type: 2} + m_BakeLightProbesForTrees: 1 + m_PreserveTreePrototypeLayers: 0 + m_DeringLightProbesForTrees: 1 + m_ReceiveGI: 1 + m_ScaleInLightmap: 0.0256 + m_LightmapParameters: {fileID: 15203, guid: 0000000000000000f000000000000000, type: 0} + m_GroupingID: 0 + m_RenderingLayerMask: 1 + m_AllowAutoConnect: 1 + m_EnableHeightmapRayTracing: 1 + m_EnableTreesAndDetailsRayTracing: 0 + m_TreeMotionVectorModeOverride: 3 +--- !u!4 &1181671548 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1482833884} + m_GameObject: {fileID: 1181671545} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -21.88, y: 0, z: -16.13} + 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!4 &1302094367 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 153991853389016720, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + m_PrefabInstance: {fileID: 1672280511} + m_PrefabAsset: {fileID: 0} +--- !u!1 &1629566069 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1629566073} + - component: {fileID: 1629566072} + - component: {fileID: 1629566071} + - component: {fileID: 1629566070} + m_Layer: 0 + m_Name: Cube1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!54 &1629566070 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629566069} + serializedVersion: 5 + m_Mass: 1 + m_LinearDamping: 0 + m_AngularDamping: 0.05 + m_CenterOfMass: {x: 0, y: 0, z: 0} + m_InertiaTensor: {x: 1, y: 1, z: 1} + m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ImplicitCom: 1 + m_ImplicitTensor: 1 + m_UseGravity: 0 + m_IsKinematic: 1 + m_Interpolate: 0 + m_Constraints: 0 + m_CollisionDetection: 0 +--- !u!23 &1629566071 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629566069} + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1629566072 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629566069} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1629566073 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629566069} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} + m_LocalScale: {x: 0.02, y: 0.02, z: 0.02} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 6837949304265555196} + m_Father: {fileID: 2071328906} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!135 &1482833886 -SphereCollider: +--- !u!1001 &1672280511 +PrefabInstance: m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1482833884} - 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: 0 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1482833887 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1482833884} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &1482833888 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1482833884} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!1 &1601278527 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1601278529} - - component: {fileID: 1601278528} - m_Layer: 0 - m_Name: Obi Solver - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1601278528 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1601278527} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9d174fab52f0c4b8399f25d5c3ea524c, type: 3} - m_Name: - m_EditorClassIdentifier: Obi::Obi.ObiSolver - simulateWhenInvisible: 1 - m_Backend: 1 - substeps: 4 - maxStepsPerFrame: 1 - synchronization: 0 - parameters: - mode: 0 - interpolation: 0 - gravity: {x: 0, y: -9.81, z: 0} - ambientWind: {x: 0, y: 0, z: 0} - foamGravityScale: 1 - damping: 0 - maxAnisotropy: 3 - sleepThreshold: 0.0005 - maxVelocity: 50 - maxAngularVelocity: 20 - collisionMargin: 0.02 - maxDepenetration: 10 - colliderCCD: 1 - particleCCD: 0 - shockPropagation: 0 - surfaceCollisionIterations: 8 - surfaceCollisionTolerance: 0.005 - diffusionMask: {x: 1, y: 1, z: 1, w: 1} - m_MaxSurfaceChunks: 32768 - maxQueryResults: 8192 - maxFoamParticles: 8192 - maxParticleNeighbors: 128 - maxParticleContacts: 6 - useLimits: 0 - killOffLimitsParticles: 0 - boundaryLimits: - m_Center: {x: 0, y: 0, z: 0} - m_Extent: {x: 5, y: 5, z: 5} - gravity: {x: 0, y: -9.81, z: 0} - gravitySpace: 1 - ambientWind: {x: 0, y: 0, z: 0} - windSpace: 1 - foamSubsteps: 1 - foamMinNeighbors: 3 - foamCollisions: 0 - maxFoamVelocityStretch: 0.3 - foamRadiusScale: 1 - foamFade: {x: 0.05, y: 0.8} - foamAccelAgingRange: {x: 0.5, y: 0.8} - foamAccelAging: 4 - foamVolumeDensity: 0.1 - foamAmbientDensity: 0.02 - foamScatterColor: {r: 0.8, g: 0.75, b: 0.7, a: 1} - foamAmbientColor: {r: 0.4, g: 0.5, b: 0.6, a: 1} - worldLinearInertiaScale: 0 - worldAngularInertiaScale: 0 - synchronousSpatialQueries: 0 - distanceConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 1 - bendingConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - particleCollisionConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 1 - particleFrictionConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - collisionConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 1 - frictionConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - skinConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 1 - volumeConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - shapeMatchingConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - tetherConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - pinConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - pinholeConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - stitchConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - densityConstraintParameters: - evaluationOrder: 1 - iterations: 1 - SORFactor: 1 - enabled: 1 - stretchShearConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 1 - bendTwistConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 1 - chainConstraintParameters: - evaluationOrder: 0 - iterations: 1 - SORFactor: 1 - enabled: 0 ---- !u!4 &1601278529 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1601278527} 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: 8117598136312104020} - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1694612696 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1694612697} - - component: {fileID: 1694612700} - - component: {fileID: 1694612699} - - component: {fileID: 1694612698} - m_Layer: 7 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1694612697 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1386063717907585334, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_Name + value: Line1 + objectReference: {fileID: 0} + - target: {fileID: 1386063717907585334, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalPosition.x + value: 0.34499 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalPosition.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalPosition.z + value: -0.55092 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4162208118158024875, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: anchorTransform + value: + objectReference: {fileID: 2055159199} + - target: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: breakLimitDuration + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 6741752443570310990, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + propertyPath: breakStretchThreshold + value: 0.08 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 153991853389016720, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + insertIndex: -1 + addedObject: {fileID: 2127675973} + - targetCorrespondingSourceObject: {fileID: 6385925521264460254, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + insertIndex: -1 + addedObject: {fileID: 305036004} + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} +--- !u!4 &1972679229 stripped Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} + m_CorrespondingSourceObject: {fileID: 6385925521264460254, guid: ea6901d8aa7c41d41987d8ca92b02f6d, type: 3} + m_PrefabInstance: {fileID: 1672280511} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1694612696} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 6844082285898097900} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!135 &1694612698 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1694612696} - 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: 0 - serializedVersion: 3 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1694612699 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1694612696} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &1694612700 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1694612696} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!1 &1714253611 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1714253613} - - component: {fileID: 1714253612} - m_Layer: 0 - m_Name: BurstCollisionWorld - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1714253612 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1714253611} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f1a161c4294214a4fbcb7e9e94800494, type: 3} - m_Name: - m_EditorClassIdentifier: Obi::Obi.BurstColliderWorld - cellSpans: - m_AlignBytes: 16 ---- !u!4 &1714253613 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1714253611} - 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!1 &2055159198 GameObject: m_ObjectHideFlags: 0 @@ -1279,13 +1062,14 @@ GameObject: - component: {fileID: 2055159202} - component: {fileID: 2055159201} - component: {fileID: 2055159200} + - component: {fileID: 2055159204} m_Layer: 7 m_Name: Tip m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &2055159199 Transform: m_ObjectHideFlags: 0 @@ -1295,7 +1079,7 @@ Transform: m_GameObject: {fileID: 2055159198} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalPosition: {x: 0, y: 1, z: 0} m_LocalScale: {x: 0.01, y: 0.01, z: 0.01} m_ConstrainProportionsScale: 0 m_Children: [] @@ -1396,6 +1180,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_AdditionalVertexStreams: {fileID: 0} --- !u!33 &2055159203 MeshFilter: @@ -1405,796 +1190,83 @@ MeshFilter: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2055159198} m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!114 &778308709455625297 +--- !u!114 &2055159204 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} + m_GameObject: {fileID: 2055159198} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c8b45ebbf86be4df6b0e6cd933812af2, type: 3} + m_Script: {fileID: 11500000, guid: 5382d66f55f6463cb469c5094b0e7a6b, type: 3} m_Name: - m_EditorClassIdentifier: Obi::Obi.ObiParticleRenderer - material: {fileID: 0} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 1 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - k__BackingField: {r: 1, g: 1, b: 1, a: 1} - k__BackingField: 1 ---- !u!114 &1920091469802601324 -MonoBehaviour: + m_EditorClassIdentifier: Assembly-CSharp::NBF.FishingLineTestController + solver: {fileID: 145783537} + initialFirstSegmentLength: 1.2 + minFirstSegmentLength: 0.1 + maxFirstSegmentLength: 5 + lineAdjustSpeed: 1 + extendKey: 273 + retractKey: 274 +--- !u!1 &2071328905 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842016368746434265} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5625b86b9e4b4482b82d83b962d0c873, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::RodLine ---- !u!114 &2634872453375388399 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c8b45ebbf86be4df6b0e6cd933812af2, type: 3} - m_Name: - m_EditorClassIdentifier: Obi::Obi.ObiParticleRenderer - material: {fileID: 0} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 1 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - k__BackingField: {r: 1, g: 1, b: 1, a: 1} - k__BackingField: 1 ---- !u!114 &3816906410227166674 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119515755686205543} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5625b86b9e4b4482b82d83b962d0c873, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::RodLine ---- !u!114 &4875253389575895776 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c8b45ebbf86be4df6b0e6cd933812af2, type: 3} - m_Name: - m_EditorClassIdentifier: Obi::Obi.ObiParticleRenderer - material: {fileID: 0} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 1 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - k__BackingField: {r: 1, g: 1, b: 1, a: 1} - k__BackingField: 1 ---- !u!114 &4919921352901105371 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842924913136487585} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ed5bbbc032ec4ca1bb56991d9141e311, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::NBF.LureController - rBody: {fileID: 6788925799129473637} - joint: {fileID: 6689220046679245543} ---- !u!1001 &5634959157749674791 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 0} - m_Modifications: - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 3385956386580495472, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_Name - value: LineSolver - objectReference: {fileID: 0} - - target: {fileID: 3385956386580495472, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - propertyPath: m_IsActive - value: 0 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: - - targetCorrespondingSourceObject: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - insertIndex: -1 - addedObject: {fileID: 6843898391279604458} - m_AddedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} ---- !u!4 &5634959157749674792 stripped -Transform: - m_CorrespondingSourceObject: {fileID: 744750288977666519, guid: 865b58fce3190254c8f19f70f294a0da, type: 3} - m_PrefabInstance: {fileID: 5634959157749674791} - m_PrefabAsset: {fileID: 0} ---- !u!114 &6133517375737252240 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119478150814791356} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8e9411b5edc6466a8014c59e3821bbaa, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::NBF.BobberController - _rbody: {fileID: 8099828655688219448} - joint: {fileID: 8253605012841951763} ---- !u!153 &6689220046679245543 -ConfigurableJoint: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842924913136487585} - serializedVersion: 4 - m_ConnectedBody: {fileID: 6788532209952517510} - m_ConnectedArticulationBody: {fileID: 0} - m_Anchor: {x: 0, y: 0, z: 0} - m_Axis: {x: 0, y: 0, z: 0} - m_AutoConfigureConnectedAnchor: 0 - m_ConnectedAnchor: {x: 0, y: 0, z: 0} - m_SecondaryAxis: {x: 0, y: 0, z: 0} - m_XMotion: 1 - m_YMotion: 1 - m_ZMotion: 1 - m_AngularXMotion: 2 - m_AngularYMotion: 2 - m_AngularZMotion: 2 - m_LinearLimitSpring: - spring: 0 - damper: 0 - m_LinearLimit: - limit: 0.5 - bounciness: 0 - contactDistance: 0 - m_AngularXLimitSpring: - spring: 0 - damper: 0 - m_LowAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_HighAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularYZLimitSpring: - spring: 0 - damper: 0 - m_AngularYLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularZLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_TargetPosition: {x: 0, y: 0, z: 0} - m_TargetVelocity: {x: 0, y: 0, z: 0} - m_XDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_YDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_TargetRotation: {x: 0, y: 0, z: 0, w: 1} - m_TargetAngularVelocity: {x: 0, y: 0, z: 0} - m_RotationDriveMode: 0 - m_AngularXDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_AngularYZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_SlerpDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ProjectionMode: 1 - m_ProjectionDistance: 0 - m_ProjectionAngle: 0 - m_ConfiguredInWorldSpace: 0 - m_SwapBodies: 0 - m_BreakForce: Infinity - m_BreakTorque: Infinity - m_EnableCollision: 0 - m_EnablePreprocessing: 0 - m_MassScale: 1 - m_ConnectedMassScale: 1 ---- !u!153 &6689916012017804461 -ConfigurableJoint: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842031574826573826} - serializedVersion: 4 - m_ConnectedBody: {fileID: 2055159200} - m_ConnectedArticulationBody: {fileID: 0} - m_Anchor: {x: 0, y: -0.01, z: 0} - m_Axis: {x: 0, y: 0, z: 0} - m_AutoConfigureConnectedAnchor: 0 - m_ConnectedAnchor: {x: 0, y: 0, z: 0} - m_SecondaryAxis: {x: 0, y: 0, z: 0} - m_XMotion: 1 - m_YMotion: 1 - m_ZMotion: 1 - m_AngularXMotion: 2 - m_AngularYMotion: 2 - m_AngularZMotion: 2 - m_LinearLimitSpring: - spring: 0 - damper: 0 - m_LinearLimit: - limit: 0.5 - bounciness: 0 - contactDistance: 0 - m_AngularXLimitSpring: - spring: 0 - damper: 0 - m_LowAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_HighAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularYZLimitSpring: - spring: 0 - damper: 0 - m_AngularYLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularZLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_TargetPosition: {x: 0, y: 0, z: 0} - m_TargetVelocity: {x: 0, y: 0, z: 0} - m_XDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_YDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_TargetRotation: {x: 0, y: 0, z: 0, w: 1} - m_TargetAngularVelocity: {x: 0, y: 0, z: 0} - m_RotationDriveMode: 0 - m_AngularXDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_AngularYZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_SlerpDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ProjectionMode: 1 - m_ProjectionDistance: 0 - m_ProjectionAngle: 0 - m_ConfiguredInWorldSpace: 0 - m_SwapBodies: 0 - m_BreakForce: Infinity - m_BreakTorque: Infinity - m_EnableCollision: 0 - m_EnablePreprocessing: 0 - m_MassScale: 1 - m_ConnectedMassScale: 1 ---- !u!54 &6788532209952517510 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842031574826573826} - serializedVersion: 5 - m_Mass: 0.1 - m_LinearDamping: 1 - m_AngularDamping: 0.1 - m_CenterOfMass: {x: 0, y: 0, z: 0} - m_InertiaTensor: {x: 0.001, y: 0.001, z: 0.001} - m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ImplicitCom: 1 - m_ImplicitTensor: 0 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 2 ---- !u!54 &6788925799129473637 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842924913136487585} - serializedVersion: 5 - m_Mass: 0.01 - m_LinearDamping: 1 - m_AngularDamping: 0.1 - m_CenterOfMass: {x: 0, y: 0, z: 0} - m_InertiaTensor: {x: 0.001, y: 0.001, z: 0.001} - m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ImplicitCom: 1 - m_ImplicitTensor: 0 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 2 ---- !u!33 &6810245148770022592 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Mesh: {fileID: 0} ---- !u!33 &6813331866940995800 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Mesh: {fileID: 0} ---- !u!23 &6818832180631398562 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 4be07647ecdb4b845a9e0fbc74bb0e0a, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!23 &6819786250721015471 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 4be07647ecdb4b845a9e0fbc74bb0e0a, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!4 &6837949304265555196 + serializedVersion: 6 + m_Component: + - component: {fileID: 2071328906} + - component: {fileID: 2071328908} + - component: {fileID: 2071328907} + m_Layer: 0 + m_Name: Test + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2071328906 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842031574826573826} + m_GameObject: {fileID: 2071328905} serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -1, z: 0} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 2, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 1482833885} - m_Father: {fileID: 6843898391279604458} + - {fileID: 1629566073} + - {fileID: 1069029758} + m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &6837974222737006430 -Transform: +--- !u!114 &2071328907 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842016368746434265} - 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: 6843898391279604458} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &6841443574183813993 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6843898391279604458} - - component: {fileID: 6872554058764761267} - m_Layer: 0 - m_Name: fishing line float set - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &6841953815286540369 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6844280562302892392} - - component: {fileID: 6876157680678237768} - - component: {fileID: 6819786250721015471} - - component: {fileID: 6810245148770022592} - - component: {fileID: 6872519578828441551} - - component: {fileID: 6876197150621984075} - - component: {fileID: 6876193849020525091} - - component: {fileID: 6873169782558645165} - - component: {fileID: 6873580244086034721} - - component: {fileID: 6873498485358597237} - - component: {fileID: 2634872453375388399} - m_Layer: 0 - m_Name: Float Line - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &6842016368746434265 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6837974222737006430} - - component: {fileID: 6870672225931587544} - - component: {fileID: 1920091469802601324} - m_Layer: 0 - m_Name: Rod Line - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!1 &6842031574826573826 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6837949304265555196} - - component: {fileID: 6788532209952517510} - - component: {fileID: 6689916012017804461} - - component: {fileID: 8882022755018891054} - m_Layer: 16 - m_Name: Float - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &6842872170371743157 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6843950384306933036} - - component: {fileID: 6873180718643268094} - - component: {fileID: 6818832180631398562} - - component: {fileID: 6813331866940995800} - - component: {fileID: 6872680517040354330} - - component: {fileID: 6872730497548243313} - - component: {fileID: 6873121608529491602} - - component: {fileID: 6872704419259973256} - - component: {fileID: 6876156905977088245} - - component: {fileID: 6873141442243636941} - - component: {fileID: 7923388705101294686} - m_Layer: 0 - m_Name: Fishing Line - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &6842924913136487585 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6844082285898097900} - - component: {fileID: 6788925799129473637} - - component: {fileID: 6689220046679245543} - - component: {fileID: 4919921352901105371} - m_Layer: 7 - m_Name: Lure - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &6843898391279604458 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841443574183813993} - 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: 6837974222737006430} - - {fileID: 6843950384306933036} - - {fileID: 6844280562302892392} - - {fileID: 6844082285898097900} - - {fileID: 6837949304265555196} - m_Father: {fileID: 5634959157749674792} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &6843950384306933036 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - 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: 6843898391279604458} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &6844082285898097900 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842924913136487585} - 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: - - {fileID: 1694612697} - m_Father: {fileID: 6843898391279604458} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &6844280562302892392 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - 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: 6843898391279604458} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!120 &6870672225931587544 + m_GameObject: {fileID: 2071328905} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: de29a7feade14959ae0942fa162dfbf6, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::NBF.SimpleRope + startPoint: {fileID: 1629566073} + endPoint: {fileID: 1069029758} + lineWidth: 0.002 +--- !u!120 &2071328908 LineRenderer: - serializedVersion: 2 + serializedVersion: 3 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842016368746434265} + m_GameObject: {fileID: 2071328905} m_Enabled: 1 m_CastShadows: 1 m_ReceiveShadows: 1 @@ -2213,7 +1285,7 @@ LineRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 4be07647ecdb4b845a9e0fbc74bb0e0a, type: 2} + - {fileID: 0} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2225,7 +1297,7 @@ LineRenderer: m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 0 + m_StitchLightmapSeams: 1 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -2235,6 +1307,7 @@ LineRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_Positions: - {x: 0, y: 0, z: 0} - {x: 0, y: 0, z: 1} @@ -2246,7 +1319,16 @@ LineRenderer: m_Curve: - serializedVersion: 3 time: 0 - value: 1 + value: 0.002 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.002 inSlope: 0 outSlope: 0 tangentMode: 0 @@ -2293,2023 +1375,50 @@ LineRenderer: textureScale: {x: 1, y: 1} shadowBias: 0.5 generateLightingData: 0 - m_MaskInteraction: 0 m_UseWorldSpace: 1 m_Loop: 0 m_ApplyActiveColorSpace: 1 ---- !u!114 &6872519578828441551 -MonoBehaviour: +--- !u!1 &2127675972 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 958c969cfb16745f192d4d7bd28b7178, type: 3} - m_Name: - m_EditorClassIdentifier: - decimation: 0.1 - smoothing: 3 - twist: 25 - indexInSystem: 0 ---- !u!114 &6872554058764761267 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841443574183813993} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c0403ffd74ce46fab8bd4ef057e51432, type: 3} - m_Name: - m_EditorClassIdentifier: - startParticleAttachment: {fileID: 6873121608529491602} - isLureConnect: 0 - rodLine: {fileID: 1920091469802601324} - fishingRope: {fileID: 6873141442243636941} - bobberRope: {fileID: 6873498485358597237} - Lure: {fileID: 4919921352901105371} - Bobber: {fileID: 8882022755018891054} ---- !u!114 &6872680517040354330 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 958c969cfb16745f192d4d7bd28b7178, type: 3} - m_Name: - m_EditorClassIdentifier: - decimation: 0.15 - smoothing: 3 - twist: 25 - indexInSystem: 1 ---- !u!114 &6872704419259973256 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 6873180718643268094} - m_Target: {fileID: 6837949304265555196} - m_ParticleGroup: {fileID: -2515171973132415257, guid: c29a67f2195883840b049b2c2a54a55c, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &6872730497548243313 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c4747da60837c44f9ba4b4a86879bcc8, type: 3} - m_Name: - m_EditorClassIdentifier: - material: {fileID: 0} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 1 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - uvAnchor: 0 - uvScale: {x: 1, y: 1} - normalizeV: 1 - section: {fileID: 11400000, guid: a0bc36a59515f413e90e10895929c938, type: 2} - thicknessScale: 1 ---- !u!114 &6873121608529491602 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 6873180718643268094} - m_Target: {fileID: 2055159199} - m_ParticleGroup: {fileID: -5395693579433732326, guid: c29a67f2195883840b049b2c2a54a55c, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &6873141442243636941 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 98ba9d435a0e49c9bb527c34cc91894d, type: 3} - m_Name: - m_EditorClassIdentifier: - isFloatRope: 0 - rope: {fileID: 6873180718643268094} - cursor: {fileID: 6876156905977088245} - percentageElasticity: 1 ---- !u!114 &6873169782558645165 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 6876157680678237768} - m_Target: {fileID: 6844082285898097900} - m_ParticleGroup: {fileID: -2515171973132415257, guid: c70c206ebccc14c4eb6a0cdbe80779f7, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &6873180718643268094 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 61104f33a3f344db9b7e0d0cda41a9fb, type: 3} - m_Name: - m_EditorClassIdentifier: - solverIndices: - serializedContents: - m_AlignBytes: 16 - groupID: 2 - m_CollisionMaterial: {fileID: 0} - m_SurfaceCollisions: 0 - m_MassScale: 1 - m_SelfCollisions: 0 - restLength_: 1 - elements: - - particle1: 126 - particle2: 127 - restLength: 0.01 - constraintForce: 0 - tearResistance: 1 - - particle1: 127 - particle2: 128 - restLength: 0.01 - constraintForce: 0 - tearResistance: 1 - - particle1: 128 - particle2: 129 - restLength: 0.01 - constraintForce: 0 - tearResistance: 1 - - particle1: 129 - particle2: 130 - restLength: 0.01 - constraintForce: 0 - tearResistance: 1 - - particle1: 130 - particle2: 131 - restLength: 0.010000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 131 - particle2: 132 - restLength: 0.009999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 132 - particle2: 133 - restLength: 0.010000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 133 - particle2: 134 - restLength: 0.009999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 134 - particle2: 135 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 135 - particle2: 136 - restLength: 0.009999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 136 - particle2: 137 - restLength: 0.009999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 137 - particle2: 138 - restLength: 0.009999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 138 - particle2: 139 - restLength: 0.009999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 139 - particle2: 140 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 140 - particle2: 141 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 141 - particle2: 142 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 142 - particle2: 143 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 143 - particle2: 144 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 144 - particle2: 145 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 145 - particle2: 146 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 146 - particle2: 147 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 147 - particle2: 148 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 148 - particle2: 149 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 149 - particle2: 150 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 150 - particle2: 151 - restLength: 0.010000005 - constraintForce: 0 - tearResistance: 1 - - particle1: 151 - particle2: 152 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 152 - particle2: 153 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 153 - particle2: 154 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 154 - particle2: 155 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 155 - particle2: 156 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 156 - particle2: 157 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 157 - particle2: 158 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 158 - particle2: 159 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 159 - particle2: 160 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 160 - particle2: 161 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 161 - particle2: 162 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 162 - particle2: 163 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 163 - particle2: 164 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 164 - particle2: 165 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 165 - particle2: 166 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 166 - particle2: 167 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 167 - particle2: 168 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 168 - particle2: 169 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 169 - particle2: 170 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 170 - particle2: 171 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 171 - particle2: 172 - restLength: 0.01000002 - constraintForce: 0 - tearResistance: 1 - - particle1: 172 - particle2: 173 - restLength: 0.00999999 - constraintForce: 0 - tearResistance: 1 - - particle1: 173 - particle2: 174 - restLength: 0.02412942 - constraintForce: 0 - tearResistance: 1 - - particle1: 174 - particle2: 175 - restLength: 0.024689138 - constraintForce: 0 - tearResistance: 1 - - particle1: 175 - particle2: 176 - restLength: 0.024504185 - constraintForce: 0 - tearResistance: 1 - - particle1: 176 - particle2: 177 - restLength: 0.024640024 - constraintForce: 0 - tearResistance: 1 - - particle1: 177 - particle2: 178 - restLength: 0.024379015 - constraintForce: 0 - tearResistance: 1 - - particle1: 178 - particle2: 179 - restLength: 0.024438322 - constraintForce: 0 - tearResistance: 1 - - particle1: 179 - particle2: 180 - restLength: 0.024568558 - constraintForce: 0 - tearResistance: 1 - - particle1: 180 - particle2: 181 - restLength: 0.024623036 - constraintForce: 0 - tearResistance: 1 - - particle1: 181 - particle2: 182 - restLength: 0.024484038 - constraintForce: 0 - tearResistance: 1 - - particle1: 182 - particle2: 183 - restLength: 0.024544239 - constraintForce: 0 - tearResistance: 1 - - particle1: 183 - particle2: 184 - restLength: 0.0245471 - constraintForce: 0 - tearResistance: 1 - - particle1: 184 - particle2: 185 - restLength: 0.024483979 - constraintForce: 0 - tearResistance: 1 - - particle1: 185 - particle2: 186 - restLength: 0.024620295 - constraintForce: 0 - tearResistance: 1 - - particle1: 186 - particle2: 187 - restLength: 0.024568498 - constraintForce: 0 - tearResistance: 1 - - particle1: 187 - particle2: 188 - restLength: 0.024438322 - constraintForce: 0 - tearResistance: 1 - - particle1: 188 - particle2: 189 - restLength: 0.024379075 - constraintForce: 0 - tearResistance: 1 - - particle1: 189 - particle2: 190 - restLength: 0.02464205 - constraintForce: 0 - tearResistance: 1 - - particle1: 190 - particle2: 191 - restLength: 0.024502158 - constraintForce: 0 - tearResistance: 1 - - particle1: 191 - particle2: 192 - restLength: 0.024687767 - constraintForce: 0 - tearResistance: 1 - - particle1: 192 - particle2: 193 - restLength: 0.024130762 - constraintForce: 0 - tearResistance: 1 - - particle1: 193 - particle2: 194 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 194 - particle2: 195 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - _aerodynamicsEnabled: 1 - _drag: 0.05 - _lift: 0.02 - m_RopeBlueprint: {fileID: 0} - tearingEnabled: 0 - tearResistanceMultiplier: 1000 - tearRate: 1 - _distanceConstraintsEnabled: 1 - _stretchingScale: 1 - _stretchCompliance: 0 - _maxCompression: 0 - _bendConstraintsEnabled: 1 - _bendCompliance: 0 - _maxBending: 0.05 - _plasticYield: 0 - _plasticCreep: 0 ---- !u!114 &6873498485358597237 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 98ba9d435a0e49c9bb527c34cc91894d, type: 3} - m_Name: - m_EditorClassIdentifier: - isFloatRope: 1 - rope: {fileID: 6876157680678237768} - cursor: {fileID: 6873580244086034721} - percentageElasticity: 1 ---- !u!114 &6873580244086034721 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8285ac97113f74d449053378d0e3a56b, type: 3} - m_Name: - m_EditorClassIdentifier: - m_CursorMu: 0 - m_SourceMu: 1 - direction: 1 ---- !u!114 &6876156905977088245 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8285ac97113f74d449053378d0e3a56b, type: 3} - m_Name: - m_EditorClassIdentifier: - m_CursorMu: 0 - m_SourceMu: 0 - direction: 1 ---- !u!114 &6876157680678237768 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 61104f33a3f344db9b7e0d0cda41a9fb, type: 3} - m_Name: - m_EditorClassIdentifier: - solverIndices: - serializedContents: - m_AlignBytes: 16 - groupID: 1 - m_CollisionMaterial: {fileID: 0} - m_SurfaceCollisions: 0 - m_MassScale: 1 - m_SelfCollisions: 0 - restLength_: 0.5 - elements: - - particle1: 0 - particle2: 1 - restLength: 0.022047479 - constraintForce: 0 - tearResistance: 1 - - particle1: 1 - particle2: 2 - restLength: 0.022272225 - constraintForce: 0 - tearResistance: 1 - - particle1: 2 - particle2: 3 - restLength: 0.022317044 - constraintForce: 0 - tearResistance: 1 - - particle1: 3 - particle2: 4 - restLength: 0.022227883 - constraintForce: 0 - tearResistance: 1 - - particle1: 4 - particle2: 5 - restLength: 0.022270732 - constraintForce: 0 - tearResistance: 1 - - particle1: 5 - particle2: 6 - restLength: 0.022227883 - constraintForce: 0 - tearResistance: 1 - - particle1: 6 - particle2: 7 - restLength: 0.022317037 - constraintForce: 0 - tearResistance: 1 - - particle1: 7 - particle2: 8 - restLength: 0.022272244 - constraintForce: 0 - tearResistance: 1 - - particle1: 8 - particle2: 9 - restLength: 0.022047475 - constraintForce: 0 - tearResistance: 1 - - particle1: 9 - particle2: 10 - restLength: 0.01999247 - constraintForce: 0 - tearResistance: 1 - - particle1: 10 - particle2: 11 - restLength: 0.020001456 - constraintForce: 0 - tearResistance: 1 - - particle1: 11 - particle2: 12 - restLength: 0.02001217 - constraintForce: 0 - tearResistance: 1 - - particle1: 12 - particle2: 13 - restLength: 0.020001411 - constraintForce: 0 - tearResistance: 1 - - particle1: 13 - particle2: 14 - restLength: 0.0199925 - constraintForce: 0 - tearResistance: 1 - - particle1: 14 - particle2: 15 - restLength: 0.01999253 - constraintForce: 0 - tearResistance: 1 - - particle1: 15 - particle2: 16 - restLength: 0.020001382 - constraintForce: 0 - tearResistance: 1 - - particle1: 16 - particle2: 17 - restLength: 0.02001217 - constraintForce: 0 - tearResistance: 1 - - particle1: 17 - particle2: 18 - restLength: 0.020001411 - constraintForce: 0 - tearResistance: 1 - - particle1: 18 - particle2: 19 - restLength: 0.0199925 - constraintForce: 0 - tearResistance: 1 - - particle1: 19 - particle2: 20 - restLength: 0.01999253 - constraintForce: 0 - tearResistance: 1 - - particle1: 20 - particle2: 21 - restLength: 0.020001382 - constraintForce: 0 - tearResistance: 1 - - particle1: 21 - particle2: 22 - restLength: 0.02001217 - constraintForce: 0 - tearResistance: 1 - - particle1: 22 - particle2: 23 - restLength: 0.020001382 - constraintForce: 0 - tearResistance: 1 - - particle1: 23 - particle2: 24 - restLength: 0.01999253 - constraintForce: 0 - tearResistance: 1 - _aerodynamicsEnabled: 1 - _drag: 0.05 - _lift: 0.02 - m_RopeBlueprint: {fileID: 11400000, guid: c70c206ebccc14c4eb6a0cdbe80779f7, type: 2} - tearingEnabled: 0 - tearResistanceMultiplier: 1000 - tearRate: 1 - _distanceConstraintsEnabled: 1 - _stretchingScale: 1 - _stretchCompliance: 0 - _maxCompression: 0 - _bendConstraintsEnabled: 1 - _bendCompliance: 0 - _maxBending: 0.05 - _plasticYield: 0 - _plasticCreep: 0 ---- !u!114 &6876193849020525091 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 6876157680678237768} - m_Target: {fileID: 6837949304265555196} - m_ParticleGroup: {fileID: -5395693579433732326, guid: c70c206ebccc14c4eb6a0cdbe80779f7, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &6876197150621984075 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6841953815286540369} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c4747da60837c44f9ba4b4a86879bcc8, type: 3} - m_Name: - m_EditorClassIdentifier: - material: {fileID: 0} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 1 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - uvAnchor: 0 - uvScale: {x: 1, y: 1} - normalizeV: 1 - section: {fileID: 11400000, guid: a0bc36a59515f413e90e10895929c938, type: 2} - thicknessScale: 1 ---- !u!114 &7645699620610277477 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118612270620924447} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ed5bbbc032ec4ca1bb56991d9141e311, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::NBF.LureController - rBody: {fileID: 8100556427846743259} - joint: {fileID: 8253140013628920921} ---- !u!114 &7923388705101294686 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842872170371743157} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c8b45ebbf86be4df6b0e6cd933812af2, type: 3} - m_Name: - m_EditorClassIdentifier: Obi::Obi.ObiParticleRenderer - material: {fileID: 0} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 1 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - k__BackingField: {r: 1, g: 1, b: 1, a: 1} - k__BackingField: 1 ---- !u!54 &8099828655688219448 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119478150814791356} - serializedVersion: 5 - m_Mass: 0.1 - m_LinearDamping: 1 - m_AngularDamping: 0.1 - m_CenterOfMass: {x: 0, y: 0, z: 0} - m_InertiaTensor: {x: 0.001, y: 0.001, z: 0.001} - m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ImplicitCom: 1 - m_ImplicitTensor: 0 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 2 ---- !u!54 &8100556427846743259 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118612270620924447} - serializedVersion: 5 - m_Mass: 0.01 - m_LinearDamping: 1 - m_AngularDamping: 0.1 - m_CenterOfMass: {x: 0, y: 0, z: 0} - m_InertiaTensor: {x: 0.001, y: 0.001, z: 0.001} - m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ImplicitCom: 1 - m_ImplicitTensor: 0 - m_UseGravity: 0 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 2 ---- !u!4 &8117225698763714518 + serializedVersion: 6 + m_Component: + - component: {fileID: 2127675973} + - component: {fileID: 2127675976} + - component: {fileID: 2127675975} + - component: {fileID: 2127675974} + m_Layer: 15 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2127675973 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} + m_GameObject: {fileID: 2127675972} 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: 8117598136312104020} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &8117449978511159890 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118612270620924447} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -1.5, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8117598136312104020} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &8117581860903869330 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + 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_LocalScale: {x: 0.02, y: 0.02, z: 0.02} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 8117598136312104020} + m_Father: {fileID: 1302094367} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &8117598136312104020 -Transform: +--- !u!65 &2127675974 +BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118962644956607959} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 486.93997, y: 0.24998, z: 420.9324} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 8122440385966590432} - - {fileID: 8117581860903869330} - - {fileID: 8117225698763714518} - - {fileID: 8117449978511159890} - - {fileID: 8122434914864310850} - m_Father: {fileID: 1601278529} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8118612270620924447 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8117449978511159890} - - component: {fileID: 8100556427846743259} - - component: {fileID: 8253140013628920921} - - component: {fileID: 8163383766948519134} - - component: {fileID: 7645699620610277477} - m_Layer: 7 - m_Name: Lure - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &8118629857601973003 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8117581860903869330} - - component: {fileID: 8160408579860127552} - - component: {fileID: 8141578562736913948} - - component: {fileID: 8129058971098738278} - - component: {fileID: 8159752492518154916} - - component: {fileID: 8159747188374390735} - - component: {fileID: 8160472619643117612} - - component: {fileID: 8159723648520316982} - - component: {fileID: 8156279967975087691} - - component: {fileID: 8160422011297183859} - - component: {fileID: 4875253389575895776} - m_Layer: 0 - m_Name: Fishing Line - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &8118962644956607959 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8117598136312104020} - - component: {fileID: 8159922936740883981} - m_Layer: 0 - m_Name: fishing line float set - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &8119478150814791356 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8122434914864310850} - - component: {fileID: 8099828655688219448} - - component: {fileID: 8253605012841951763} - - component: {fileID: 6133517375737252240} - m_Layer: 16 - m_Name: Float - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &8119515755686205543 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8122440385966590432} - - component: {fileID: 8143755866791508326} - - component: {fileID: 3816906410227166674} - m_Layer: 0 - m_Name: Rod Line - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!1 &8119543254562602735 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8117225698763714518} - - component: {fileID: 8156280429137191158} - - component: {fileID: 8140632749704126481} - - component: {fileID: 8133273112949334654} - - component: {fileID: 8159943123048042865} - - component: {fileID: 8156232011165955061} - - component: {fileID: 8156244270472182941} - - component: {fileID: 8160397922979826963} - - component: {fileID: 8160018935126886303} - - component: {fileID: 8160095196834104011} - - component: {fileID: 778308709455625297} - m_Layer: 0 - m_Name: Float Line - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &8122434914864310850 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119478150814791356} - 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: 8117598136312104020} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &8122440385966590432 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119515755686205543} - 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: 8117598136312104020} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8129058971098738278 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Mesh: {fileID: 0} ---- !u!33 &8133273112949334654 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Mesh: {fileID: 0} ---- !u!23 &8140632749704126481 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 4be07647ecdb4b845a9e0fbc74bb0e0a, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!23 &8141578562736913948 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - 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_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 4be07647ecdb4b845a9e0fbc74bb0e0a, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!120 &8143755866791508326 -LineRenderer: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119515755686205543} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 0 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 0 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 4be07647ecdb4b845a9e0fbc74bb0e0a, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 0 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_Positions: - - {x: 0, y: 0, z: 0} - - {x: 0, y: 0, z: 1} - m_Parameters: - serializedVersion: 3 - widthMultiplier: 1 - widthCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - colorGradient: - serializedVersion: 2 - key0: {r: 1, g: 1, b: 1, a: 1} - key1: {r: 1, g: 1, b: 1, a: 1} - key2: {r: 0, g: 0, b: 0, a: 0} - key3: {r: 0, g: 0, b: 0, a: 0} - key4: {r: 0, g: 0, b: 0, a: 0} - key5: {r: 0, g: 0, b: 0, a: 0} - key6: {r: 0, g: 0, b: 0, a: 0} - key7: {r: 0, g: 0, b: 0, a: 0} - ctime0: 0 - ctime1: 65535 - ctime2: 0 - ctime3: 0 - ctime4: 0 - ctime5: 0 - ctime6: 0 - ctime7: 0 - atime0: 0 - atime1: 65535 - atime2: 0 - atime3: 0 - atime4: 0 - atime5: 0 - atime6: 0 - atime7: 0 - m_Mode: 0 - m_ColorSpace: -1 - m_NumColorKeys: 2 - m_NumAlphaKeys: 2 - numCornerVertices: 0 - numCapVertices: 0 - alignment: 0 - textureMode: 0 - textureScale: {x: 1, y: 1} - shadowBias: 0.5 - generateLightingData: 0 - m_MaskInteraction: 0 - m_UseWorldSpace: 1 - m_Loop: 0 - m_ApplyActiveColorSpace: 1 ---- !u!114 &8156232011165955061 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c4747da60837c44f9ba4b4a86879bcc8, type: 3} - m_Name: - m_EditorClassIdentifier: - material: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 0 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - uvAnchor: 0 - uvScale: {x: 1, y: 1} - normalizeV: 1 - section: {fileID: 11400000, guid: a0bc36a59515f413e90e10895929c938, type: 2} - thicknessScale: 1 ---- !u!114 &8156244270472182941 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 8156280429137191158} - m_Target: {fileID: 8122434914864310850} - m_ParticleGroup: {fileID: -5395693579433732326, guid: c70c206ebccc14c4eb6a0cdbe80779f7, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &8156279967975087691 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8285ac97113f74d449053378d0e3a56b, type: 3} - m_Name: - m_EditorClassIdentifier: - m_CursorMu: 0 - m_SourceMu: 0 - direction: 1 ---- !u!114 &8156280429137191158 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 61104f33a3f344db9b7e0d0cda41a9fb, type: 3} - m_Name: - m_EditorClassIdentifier: - solverIndices: - serializedContents: 000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f000000400000004100000042000000430000004400000045000000460000004700000048000000490000004a0000004b0000004c0000004d0000004e0000004f000000500000005100000052000000530000005400000055000000560000005700000058000000590000005a0000005b0000005c0000005d0000005e0000005f000000600000006100000062000000630000006400000065000000660000006700000068000000690000006a0000006b0000006c0000006d0000006e0000006f000000700000007100000072000000730000007400000075000000760000007700000078000000790000007a0000007b0000007c000000 - m_AlignBytes: 16 - groupID: 1 - m_CollisionMaterial: {fileID: 0} - m_SurfaceCollisions: 0 - m_MassScale: 1 - m_SelfCollisions: 0 - restLength_: 0.5 - elements: - - particle1: 0 - particle2: 1 - restLength: 0.022047479 - constraintForce: 0 - tearResistance: 1 - - particle1: 1 - particle2: 2 - restLength: 0.022272225 - constraintForce: 0 - tearResistance: 1 - - particle1: 2 - particle2: 3 - restLength: 0.022317044 - constraintForce: 0 - tearResistance: 1 - - particle1: 3 - particle2: 4 - restLength: 0.022227883 - constraintForce: 0 - tearResistance: 1 - - particle1: 4 - particle2: 5 - restLength: 0.022270732 - constraintForce: 0 - tearResistance: 1 - - particle1: 5 - particle2: 6 - restLength: 0.022227883 - constraintForce: 0 - tearResistance: 1 - - particle1: 6 - particle2: 7 - restLength: 0.022317037 - constraintForce: 0 - tearResistance: 1 - - particle1: 7 - particle2: 8 - restLength: 0.022272244 - constraintForce: 0 - tearResistance: 1 - - particle1: 8 - particle2: 9 - restLength: 0.022047475 - constraintForce: 0 - tearResistance: 1 - - particle1: 9 - particle2: 10 - restLength: 0.01999247 - constraintForce: 0 - tearResistance: 1 - - particle1: 10 - particle2: 11 - restLength: 0.020001456 - constraintForce: 0 - tearResistance: 1 - - particle1: 11 - particle2: 12 - restLength: 0.02001217 - constraintForce: 0 - tearResistance: 1 - - particle1: 12 - particle2: 13 - restLength: 0.020001411 - constraintForce: 0 - tearResistance: 1 - - particle1: 13 - particle2: 14 - restLength: 0.0199925 - constraintForce: 0 - tearResistance: 1 - - particle1: 14 - particle2: 15 - restLength: 0.01999253 - constraintForce: 0 - tearResistance: 1 - - particle1: 15 - particle2: 16 - restLength: 0.020001382 - constraintForce: 0 - tearResistance: 1 - - particle1: 16 - particle2: 17 - restLength: 0.02001217 - constraintForce: 0 - tearResistance: 1 - - particle1: 17 - particle2: 18 - restLength: 0.020001411 - constraintForce: 0 - tearResistance: 1 - - particle1: 18 - particle2: 19 - restLength: 0.0199925 - constraintForce: 0 - tearResistance: 1 - - particle1: 19 - particle2: 20 - restLength: 0.01999253 - constraintForce: 0 - tearResistance: 1 - - particle1: 20 - particle2: 21 - restLength: 0.020001382 - constraintForce: 0 - tearResistance: 1 - - particle1: 21 - particle2: 22 - restLength: 0.02001217 - constraintForce: 0 - tearResistance: 1 - - particle1: 22 - particle2: 23 - restLength: 0.020001382 - constraintForce: 0 - tearResistance: 1 - - particle1: 23 - particle2: 24 - restLength: 0.01999253 - constraintForce: 0 - tearResistance: 1 - _aerodynamicsEnabled: 1 - _drag: 0.05 - _lift: 0.02 - m_RopeBlueprint: {fileID: 11400000, guid: c70c206ebccc14c4eb6a0cdbe80779f7, type: 2} - tearingEnabled: 0 - tearResistanceMultiplier: 1000 - tearRate: 1 - _distanceConstraintsEnabled: 1 - _stretchingScale: 1 - _stretchCompliance: 0 - _maxCompression: 0 - _bendConstraintsEnabled: 1 - _bendCompliance: 0.5 - _maxBending: 0.5 - _plasticYield: 0.1 - _plasticCreep: 0 ---- !u!114 &8159723648520316982 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 8160408579860127552} - m_Target: {fileID: 8122434914864310850} - m_ParticleGroup: {fileID: -6506362155496508246, guid: 90165a559e0af984497f40ee19419ea5, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &8159747188374390735 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c4747da60837c44f9ba4b4a86879bcc8, type: 3} - m_Name: - m_EditorClassIdentifier: - material: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} - renderParameters: - layer: 0 - lightProbeUsage: 1 - reflectionProbeUsage: 1 - shadowCastingMode: 0 - receiveShadows: 1 - motionVectors: 0 - renderingLayerMask: 4294967295 - uvAnchor: 0 - uvScale: {x: 1, y: 1} - normalizeV: 1 - section: {fileID: 11400000, guid: a0bc36a59515f413e90e10895929c938, type: 2} - thicknessScale: 1 ---- !u!114 &8159752492518154916 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 958c969cfb16745f192d4d7bd28b7178, type: 3} - m_Name: - m_EditorClassIdentifier: - decimation: 0.15 - smoothing: 3 - twist: 25 - indexInSystem: 1 ---- !u!114 &8159922936740883981 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118962644956607959} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c0403ffd74ce46fab8bd4ef057e51432, type: 3} - m_Name: - m_EditorClassIdentifier: - startParticleAttachment: {fileID: 8160472619643117612} - isLureConnect: 0 - rodLine: {fileID: 3816906410227166674} - fishingRope: {fileID: 8160422011297183859} - bobberRope: {fileID: 8160095196834104011} - Lure: {fileID: 7645699620610277477} - Bobber: {fileID: 6133517375737252240} ---- !u!114 &8159943123048042865 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 958c969cfb16745f192d4d7bd28b7178, type: 3} - m_Name: - m_EditorClassIdentifier: - decimation: 0.1 - smoothing: 3 - twist: 25 - indexInSystem: 0 ---- !u!114 &8160018935126886303 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8285ac97113f74d449053378d0e3a56b, type: 3} - m_Name: - m_EditorClassIdentifier: - m_CursorMu: 0 - m_SourceMu: 1 - direction: 1 ---- !u!114 &8160095196834104011 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 98ba9d435a0e49c9bb527c34cc91894d, type: 3} - m_Name: - m_EditorClassIdentifier: - isFloatRope: 1 - rope: {fileID: 8156280429137191158} - cursor: {fileID: 8160018935126886303} - percentageElasticity: 1 ---- !u!114 &8160397922979826963 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119543254562602735} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 8156280429137191158} - m_Target: {fileID: 8117449978511159890} - m_ParticleGroup: {fileID: -2515171973132415257, guid: c70c206ebccc14c4eb6a0cdbe80779f7, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!114 &8160408579860127552 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 61104f33a3f344db9b7e0d0cda41a9fb, type: 3} - m_Name: - m_EditorClassIdentifier: - solverIndices: - serializedContents: 7d0000007e0000007f000000800000008100000082000000830000008400000085000000860000008700000088000000890000008a0000008b0000008c0000008d0000008e0000008f000000900000009100000092000000930000009400000095000000960000009700000098000000990000009a0000009b0000009c0000009d0000009e0000009f000000a0000000a1000000a2000000a3000000a4000000a5000000a6000000a7000000a8000000a9000000aa000000ab000000ac000000ad000000ae000000af000000b0000000b1000000b2000000b3000000b4000000b5000000b6000000b7000000b8000000b9000000ba000000bb000000bc000000bd000000be000000bf000000c0000000c1000000c2000000c3000000c4000000c5000000c6000000c7000000c8000000c9000000ca000000cb000000cc000000cd000000ce000000cf000000d0000000d1000000d2000000d3000000d4000000d5000000d6000000d7000000d8000000d9000000da000000db000000dc000000dd000000de000000df000000e0000000e1000000e2000000e3000000e4000000e5000000e6000000e7000000e8000000e9000000ea000000eb000000ec000000ed000000ee000000ef000000f0000000f1000000f2000000f3000000f4000000f5000000f6000000f7000000f8000000f9000000fa000000fb000000fc000000fd000000fe000000ff000000000100000101000002010000030100000401000005010000060100000701000008010000090100000a0100000b0100000c0100000d0100000e0100000f010000100100001101000012010000130100001401000015010000160100001701000018010000190100001a0100001b0100001c0100001d0100001e0100001f010000200100002101000022010000230100002401000025010000260100002701000028010000290100002a0100002b0100002c0100002d0100002e0100002f010000300100003101000032010000330100003401000035010000360100003701000038010000390100003a0100003b0100003c0100003d0100003e0100003f010000400100004101000042010000430100004401000045010000460100004701000048010000490100004a0100004b0100004c0100004d0100004e0100004f010000500100005101000052010000530100005401000055010000560100005701000058010000590100005a0100005b0100005c0100005d0100005e0100005f010000600100006101000062010000630100006401000065010000660100006701000068010000690100006a0100006b0100006c0100006d0100006e0100006f01000070010000710100007201000073010000740100007501000076010000 - m_AlignBytes: 16 - groupID: 2 - m_CollisionMaterial: {fileID: 0} - m_SurfaceCollisions: 0 - m_MassScale: 1 - m_SelfCollisions: 0 - restLength_: 1 - elements: - - particle1: 125 - particle2: 126 - restLength: 0.02 - constraintForce: 0 - tearResistance: 1 - - particle1: 126 - particle2: 127 - restLength: 0.02 - constraintForce: 0 - tearResistance: 1 - - particle1: 127 - particle2: 128 - restLength: 0.02 - constraintForce: 0 - tearResistance: 1 - - particle1: 128 - particle2: 129 - restLength: 0.02 - constraintForce: 0 - tearResistance: 1 - - particle1: 129 - particle2: 130 - restLength: 0.020000003 - constraintForce: 0 - tearResistance: 1 - - particle1: 130 - particle2: 131 - restLength: 0.019999996 - constraintForce: 0 - tearResistance: 1 - - particle1: 131 - particle2: 132 - restLength: 0.020000003 - constraintForce: 0 - tearResistance: 1 - - particle1: 132 - particle2: 133 - restLength: 0.019999996 - constraintForce: 0 - tearResistance: 1 - - particle1: 133 - particle2: 134 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 134 - particle2: 135 - restLength: 0.019999996 - constraintForce: 0 - tearResistance: 1 - - particle1: 135 - particle2: 136 - restLength: 0.019999996 - constraintForce: 0 - tearResistance: 1 - - particle1: 136 - particle2: 137 - restLength: 0.019999996 - constraintForce: 0 - tearResistance: 1 - - particle1: 137 - particle2: 138 - restLength: 0.019999996 - constraintForce: 0 - tearResistance: 1 - - particle1: 138 - particle2: 139 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 139 - particle2: 140 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 140 - particle2: 141 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 141 - particle2: 142 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 142 - particle2: 143 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 143 - particle2: 144 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 144 - particle2: 145 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 145 - particle2: 146 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 146 - particle2: 147 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 147 - particle2: 148 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 148 - particle2: 149 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 149 - particle2: 150 - restLength: 0.02000001 - constraintForce: 0 - tearResistance: 1 - - particle1: 150 - particle2: 151 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 151 - particle2: 152 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 152 - particle2: 153 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 153 - particle2: 154 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 154 - particle2: 155 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 155 - particle2: 156 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 156 - particle2: 157 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 157 - particle2: 158 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 158 - particle2: 159 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 159 - particle2: 160 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 160 - particle2: 161 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 161 - particle2: 162 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 162 - particle2: 163 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 163 - particle2: 164 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 164 - particle2: 165 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 165 - particle2: 166 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 166 - particle2: 167 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 167 - particle2: 168 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 168 - particle2: 169 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 169 - particle2: 170 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 170 - particle2: 171 - restLength: 0.02000004 - constraintForce: 0 - tearResistance: 1 - - particle1: 171 - particle2: 172 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 172 - particle2: 173 - restLength: 0.01999998 - constraintForce: 0 - tearResistance: 1 - - particle1: 173 - particle2: 174 - restLength: 0.04000002 - constraintForce: 0 - tearResistance: 1 - _aerodynamicsEnabled: 1 - _drag: 0.05 - _lift: 0.02 - m_RopeBlueprint: {fileID: 11400000, guid: 90165a559e0af984497f40ee19419ea5, type: 2} - tearingEnabled: 0 - tearResistanceMultiplier: 1000 - tearRate: 1 - _distanceConstraintsEnabled: 1 - _stretchingScale: 1 - _stretchCompliance: 0 - _maxCompression: 0 - _bendConstraintsEnabled: 1 - _bendCompliance: 0.5 - _maxBending: 0.5 - _plasticYield: 0.1 - _plasticCreep: 0 ---- !u!114 &8160422011297183859 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 98ba9d435a0e49c9bb527c34cc91894d, type: 3} - m_Name: - m_EditorClassIdentifier: - isFloatRope: 0 - rope: {fileID: 8160408579860127552} - cursor: {fileID: 8156279967975087691} - percentageElasticity: 1 ---- !u!114 &8160472619643117612 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118629857601973003} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4d03c9194b7ab4aaba4dfa5afec22c69, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actor: {fileID: 8160408579860127552} - m_Target: {fileID: 0} - m_ParticleGroup: {fileID: 5356683708585918033, guid: 90165a559e0af984497f40ee19419ea5, type: 2} - m_AttachmentType: 0 - m_ConstrainOrientation: 0 - m_Projection: 0 - m_Compliance: 0 - breakThreshold: Infinity ---- !u!135 &8163383766948519134 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118612270620924447} + m_GameObject: {fileID: 2127675972} m_Material: {fileID: 0} m_IncludeLayers: serializedVersion: 2 @@ -4322,235 +1431,72 @@ SphereCollider: m_ProvidesContacts: 0 m_Enabled: 1 serializedVersion: 3 - m_Radius: 0.003 - m_Center: {x: 0, y: -0.0015, z: 0} ---- !u!153 &8253140013628920921 -ConfigurableJoint: + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &2127675975 +MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8118612270620924447} - serializedVersion: 4 - m_ConnectedBody: {fileID: 8099828655688219448} - m_ConnectedArticulationBody: {fileID: 0} - m_Anchor: {x: 0, y: 0, z: 0} - m_Axis: {x: 0, y: 0, z: 0} - m_AutoConfigureConnectedAnchor: 0 - m_ConnectedAnchor: {x: 0, y: 0, z: 0} - m_SecondaryAxis: {x: 0, y: 0, z: 0} - m_XMotion: 1 - m_YMotion: 1 - m_ZMotion: 1 - m_AngularXMotion: 2 - m_AngularYMotion: 2 - m_AngularZMotion: 2 - m_LinearLimitSpring: - spring: 0 - damper: 0 - m_LinearLimit: - limit: 0.5 - bounciness: 0 - contactDistance: 0 - m_AngularXLimitSpring: - spring: 0 - damper: 0 - m_LowAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_HighAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularYZLimitSpring: - spring: 0 - damper: 0 - m_AngularYLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularZLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_TargetPosition: {x: 0, y: 0, z: 0} - m_TargetVelocity: {x: 0, y: 0, z: 0} - m_XDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_YDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_TargetRotation: {x: 0, y: 0, z: 0, w: 1} - m_TargetAngularVelocity: {x: 0, y: 0, z: 0} - m_RotationDriveMode: 0 - m_AngularXDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_AngularYZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_SlerpDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ProjectionMode: 1 - m_ProjectionDistance: 0 - m_ProjectionAngle: 0 - m_ConfiguredInWorldSpace: 0 - m_SwapBodies: 0 - m_BreakForce: Infinity - m_BreakTorque: Infinity - m_EnableCollision: 0 - m_EnablePreprocessing: 0 - m_MassScale: 1 - m_ConnectedMassScale: 1 ---- !u!153 &8253605012841951763 -ConfigurableJoint: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8119478150814791356} - serializedVersion: 4 - m_ConnectedBody: {fileID: 2055159200} - m_ConnectedArticulationBody: {fileID: 0} - m_Anchor: {x: 0, y: -0.01, z: 0} - m_Axis: {x: 0, y: 0, z: 0} - m_AutoConfigureConnectedAnchor: 0 - m_ConnectedAnchor: {x: 0, y: 0, z: 0} - m_SecondaryAxis: {x: 0, y: 0, z: 0} - m_XMotion: 1 - m_YMotion: 1 - m_ZMotion: 1 - m_AngularXMotion: 2 - m_AngularYMotion: 2 - m_AngularZMotion: 2 - m_LinearLimitSpring: - spring: 0 - damper: 0 - m_LinearLimit: - limit: 0.5 - bounciness: 0 - contactDistance: 0 - m_AngularXLimitSpring: - spring: 0 - damper: 0 - m_LowAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_HighAngularXLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularYZLimitSpring: - spring: 0 - damper: 0 - m_AngularYLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_AngularZLimit: - limit: 0 - bounciness: 0 - contactDistance: 0 - m_TargetPosition: {x: 0, y: 0, z: 0} - m_TargetVelocity: {x: 0, y: 0, z: 0} - m_XDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_YDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_TargetRotation: {x: 0, y: 0, z: 0, w: 1} - m_TargetAngularVelocity: {x: 0, y: 0, z: 0} - m_RotationDriveMode: 0 - m_AngularXDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_AngularYZDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_SlerpDrive: - serializedVersion: 4 - positionSpring: 0 - positionDamper: 0 - maximumForce: 3.4028233e+38 - useAcceleration: 0 - m_ProjectionMode: 1 - m_ProjectionDistance: 0 - m_ProjectionAngle: 0 - m_ConfiguredInWorldSpace: 0 - m_SwapBodies: 0 - m_BreakForce: Infinity - m_BreakTorque: Infinity - m_EnableCollision: 0 - m_EnablePreprocessing: 0 - m_MassScale: 1 - m_ConnectedMassScale: 1 ---- !u!114 &8882022755018891054 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6842031574826573826} + m_GameObject: {fileID: 2127675972} m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8e9411b5edc6466a8014c59e3821bbaa, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::NBF.BobberController - _rbody: {fileID: 6788532209952517510} - joint: {fileID: 6689916012017804461} + 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_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, 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_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &2127675976 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2127675972} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 m_Roots: - {fileID: 961739753} - {fileID: 203844589} + - {fileID: 1181671548} - {fileID: 2055159199} - - {fileID: 5634959157749674791} - - {fileID: 1264227901} - - {fileID: 337505879} - - {fileID: 1601278529} - - {fileID: 1714253613} + - {fileID: 1672280511} + - {fileID: 2071328906} diff --git a/Assets/Scripts/Editor/RopeEditor.cs b/Assets/Scripts/Editor/RopeEditor.cs deleted file mode 100644 index 1f5082308..000000000 --- a/Assets/Scripts/Editor/RopeEditor.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UnityEditor; -using UnityEngine; - -[CustomEditor(typeof(Rope))] -public class RopeFishLineEditor : Editor -{ - private Rope _target; - - void OnEnable() - { - _target = target as Rope; - // lookAtPoint = serializedObject.FindProperty("lookAtPoint"); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - - if (GUILayout.Button("打印总长度")) - { - _target.DebugLength(); - // Debug.Log($"总长度={_target.GetCurrentLength()} 目标长度={_target.GetTargetLength()} smoot={_target.GetLengthSmoothVel()} relLen={_target.GetLengthByPoints()} PolylineLength={_target.GetPhysicsPolylineLength()}"); - } - // serializedObject.Update(); - // EditorGUILayout.PropertyField(lookAtPoint); - // serializedObject.ApplyModifiedProperties(); - } -} \ No newline at end of file diff --git a/Assets/Scripts/Editor/RopeEditor.cs.meta b/Assets/Scripts/Editor/RopeEditor.cs.meta deleted file mode 100644 index 9fc80e10b..000000000 --- a/Assets/Scripts/Editor/RopeEditor.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f24add4ba0ae4e76acd98c4a5512c366 -timeCreated: 1771850618 \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs b/Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs new file mode 100644 index 000000000..a4c2f9be4 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs @@ -0,0 +1,138 @@ +using UnityEngine; + +namespace NBF +{ + public enum FLineLogicNodeType + { + Start, + Bobber, + End + } + + /// + /// 硬线节点组件 - 可选,用于更方便的管理 + /// + [RequireComponent(typeof(Rigidbody))] + public class FLineLogicNode : MonoBehaviour + { + [Header("节点设置")] public FLineLogicNodeType NodeType = FLineLogicNodeType.Bobber; + [SerializeField] private bool isKinematic = false; + [SerializeField] private float mass = 1f; + + [Header("到下一个节点的段配置")] [SerializeField, Min(0.01f)] + private float nextSegmentMaxLength = 1f; + + [SerializeField, Min(0f)] private float nextSegmentMinLength = 0f; + + private Rigidbody rb; + private FLine parentCable; + + public Rigidbody Rigidbody + { + get + { + if (!rb) + { + rb = GetComponent(); + } + + return rb; + } + } + + public float NextSegmentMaxLength + { + get => nextSegmentMaxLength; + set => nextSegmentMaxLength = Mathf.Max(0.01f, value); + } + + public float NextSegmentMinLength + { + get => nextSegmentMinLength; + set => nextSegmentMinLength = Mathf.Max(0f, value); + } + + void Awake() + { + rb = Rigidbody; + InitializeNode(); + } + + void OnValidate() + { + mass = Mathf.Max(0.0001f, mass); + nextSegmentMaxLength = Mathf.Max(0.01f, nextSegmentMaxLength); + nextSegmentMinLength = Mathf.Max(0f, nextSegmentMinLength); + } + + private void InitializeNode() + { + if (Rigidbody) + { + Rigidbody.isKinematic = isKinematic; + Rigidbody.mass = Mathf.Max(0.0001f, mass); + Rigidbody.useGravity = !isKinematic; + } + } + + public void AttachToCable(FLine cable) + { + parentCable = cable; + + // // 计算到前一个节点的距离 + // var bodies = parentCable.GetConnectedBodies(); + // int myIndex = bodies.IndexOf(rb); + // + // if (myIndex > 0 && bodies[myIndex - 1] != null) + // { + // float distanceToPrevious = Vector3.Distance( + // transform.position, + // bodies[myIndex - 1].position + // ); + // parentCable.SetSegmentLength(myIndex - 1, distanceToPrevious); + // } + } + + /// + /// 固定/释放此节点 + /// + public void SetFixed(bool fixed_) + { + if (Rigidbody) + { + isKinematic = fixed_; + Rigidbody.isKinematic = fixed_; + Rigidbody.useGravity = !fixed_; + } + } + + /// + /// 施加力到此节点(会影响相邻节点) + /// + public void ApplyForce(Vector3 force, ForceMode mode = ForceMode.Force) + { + if (parentCable) + { + parentCable.ApplyForceAtBody(Rigidbody, force, mode); + } + else if (Rigidbody) + { + Rigidbody.AddForce(force, mode); + } + } + + public void SetSegmentLengths(float maxLength, float minLength) + { + NextSegmentMaxLength = maxLength; + NextSegmentMinLength = minLength; + } + + public bool TryGetAdjacentBodies(out Rigidbody previousBody, out Rigidbody nextBody) + { + previousBody = null; + nextBody = null; + + return parentCable && parentCable.TryGetAdjacentBodies(this, out previousBody, out nextBody); + } + } +} diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs.meta b/Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs.meta new file mode 100644 index 000000000..978d41932 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FLineLogicNode.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 324bd710e0c5460ea880c6314ae95058 +timeCreated: 1776948853 \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs b/Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs new file mode 100644 index 000000000..eb4f7f5f2 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs @@ -0,0 +1,1006 @@ +using System.Collections.Generic; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace NBF +{ + /// + /// Used for FLine visual rendering. + /// Reads rigid body nodes from the cable and simulates extra render points between logic nodes. + /// + [RequireComponent(typeof(FLine))] + [RequireComponent(typeof(LineRenderer))] + public class FLineRenderer : MonoBehaviour + { + private sealed class VisualSegmentState + { + public int SegmentIndex; + public int Subdivisions; + public LineRenderer Renderer; + public GameObject RendererObject; + public Vector3[] Points; + public Vector3[] PrevPoints; + public float[] EdgeRestLengths; + public bool[] SupportedPoints; + public Vector3[] SmoothPoints; + public Vector3[] SegmentPoints; + public int SmoothCapacity; + public int SegmentCapacity; + + public int PointCount => Points != null ? Points.Length : 0; + } + + [Header("Source")] [SerializeField] private FLine cable; + [SerializeField, Min(1)] private int visualSubdivisionsPerSegment = 5; + [SerializeField] private List visualSubdivisionsBySegment = new List(); + [SerializeField, Min(0f)] private float visualLengthTrim = 0.05f; + + [Header("Visual Physics")] [SerializeField, Min(0f)] + private float gravityStrength = 9.81f; + + [SerializeField, Range(0f, 1f)] private float velocityDamping = 0.985f; + [SerializeField, Range(1, 40)] private int solverIterations = 12; + [SerializeField, Range(0f, 1f)] private float stiffness = 1f; + [SerializeField] private Vector3 windVelocity = Vector3.zero; + [SerializeField, Min(0f)] private float windResponse = 0.5f; + [SerializeField, Min(0f)] private float maxWindAcceleration = 30f; + [SerializeField, Min(0f)] private float maxPointSpeed = 25f; + + [Header("Ground")] [SerializeField] private bool stopOnGround = false; + [SerializeField] private LayerMask groundMask = 0; + [SerializeField, Min(0f)] private float groundRadius = 0.01f; + [SerializeField, Min(0f)] private float groundCastHeight = 1f; + [SerializeField, Min(0.01f)] private float groundCastDistance = 3f; + + [Header("Water")] [SerializeField] private bool stopOnWaterSurface = false; + [SerializeField] private float waterSurfaceIgnoreNodeCount = 3; + [SerializeField] private float waterLevelY = 0f; + [SerializeField, Min(0f)] private float waterSurfaceOffset = 0.002f; + + [Header("Line Renderer")] [SerializeField, Min(0.0001f)] + private float lineWidth = 0.01f; + + [SerializeField] private bool smoothLine = true; + [SerializeField, Range(0, 4)] private int smoothingIterations = 2; + [SerializeField, Range(0.05f, 0.45f)] private float smoothingStrength = 0.25f; + [SerializeField, Min(0f)] private float lengthTolerance = 0.0005f; + + [Header("Taut Stabilization")] [SerializeField, Min(0f)] + private float tautSlackThreshold = 0.01f; + + [SerializeField, Range(0f, 1f)] private float tautPositionBlend = 0.85f; + [SerializeField, Range(0f, 1f)] private float tautVelocityRetention = 0.05f; + + [Header("Debug")] [SerializeField] private bool drawVisualNodes = false; + [SerializeField] private float gizmoNodeRadius = 0.015f; + + private readonly List _bodies = new List(); + private readonly List _segments = new List(); + + private LineRenderer _lineRenderer; + private bool _needsRebuild = true; + + private const float MinDistance = 0.0001f; + private const float MinDeltaTime = 0.0001f; + private const string SegmentRendererNamePrefix = "FLineRenderer Segment "; + + private void Awake() + { + cable = cable ? cable : GetComponent(); + _lineRenderer = GetComponent(); + ConfigureLineRenderer(_lineRenderer); + } + + private void OnEnable() + { + _needsRebuild = true; + } + + private void OnDisable() + { + ClearLine(); + } + + private void OnDestroy() + { + DestroyExtraSegmentRenderers(); + } + + private void OnValidate() + { + visualSubdivisionsPerSegment = Mathf.Max(1, visualSubdivisionsPerSegment); + gravityStrength = Mathf.Max(0f, gravityStrength); + visualLengthTrim = Mathf.Max(0f, visualLengthTrim); + velocityDamping = Mathf.Clamp01(velocityDamping); + solverIterations = Mathf.Clamp(solverIterations, 1, 40); + stiffness = Mathf.Clamp01(stiffness); + windResponse = Mathf.Max(0f, windResponse); + maxWindAcceleration = Mathf.Max(0f, maxWindAcceleration); + maxPointSpeed = Mathf.Max(0f, maxPointSpeed); + groundRadius = Mathf.Max(0f, groundRadius); + groundCastHeight = Mathf.Max(0f, groundCastHeight); + groundCastDistance = Mathf.Max(0.01f, groundCastDistance); + waterSurfaceOffset = Mathf.Max(0f, waterSurfaceOffset); + lineWidth = Mathf.Max(0.0001f, lineWidth); + smoothingIterations = Mathf.Clamp(smoothingIterations, 0, 4); + smoothingStrength = Mathf.Clamp(smoothingStrength, 0.05f, 0.45f); + lengthTolerance = Mathf.Max(0f, lengthTolerance); + tautSlackThreshold = Mathf.Max(0f, tautSlackThreshold); + tautPositionBlend = Mathf.Clamp01(tautPositionBlend); + tautVelocityRetention = Mathf.Clamp01(tautVelocityRetention); + gizmoNodeRadius = Mathf.Max(0f, gizmoNodeRadius); + + if (visualSubdivisionsBySegment == null) + visualSubdivisionsBySegment = new List(); + + for (int i = 0; i < visualSubdivisionsBySegment.Count; i++) + visualSubdivisionsBySegment[i] = Mathf.Max(0, visualSubdivisionsBySegment[i]); + + _needsRebuild = true; + + if (_lineRenderer == null) + _lineRenderer = GetComponent(); + + ConfigureLineRenderer(_lineRenderer); + SyncSegmentRendererStyles(); + } + + private void FixedUpdate() + { + if (!PrepareSimulation()) + return; + + float dt = Mathf.Max(Time.fixedDeltaTime, MinDeltaTime); + if (!stopOnGround && !stopOnWaterSurface) + ClearSupportedPoints(); + + LockCableNodes(); + SimulateFreePoints(dt); + RefreshRestLengths(); + + for (int i = 0; i < solverIterations; i++) + { + LockCableNodes(); + SolveDistanceConstraints(); + ApplySurfaceConstraints(); + } + + EnforceExactSegmentLengths(); + StabilizeTautSegments(); + LockCableNodes(); + } + + private void LateUpdate() + { + if (!PrepareSimulation()) + { + ClearLine(); + return; + } + + LockCableNodes(); + DrawLine(); + } + + public void Rebuild() + { + _needsRebuild = true; + } + + public void SetWind(Vector3 velocity, float response) + { + windVelocity = velocity; + windResponse = Mathf.Max(0f, response); + } + + private bool PrepareSimulation() + { + if (cable == null) + cable = GetComponent(); + + if (_lineRenderer == null) + { + _lineRenderer = GetComponent(); + ConfigureLineRenderer(_lineRenderer); + } + + if (cable == null || !RefreshBodies()) + return false; + + EnsureSegmentStates(); + return _segments.Count > 0; + } + + private bool RefreshBodies() + { + List sourceBodies = cable.GetConnectedBodies(); + if (sourceBodies == null || sourceBodies.Count < 2) + return false; + + bool changed = sourceBodies.Count != _bodies.Count; + if (!changed) + { + for (int i = 0; i < sourceBodies.Count; i++) + { + if (sourceBodies[i] != _bodies[i]) + { + changed = true; + break; + } + } + } + + if (changed) + { + _bodies.Clear(); + _bodies.AddRange(sourceBodies); + _needsRebuild = true; + } + + for (int i = 0; i < _bodies.Count; i++) + { + if (_bodies[i] == null) + return false; + } + + return true; + } + + private void EnsureSegmentStates() + { + int segmentCount = _bodies.Count - 1; + EnsureSegmentRendererCount(segmentCount); + + for (int segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) + { + VisualSegmentState state = _segments[segmentIndex]; + state.SegmentIndex = segmentIndex; + state.Renderer = GetOrCreateSegmentRenderer(segmentIndex, state); + + int subdivisions = GetVisualSubdivisionsForSegment(segmentIndex); + int pointCount = subdivisions + 1; + if (state.Points == null || + state.PointCount != pointCount || + state.Subdivisions != subdivisions || + _needsRebuild) + { + state.Subdivisions = subdivisions; + state.Points = new Vector3[pointCount]; + state.PrevPoints = new Vector3[pointCount]; + state.EdgeRestLengths = new float[subdivisions]; + state.SupportedPoints = new bool[pointCount]; + state.SmoothPoints = null; + state.SegmentPoints = null; + state.SmoothCapacity = 0; + state.SegmentCapacity = 0; + InitializeSegmentPoints(state); + } + } + + _needsRebuild = false; + } + + private void EnsureSegmentRendererCount(int segmentCount) + { + while (_segments.Count < segmentCount) + _segments.Add(new VisualSegmentState()); + + for (int i = _segments.Count - 1; i >= segmentCount; i--) + { + DestroySegmentRenderer(_segments[i]); + _segments.RemoveAt(i); + } + } + + private LineRenderer GetOrCreateSegmentRenderer(int segmentIndex, VisualSegmentState state) + { + if (segmentIndex == 0) + return _lineRenderer; + + if (state.Renderer != null) + return state.Renderer; + + string rendererName = SegmentRendererNamePrefix + segmentIndex; + GameObject rendererObject; + LineRenderer renderer; + + Transform child = transform.Find(rendererName); + if (child != null) + { + rendererObject = child.gameObject; + renderer = child.GetComponent(); + } + else + { + rendererObject = new GameObject(rendererName); + rendererObject.transform.SetParent(transform, false); + renderer = null; + } + + if (renderer == null) + renderer = rendererObject.AddComponent(); + + state.RendererObject = rendererObject; + state.Renderer = renderer; + ConfigureLineRenderer(renderer); + return renderer; + } + + private void DestroyExtraSegmentRenderers() + { + for (int i = 1; i < _segments.Count; i++) + DestroySegmentRenderer(_segments[i]); + } + + private void DestroySegmentRenderer(VisualSegmentState state) + { + if (state == null) + return; + + if (state.Renderer == _lineRenderer) + { + state.Renderer = null; + state.RendererObject = null; + return; + } + + GameObject rendererObject = state.RendererObject; + if (rendererObject == null && state.Renderer != null) + rendererObject = state.Renderer.gameObject; + + if (state.Renderer != null) + state.Renderer.positionCount = 0; + + state.Renderer = null; + state.RendererObject = null; + + if (rendererObject == null) + return; + + if (Application.isPlaying) + Destroy(rendererObject); + else + DestroyImmediate(rendererObject); + } + + private void InitializeSegmentPoints(VisualSegmentState state) + { + int subdivisions = Mathf.Max(1, state.Subdivisions); + Vector3 start = _bodies[state.SegmentIndex].position; + Vector3 end = _bodies[state.SegmentIndex + 1].position; + + for (int i = 0; i <= subdivisions; i++) + { + float t = i / (float)subdivisions; + Vector3 point = Vector3.Lerp(start, end, t); + state.Points[i] = point; + state.PrevPoints[i] = point; + state.SupportedPoints[i] = false; + } + + RefreshRestLengths(state); + } + + private void RefreshRestLengths() + { + for (int i = 0; i < _segments.Count; i++) + RefreshRestLengths(_segments[i]); + } + + private void RefreshRestLengths(VisualSegmentState state) + { + float currentDistance = Vector3.Distance( + _bodies[state.SegmentIndex].position, + _bodies[state.SegmentIndex + 1].position + ); + float maxLength = cable.GetSegmentMaxLength(state.SegmentIndex); + if (maxLength <= 0f) + maxLength = currentDistance; + + float visualRest = Mathf.Max(maxLength - visualLengthTrim, 0f); + float totalRest = Mathf.Max(visualRest, currentDistance); + float edgeRest = totalRest / Mathf.Max(1, state.Subdivisions); + + for (int i = 0; i < state.EdgeRestLengths.Length; i++) + state.EdgeRestLengths[i] = edgeRest; + } + + private void ConfigureLineRenderer(LineRenderer renderer) + { + if (renderer == null) + return; + + if (_lineRenderer != null && renderer != _lineRenderer) + CopyLineRendererTemplate(_lineRenderer, renderer); + + renderer.useWorldSpace = true; + renderer.loop = false; + renderer.startWidth = lineWidth; + renderer.endWidth = lineWidth; + } + + private void CopyLineRendererTemplate(LineRenderer template, LineRenderer target) + { + if (template == null || target == null || template == target) + return; + + target.alignment = template.alignment; + target.textureMode = template.textureMode; + target.shadowBias = template.shadowBias; + target.generateLightingData = template.generateLightingData; + target.numCapVertices = template.numCapVertices; + target.numCornerVertices = template.numCornerVertices; + target.startColor = template.startColor; + target.endColor = template.endColor; + target.colorGradient = template.colorGradient; + target.widthCurve = template.widthCurve; + target.widthMultiplier = template.widthMultiplier; + target.sharedMaterial = template.sharedMaterial; + target.sortingLayerID = template.sortingLayerID; + target.sortingOrder = template.sortingOrder; + target.shadowCastingMode = template.shadowCastingMode; + target.receiveShadows = template.receiveShadows; + target.enabled = template.enabled; + } + + private void SyncSegmentRendererStyles() + { + for (int i = 0; i < _segments.Count; i++) + ConfigureLineRenderer(_segments[i].Renderer); + } + + private void ClearLine() + { + if (_lineRenderer != null) + _lineRenderer.positionCount = 0; + + for (int i = 1; i < _segments.Count; i++) + { + LineRenderer renderer = _segments[i].Renderer; + if (renderer != null) + renderer.positionCount = 0; + } + } + + private void LockCableNodes() + { + for (int i = 0; i < _segments.Count; i++) + LockCableNodes(_segments[i]); + } + + private void LockCableNodes(VisualSegmentState state) + { + if (state.Points == null || state.PrevPoints == null || state.PointCount < 2) + return; + + int lastIndex = state.PointCount - 1; + Vector3 start = _bodies[state.SegmentIndex].position; + Vector3 end = _bodies[state.SegmentIndex + 1].position; + + state.Points[0] = start; + state.PrevPoints[0] = start; + state.SupportedPoints[0] = false; + + state.Points[lastIndex] = end; + state.PrevPoints[lastIndex] = end; + state.SupportedPoints[lastIndex] = false; + } + + private void SimulateFreePoints(float dt) + { + for (int i = 0; i < _segments.Count; i++) + SimulateFreePoints(_segments[i], dt); + } + + private void SimulateFreePoints(VisualSegmentState state, float dt) + { + if (state.PointCount <= 2) + return; + + float dt2 = dt * dt; + float maxDisp = maxPointSpeed > 0f ? maxPointSpeed * dt : float.PositiveInfinity; + float maxDispSq = maxDisp * maxDisp; + Vector3 gravity = Vector3.down * gravityStrength; + bool useWind = windResponse > 0f && windVelocity.sqrMagnitude > 0.0001f; + float chordLength = Vector3.Distance( + _bodies[state.SegmentIndex].position, + _bodies[state.SegmentIndex + 1].position + ); + float tautness = GetSegmentTautness(state.SegmentIndex, chordLength); + float mobility = 1f - tautness; + + for (int i = 1; i < state.PointCount - 1; i++) + { + if (state.SupportedPoints[i]) + { + state.PrevPoints[i] = state.Points[i]; + continue; + } + + Vector3 current = state.Points[i]; + Vector3 displacement = current - state.PrevPoints[i]; + if (maxPointSpeed > 0f && displacement.sqrMagnitude > maxDispSq) + displacement = displacement.normalized * maxDisp; + + displacement *= Mathf.Lerp(tautVelocityRetention, 1f, mobility); + + Vector3 acceleration = gravity; + if (useWind) + { + Vector3 velocity = displacement / dt; + Vector3 windAcceleration = (windVelocity - velocity) * windResponse; + if (maxWindAcceleration > 0f && + windAcceleration.sqrMagnitude > maxWindAcceleration * maxWindAcceleration) + windAcceleration = windAcceleration.normalized * maxWindAcceleration; + + acceleration += windAcceleration; + } + + acceleration *= mobility; + + state.PrevPoints[i] = current; + state.Points[i] = current + displacement * velocityDamping + acceleration * dt2; + } + } + + private void SolveDistanceConstraints() + { + float solveStiffness = Mathf.Clamp01(stiffness); + for (int i = 0; i < _segments.Count; i++) + SolveDistanceConstraints(_segments[i], solveStiffness); + } + + private void SolveDistanceConstraints(VisualSegmentState state, float solveStiffness) + { + if (state.EdgeRestLengths == null || state.EdgeRestLengths.Length == 0) + return; + + SolveSweep(state, 0, state.EdgeRestLengths.Length, 1, solveStiffness); + SolveSweep(state, state.EdgeRestLengths.Length - 1, -1, -1, solveStiffness); + } + + private void SolveSweep(VisualSegmentState state, int start, int endExclusive, int step, float solveStiffness) + { + float chordLength = Vector3.Distance(state.Points[0], state.Points[state.PointCount - 1]); + bool useMaxOnly = ShouldUseMaxOnlyConstraint(state.SegmentIndex, chordLength, state); + + for (int edge = start; edge != endExclusive; edge += step) + { + int aIndex = edge; + int bIndex = edge + 1; + Vector3 a = state.Points[aIndex]; + Vector3 b = state.Points[bIndex]; + Vector3 delta = b - a; + float sqrMagnitude = delta.sqrMagnitude; + if (sqrMagnitude < 1e-10f) + continue; + + float distance = Mathf.Sqrt(sqrMagnitude); + float rest = Mathf.Max(state.EdgeRestLengths[edge], MinDistance); + if (useMaxOnly && distance <= rest + lengthTolerance) + continue; + + float error = useMaxOnly ? Mathf.Max(distance - rest, 0f) : distance - rest; + Vector3 correction = delta * (error / distance * solveStiffness); + + bool aLocked = aIndex == 0; + bool bLocked = bIndex == state.PointCount - 1; + + if (!aLocked && !bLocked) + { + state.Points[aIndex] = a + correction * 0.5f; + state.Points[bIndex] = b - correction * 0.5f; + } + else if (aLocked && !bLocked) + { + state.Points[bIndex] = b - correction; + } + else if (!aLocked && bLocked) + { + state.Points[aIndex] = a + correction; + } + } + } + + private void ApplySurfaceConstraints() + { + if (!stopOnGround && !stopOnWaterSurface) + return; + + for (int i = 0; i < _segments.Count; i++) + ApplySurfaceConstraints(_segments[i]); + } + + private void ApplySurfaceConstraints(VisualSegmentState state) + { + if (state.PointCount <= 2) + return; + + for (int i = 0; i < state.SupportedPoints.Length; i++) + state.SupportedPoints[i] = false; + + for (int i = 1; i < state.PointCount - 1; i++) + { + float minY = SampleSurfaceMinY(state, i); + if (float.IsNegativeInfinity(minY)) + continue; + + Vector3 point = state.Points[i]; + if (point.y < minY) + { + point.y = minY; + state.Points[i] = point; + + Vector3 prev = state.PrevPoints[i]; + if (prev.y < minY) + { + prev.y = minY; + state.PrevPoints[i] = prev; + } + } + + if (state.Points[i].y <= minY + lengthTolerance) + state.SupportedPoints[i] = true; + } + } + + private void EnforceExactSegmentLengths() + { + for (int i = 0; i < _segments.Count; i++) + EnforceExactSegmentLengths(_segments[i]); + + ApplySurfaceConstraints(); + } + + private void EnforceExactSegmentLengths(VisualSegmentState state) + { + if (state.Subdivisions <= 1 || state.PointCount <= 2) + return; + + Vector3 start = state.Points[0]; + Vector3 end = state.Points[state.PointCount - 1]; + float chordLength = Vector3.Distance(start, end); + if (ShouldUseMaxOnlyConstraint(state.SegmentIndex, chordLength, state)) + return; + + float targetLength = GetTargetSegmentLength(state.SegmentIndex, chordLength); + float currentLength = ComputeSegmentLength(state); + if (currentLength <= targetLength + lengthTolerance) + return; + + float blend = FindSegmentCompressionBlend(state, start, end, targetLength); + ApplySegmentCompression(state, start, end, blend); + } + + private void StabilizeTautSegments() + { + for (int i = 0; i < _segments.Count; i++) + StabilizeTautSegments(_segments[i]); + + ApplySurfaceConstraints(); + } + + private void StabilizeTautSegments(VisualSegmentState state) + { + if (state.Subdivisions <= 1 || state.PointCount <= 2) + return; + + Vector3 start = state.Points[0]; + Vector3 end = state.Points[state.PointCount - 1]; + float chordLength = Vector3.Distance(start, end); + if (ShouldUseMaxOnlyConstraint(state.SegmentIndex, chordLength, state)) + return; + + float tautness = GetSegmentTautness(state.SegmentIndex, chordLength); + if (tautness <= 0f) + return; + + float positionBlend = tautPositionBlend * tautness; + bool fullyTaut = tautness >= 0.999f; + + for (int pointIndex = 1; pointIndex < state.PointCount - 1; pointIndex++) + { + float t = pointIndex / (float)state.Subdivisions; + Vector3 linear = Vector3.Lerp(start, end, t); + + if (fullyTaut) + { + state.Points[pointIndex] = linear; + state.PrevPoints[pointIndex] = linear; + continue; + } + + Vector3 stabilized = Vector3.Lerp(state.Points[pointIndex], linear, positionBlend); + state.Points[pointIndex] = stabilized; + state.PrevPoints[pointIndex] = Vector3.Lerp(state.PrevPoints[pointIndex], stabilized, positionBlend); + } + } + + private float ComputeSegmentLength(VisualSegmentState state) + { + float length = 0f; + for (int i = 0; i < state.PointCount - 1; i++) + length += Vector3.Distance(state.Points[i], state.Points[i + 1]); + + return length; + } + + private float FindSegmentCompressionBlend(VisualSegmentState state, Vector3 start, Vector3 end, + float targetLength) + { + float minBlend = 0f; + float maxBlend = 1f; + + for (int iteration = 0; iteration < 10; iteration++) + { + float midBlend = (minBlend + maxBlend) * 0.5f; + float midLength = ComputeCompressedSegmentLength(state, start, end, midBlend); + if (midLength > targetLength) + maxBlend = midBlend; + else + minBlend = midBlend; + } + + return minBlend; + } + + private float ComputeCompressedSegmentLength(VisualSegmentState state, Vector3 start, Vector3 end, float blend) + { + Vector3 previous = start; + float length = 0f; + + for (int pointIndex = 1; pointIndex < state.PointCount - 1; pointIndex++) + { + float t = pointIndex / (float)state.Subdivisions; + Vector3 linear = Vector3.Lerp(start, end, t); + Vector3 current = state.Points[pointIndex]; + Vector3 blended = Vector3.Lerp(linear, current, blend); + length += Vector3.Distance(previous, blended); + previous = blended; + } + + length += Vector3.Distance(previous, end); + return length; + } + + private void ApplySegmentCompression(VisualSegmentState state, Vector3 start, Vector3 end, float blend) + { + for (int pointIndex = 1; pointIndex < state.PointCount - 1; pointIndex++) + { + float t = pointIndex / (float)state.Subdivisions; + Vector3 linear = Vector3.Lerp(start, end, t); + Vector3 compressed = Vector3.Lerp(linear, state.Points[pointIndex], blend); + state.Points[pointIndex] = compressed; + state.PrevPoints[pointIndex] = compressed; + } + } + + private float SampleSurfaceMinY(VisualSegmentState state, int pointIndex) + { + Vector3 point = state.Points[pointIndex]; + float minY = float.NegativeInfinity; + + if (stopOnGround && groundMask.value != 0) + { + Vector3 origin = point + Vector3.up * groundCastHeight; + if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, groundCastDistance, groundMask, + QueryTriggerInteraction.Ignore)) + { + minY = Mathf.Max(minY, hit.point.y + groundRadius); + } + } + + if (stopOnWaterSurface && state.SegmentIndex == 0) + { + if (pointIndex > waterSurfaceIgnoreNodeCount && + pointIndex < state.PointCount - waterSurfaceIgnoreNodeCount) + minY = Mathf.Max(minY, waterLevelY + waterSurfaceOffset); + } + + return minY; + } + + private void ClearSupportedPoints() + { + for (int i = 0; i < _segments.Count; i++) + { + bool[] supportedPoints = _segments[i].SupportedPoints; + if (supportedPoints == null) + continue; + + for (int pointIndex = 0; pointIndex < supportedPoints.Length; pointIndex++) + supportedPoints[pointIndex] = false; + } + } + + private float GetTargetSegmentLength(int segmentIndex, float chordLength) + { + float maxLength = cable.GetSegmentMaxLength(segmentIndex); + if (maxLength <= 0f) + maxLength = chordLength; + + return Mathf.Max(maxLength - visualLengthTrim, chordLength); + } + + private float GetSegmentTautness(int segmentIndex, float chordLength) + { + float targetLength = GetTargetSegmentLength(segmentIndex, chordLength); + float slack = Mathf.Max(targetLength - chordLength, 0f); + if (tautSlackThreshold <= 0f) + return slack <= lengthTolerance ? 1f : 0f; + + return 1f - Mathf.Clamp01(slack / tautSlackThreshold); + } + + private bool ShouldUseMaxOnlyConstraint(int segmentIndex, float chordLength, VisualSegmentState state) + { + if (IsSegmentSupported(state)) + return true; + + return GetSegmentTautness(segmentIndex, chordLength) < 0.999f; + } + + private bool IsSegmentSupported(VisualSegmentState state) + { + if (state.SupportedPoints == null || state.PointCount <= 2) + return false; + + for (int i = 1; i < state.PointCount - 1; i++) + { + if (state.SupportedPoints[i]) + return true; + } + + return false; + } + + private int GetVisualSubdivisionsForSegment(int segmentIndex) + { + if (segmentIndex >= 0 && segmentIndex < visualSubdivisionsBySegment.Count) + { + int overrideValue = visualSubdivisionsBySegment[segmentIndex]; + if (overrideValue > 0) + return overrideValue; + } + + return Mathf.Max(1, visualSubdivisionsPerSegment); + } + + private void DrawLine() + { + SyncSegmentRendererStyles(); + + for (int i = 0; i < _segments.Count; i++) + DrawSegment(_segments[i]); + } + + private void DrawSegment(VisualSegmentState state) + { + LineRenderer renderer = state.Renderer; + if (renderer == null) + return; + + if (state.Points == null || state.PointCount < 2) + { + renderer.positionCount = 0; + return; + } + + if (!smoothLine || smoothingIterations <= 0 || state.PointCount <= 2) + { + ApplyRendererPositions(renderer, state.Points, state.PointCount); + return; + } + + int count = BuildSmoothedSegment(state); + ApplyRendererPositions(renderer, state.SegmentPoints, count); + } + + private int BuildSmoothedSegment(VisualSegmentState state) + { + int sourceCount = state.PointCount; + EnsureSegmentCapacity(state, sourceCount); + for (int i = 0; i < sourceCount; i++) + state.SegmentPoints[i] = state.Points[i]; + + Vector3[] source = state.SegmentPoints; + int segmentPointCount = sourceCount; + + for (int iteration = 0; iteration < smoothingIterations; iteration++) + { + int needed = segmentPointCount * 2; + Vector3[] target; + if (source == state.SegmentPoints) + { + EnsureSmoothCapacity(state, needed); + target = state.SmoothPoints; + } + else + { + EnsureSegmentCapacity(state, needed); + target = state.SegmentPoints; + } + + int index = 0; + target[index++] = source[0]; + + for (int i = 0; i < segmentPointCount - 1; i++) + { + Vector3 a = source[i]; + Vector3 b = source[i + 1]; + target[index++] = Vector3.Lerp(a, b, smoothingStrength); + target[index++] = Vector3.Lerp(a, b, 1f - smoothingStrength); + } + + target[index++] = source[segmentPointCount - 1]; + source = target; + segmentPointCount = index; + } + + if (source != state.SegmentPoints) + { + EnsureSegmentCapacity(state, segmentPointCount); + for (int i = 0; i < segmentPointCount; i++) + state.SegmentPoints[i] = source[i]; + } + + return segmentPointCount; + } + + private void EnsureSmoothCapacity(VisualSegmentState state, int needed) + { + if (state.SmoothPoints != null && state.SmoothCapacity >= needed) + return; + + state.SmoothCapacity = needed; + state.SmoothPoints = new Vector3[state.SmoothCapacity]; + } + + private void EnsureSegmentCapacity(VisualSegmentState state, int needed) + { + if (state.SegmentPoints != null && state.SegmentCapacity >= needed) + return; + + state.SegmentCapacity = needed; + state.SegmentPoints = new Vector3[state.SegmentCapacity]; + } + + private void ApplyRendererPositions(LineRenderer renderer, Vector3[] positions, int count) + { + if (renderer == null) + return; + + renderer.positionCount = count; + for (int i = 0; i < count; i++) + renderer.SetPosition(i, positions[i]); + } + + private void OnDrawGizmosSelected() + { + if (!drawVisualNodes) + return; + + for (int segmentIndex = 0; segmentIndex < _segments.Count; segmentIndex++) + { + VisualSegmentState state = _segments[segmentIndex]; + if (state.Points == null) + continue; + + for (int pointIndex = 0; pointIndex < state.PointCount; pointIndex++) + { + bool isLogicNode = pointIndex == 0 || pointIndex == state.PointCount - 1; + Gizmos.color = isLogicNode ? Color.yellow : Color.cyan; + Gizmos.DrawSphere(state.Points[pointIndex], gizmoNodeRadius); +#if UNITY_EDITOR + Handles.Label( + state.Points[pointIndex] + Vector3.up * gizmoNodeRadius, + $"{segmentIndex}:{pointIndex}" + ); +#endif + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs.meta b/Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs.meta new file mode 100644 index 000000000..952713181 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FLineRenderer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9e43f5ab12b64bb9a47c0c674a3177f2 +timeCreated: 1776960000 diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs b/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs new file mode 100644 index 000000000..c32341dc4 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs @@ -0,0 +1,349 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace NBF +{ + /// + /// 硬线系统测试脚本,直接读取 FLine 已配置的节点。 + /// + public class FLineTest : MonoBehaviour + { + [Header("测试控制")] [SerializeField] private KeyCode fixMiddleKey = KeyCode.M; + [SerializeField] private KeyCode applyForceKey = KeyCode.F; + [SerializeField] private Vector3 testForce = new Vector3(0f, 10f, 0f); + + [Header("动态间距控制")] + // [SerializeField] private KeyCode extendKey = KeyCode.UpArrow; + // [SerializeField] private KeyCode contractKey = KeyCode.DownArrow; + [SerializeField] + private KeyCode resetKey = KeyCode.Alpha0; + + [SerializeField] private KeyCode pullFirstKey = KeyCode.UpArrow; + [SerializeField] private KeyCode relaxFirstKey = KeyCode.DownArrow; + [SerializeField, Min(0.01f)] private float extendAmount = 0.5f; + [SerializeField, Min(0.01f)] private float holdAdjustSpeed = 1f; + [SerializeField, Min(0.01f)] private float transitionSpeed = 2f; + [SerializeField] private bool smoothTransition = true; + + [SerializeField] private FLine line; + private float[] initialLengths; + + private void OnValidate() + { + extendAmount = Mathf.Max(0.01f, extendAmount); + holdAdjustSpeed = Mathf.Max(0.01f, holdAdjustSpeed); + transitionSpeed = Mathf.Max(0.01f, transitionSpeed); + } + + private void Start() + { + RefreshInitialLengths(true); + line.OnLineBreakRequested += OnLineBreakRequested; + } + + private void OnLineBreakRequested(FLine lineSolver) + { + Debug.LogError($"当前拉力达到极限,切线,极限时间={lineSolver.LimitStateTime}"); + + var nodes = line.GetLineNodes(); + nodes[^1].Rigidbody.isKinematic = false; + // line.Body.isKinematic = false; + } + + private void Update() + { + if (!EnsureCable()) + return; + + RefreshInitialLengths(); + HandleInput(); + + if (line.CurrentBreakStretchPercent > 10f) + { + Debug.LogError( + $"当前极限情况,CurrentBreakStretchPercent={line.CurrentBreakStretchPercent} CurrentStretchLength={line.CurrentStretchLength} TotalLength={line.TotalLength} LimitStateTime={line.LimitStateTime}"); + } + } + + private bool EnsureCable() + { + if (line) + return true; + + line = GetComponent(); + return line != null; + } + + private List GetNodes() + { + return line != null ? line.GetLineNodes() : null; + } + + private void RefreshInitialLengths(bool force = false) + { + List nodes = GetNodes(); + int segmentCount = nodes != null ? Mathf.Max(0, nodes.Count - 1) : 0; + + if (!force && initialLengths != null && initialLengths.Length == segmentCount) + return; + + initialLengths = new float[segmentCount]; + for (int i = 0; i < segmentCount; i++) + { + float configuredLength = line.GetSegmentMaxLength(i); + if (configuredLength <= 0f) + configuredLength = Mathf.Max(0.01f, line.GetCurrentSegmentLength(i)); + + initialLengths[i] = Mathf.Max(0.01f, configuredLength); + } + } + + private float GetCurrentMaxLength(int segmentIndex) + { + float length = line.GetSegmentMaxLength(segmentIndex); + return Mathf.Max(0.01f, length); + } + + private float GetTargetMaxLength(int segmentIndex) + { + float length = line.GetTargetMaxLength(segmentIndex); + if (length <= 0f) + length = line.GetSegmentMaxLength(segmentIndex); + + return Mathf.Max(0.01f, length); + } + + private int GetSegmentCount() + { + return initialLengths != null ? initialLengths.Length : 0; + } + + private void HandleInput() + { + HandleOriginalControls(); + HandleDynamicDistanceControls(); + } + + private void HandleOriginalControls() + { + List nodes = GetNodes(); + if (nodes == null) + return; + + if (Input.GetKeyDown(fixMiddleKey) && nodes.Count >= 3) + { + int middleIndex = nodes.Count / 2; + FLineLogicNode middleNode = nodes[middleIndex]; + Rigidbody middleRb = middleNode ? middleNode.Rigidbody : null; + + if (middleNode && middleRb) + { + bool newState = !middleRb.isKinematic; + middleNode.SetFixed(newState); + Debug.Log($"中间节点({middleIndex}) {(newState ? "固定" : "释放")} - 观察其他节点变化"); + } + } + + if (Input.GetKeyDown(applyForceKey) && nodes.Count > 2) + { + int randomIndex = Random.Range(1, nodes.Count - 1); + FLineLogicNode targetNode = nodes[randomIndex]; + Rigidbody targetRb = targetNode ? targetNode.Rigidbody : null; + + if (targetNode && targetRb && !targetRb.isKinematic) + { + targetNode.ApplyForce(testForce, ForceMode.Impulse); + Debug.Log($"对节点{randomIndex}施加力: {testForce} - 观察传递效果"); + } + } + } + + private void HandleDynamicDistanceControls() + { + if (line == null || initialLengths == null || initialLengths.Length == 0) + return; + + // HandleLengthAdjustInput(); + + if (Input.GetKeyDown(resetKey)) + ResetAllSegments(); + + if (Input.GetKeyDown(pullFirstKey)) + PullFirstSegment(extendAmount * 0.5f); + + if (Input.GetKeyDown(relaxFirstKey)) + RelaxFirstSegment(extendAmount * 0.5f); + + if (Input.mouseScrollDelta.y != 0f && Input.GetKey(KeyCode.LeftShift)) + AdjustNearestSegment(Input.mouseScrollDelta.y * 0.1f); + } + + + private void ApplySegmentTargetLength(int segmentIndex, float targetLength) + { + line.SetSegmentMaxLength(segmentIndex, targetLength, transitionSpeed); + } + + private void ResetAllSegments() + { + for (int i = 0; i < GetSegmentCount(); i++) + { + ApplySegmentTargetLength(i, initialLengths[i]); + } + + Debug.Log("重置绳索到 FLine 初始节点配置"); + } + + private void PullFirstSegment(float amount) + { + if (GetSegmentCount() <= 0) + return; + + float targetLength = Mathf.Max(0.1f, GetTargetMaxLength(0) - amount); + ApplySegmentTargetLength(0, targetLength); + Debug.Log($"拉紧第一段到 {targetLength:F2}"); + } + + private void RelaxFirstSegment(float amount) + { + if (GetSegmentCount() <= 0) + return; + + float targetLength = GetTargetMaxLength(0) + amount; + ApplySegmentTargetLength(0, targetLength); + Debug.Log($"放松第一段到 {targetLength:F2}"); + } + + private void AdjustNearestSegment(float amount) + { + int nearestSegment = FindNearestSegmentToCamera(); + if (nearestSegment < 0 || nearestSegment >= GetSegmentCount()) + return; + + float targetLength = Mathf.Max(0.1f, GetTargetMaxLength(nearestSegment) + amount); + ApplySegmentTargetLength(nearestSegment, targetLength); + Debug.Log($"调整段{nearestSegment}到 {targetLength:F2}"); + } + + private int FindNearestSegmentToCamera() + { + Camera cam = Camera.main; + List nodes = GetNodes(); + if (cam == null || nodes == null || nodes.Count < 2) + return -1; + + int nearestSegment = -1; + float nearestDistance = float.MaxValue; + + for (int i = 0; i < nodes.Count - 1; i++) + { + Rigidbody bodyA = nodes[i] ? nodes[i].Rigidbody : null; + Rigidbody bodyB = nodes[i + 1] ? nodes[i + 1].Rigidbody : null; + if (!bodyA || !bodyB) + continue; + + Vector3 midPoint = (bodyA.position + bodyB.position) * 0.5f; + Vector3 screenPoint = cam.WorldToScreenPoint(midPoint); + Vector3 mousePos = Input.mousePosition; + + float distance = Vector2.Distance( + new Vector2(screenPoint.x, screenPoint.y), + new Vector2(mousePos.x, mousePos.y) + ); + + if (distance < nearestDistance) + { + nearestDistance = distance; + nearestSegment = i; + } + } + + return nearestSegment; + } + + private void OnGUI() + { + if (!EnsureCable()) + return; + + RefreshInitialLengths(); + + List nodes = GetNodes(); + int nodeCount = nodes != null ? nodes.Count : 0; + + GUILayout.BeginArea(new Rect(10f, 10f, 360f, 260f)); + GUILayout.Label("=== 硬线系统测试控制 ==="); + GUILayout.Label("原始控制:"); + GUILayout.Label($" {fixMiddleKey} - 固定/释放中间节点"); + GUILayout.Label($" {applyForceKey} - 随机施加力"); + GUILayout.Space(10f); + GUILayout.Label("动态间距控制:"); + GUILayout.Label($" {resetKey} - 重置到初始节点配置"); + GUILayout.Label($" {pullFirstKey} - 拉紧第一段"); + GUILayout.Label($" {relaxFirstKey} - 放松第一段"); + GUILayout.Label(" Shift+滚轮 - 调整最近段"); + GUILayout.Space(10f); + GUILayout.Label("设置:"); + GUILayout.Label($" 节点数: {nodeCount}"); + GUILayout.Label(" 初始长度来源: FLine 节点配置"); + GUILayout.Label($" 过渡模式: {(smoothTransition ? "平滑" : "即时")}"); + if (smoothTransition) + GUILayout.Label($" 过渡速度: {transitionSpeed:F1}"); + + GUILayout.EndArea(); + + GUILayout.BeginArea(new Rect(10f, 280f, 360f, 220f)); + GUILayout.Label("=== 各段实际长度 ==="); + + for (int i = 0; i < Mathf.Min(GetSegmentCount(), 10); i++) + { + Rigidbody bodyA = nodes[i] ? nodes[i].Rigidbody : null; + Rigidbody bodyB = nodes[i + 1] ? nodes[i + 1].Rigidbody : null; + if (!bodyA || !bodyB) + continue; + + float actualDistance = Vector3.Distance(bodyA.position, bodyB.position); + float currentLimit = GetCurrentMaxLength(i); + float targetLimit = GetTargetMaxLength(i); + + string segmentInfo = $"段{i}: {actualDistance:F2} (限制: {currentLimit:F2}"; + if (line.IsSegmentTransitioning(i)) + segmentInfo += $" -> {targetLimit:F2}"; + + segmentInfo += ")"; + + if (actualDistance > targetLimit * 1.1f) + { + GUI.color = Color.red; + } + else if (line.IsSegmentTransitioning(i)) + { + GUI.color = Color.yellow; + } + else + { + GUI.color = Color.green; + } + + GUILayout.Label(segmentInfo); + } + + GUI.color = Color.white; + + bool anyTransitioning = false; + for (int i = 0; i < GetSegmentCount(); i++) + { + if (line.IsSegmentTransitioning(i)) + { + anyTransitioning = true; + break; + } + } + + if (anyTransitioning) + GUILayout.Label("状态: 过渡中..."); + + GUILayout.EndArea(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs.meta b/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs.meta new file mode 100644 index 000000000..8ae29cbf1 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/FLineTest.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c2c33030c494448488a01acae5f2ba54 \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/Provider.meta b/Assets/Scripts/Fishing/New/View/FishingLine/Provider.meta new file mode 100644 index 000000000..0113b8800 --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/Provider.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 72431056211140f1bdbf95503df5f198 +timeCreated: 1777005389 \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs b/Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs new file mode 100644 index 000000000..fe7310f9f --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs @@ -0,0 +1,1539 @@ +using UnityEngine; + +namespace NBF +{ + /// + /// 简单水面接口。你可以替换成自己的水系统。 + /// + public interface IWaterSurfaceProvider + { + float GetWaterHeight(Vector3 worldPos); + Vector3 GetWaterNormal(Vector3 worldPos); + } + + /// + /// 浮漂控制模式: + /// 1. AirPhysics:空中/未入水,使用刚体物理 + /// 2. WaterPresentation:入水后,关闭重力,Y 和旋转由脚本控制 + /// + public enum BobberControlMode + { + AirPhysics, + WaterPresentation + } + + /// + /// 漂像事件类型 + /// + public enum BobberBiteType + { + None, + Tap, // 轻点:快速下顿再回弹 + MultiTap, // 连顿:连续多次下顿(鱼反复试探) + SlowSink, // 缓沉:分段下沉,中途短暂停顿 + Lift, // 送漂:上抬至高位后轻微晃动稳住 + BlackDrift, // 黑漂:快速深沉并水平拖拽 + Tremble // 微颤:高频小幅抖动(鱼在蹭饵试探) + } + + public enum BobberPosture + { + Lying, // 躺漂 + Tilted, // 斜漂 + Upright // 立漂 + } + + /// + /// 入水后的内部阶段,可供外部查询或驱动 UI/音效 + /// + public enum BobberWaterPhase + { + Settling, // 刚入水,正在稳定 + Stable, // 正常浮漂 + Biting // 漂像动画中 + } + + public struct BobberWaterConstraintState + { + public Vector3 TargetPosition; + public float PlanarStrength; + public float UpwardStrength; + public float DownwardStrength; + public float MaxCorrection; + } + + [DisallowMultipleComponent] + [RequireComponent(typeof(Rigidbody))] + public class FLineNodeBobberProvider : MonoBehaviour, IFLineNodeConstraintProvider + { + [Header("Water")] [Tooltip("没有水提供器时使用固定水位")] + public float fallbackWaterLevel = 0f; + + + [Tooltip("可选:挂实现了 IWaterSurfaceProvider 的组件")] + public MonoBehaviour waterProviderBehaviour; + + [Header("Enter Water")] [Tooltip("底部进入水面多少米后切换为漂像控制")] + public float enterWaterDepth = 0.002f; + + [Tooltip("离开水面多少米后回到空中物理。一般给负值做滞回")] public float exitWaterDepth = -0.01f; + + [Header("Entry Animation")] [Tooltip("入水瞬间的初始下顿深度(米),形成自然入水感")] + public float entryDipAmplitude = 0.012f; + + [Tooltip("入水稳定动画总时长(秒)")] public float entrySettleDuration = 0.8f; + + [Header("Air Hang")] [Tooltip("悬空时是否让浮漂长轴自然沿重力方向下挂")] + public bool enableAirHangRotation = true; + + [Tooltip("悬空下垂旋转的跟随速度")] public float airHangRotationSpeed = 10f; + + [Tooltip("悬空时,上方支撑方向对平面朝向的影响权重。0=只看重力下垂,1=更多参考上方线段")] [Range(0f, 1f)] + public float airHangLineInfluence = 0.75f; + + [Tooltip("悬空时优先让刚体本地重心方向朝向重力下方;重心方向不可用时才使用下面的手动轴")] + public bool preferAirHangCenterOfMass = true; + + [UnityEngine.Serialization.FormerlySerializedAs("airHangUpAxisLocal")] [Tooltip("悬空时,浮漂本地哪个轴代表朝向底部/重心的长轴方向")] + public Vector3 airHangDownAxisLocal = Vector3.down; + + [Tooltip("悬空时,用于确定绕长轴朝向的本地参考前向")] public Vector3 airHangForwardAxisLocal = Vector3.forward; + + [Header("Geometry")] [Tooltip("浮漂总高度(米)")] + public float floatHeight = 0.08f; + + [Tooltip("如果 Pivot 在浮漂底部,这里填 0;如果 Pivot 在模型中心,就填底部相对 Pivot 的本地 Y")] + public float bottomOffsetLocalY = 0f; + + [Header("Base Float")] [Tooltip("基础吃铅比例,决定静止时有多少在水下")] [Range(0.05f, 0.95f)] + public float baseSubmergeRatio = 0.28f; + + [Tooltip("Y 轴平滑时间,越小响应越快")] public float ySmoothTime = 0.08f; + + [Tooltip("最大竖直速度限制(用于 SmoothDamp)")] public float maxYSpeed = 2f; + + [Tooltip("静止小死区,减少微抖")] public float yDeadZone = 0.0005f; + + [Header("Surface Motion")] [Tooltip("是否启用轻微水面起伏")] + public bool enableSurfaceBobbing = true; + + [Tooltip("主水面起伏振幅(米)")] public float surfaceBobAmplitude = 0.0015f; + + [Tooltip("主水面起伏频率(Hz)")] public float surfaceBobFrequency = 1.2f; + + [Tooltip("次级起伏振幅比例(主振幅的倍率),使用黄金比例频率增加自然感")] [Range(0f, 1f)] + public float surfaceBobSecondaryRatio = 0.35f; + + [Header("XZ Motion")] [Tooltip("入水后是否锁定 XZ 到入水点附近")] + public bool lockXZAroundAnchor = true; + + [Tooltip("XZ 跟随平滑时间")] public float xzSmoothTime = 0.15f; + + [Tooltip("水流/拖拽带来的额外平面偏移最大值")] public float maxPlanarOffset = 0.15f; + + [Tooltip("移漂默认持续推力时间(秒)")] public float driftForceDuration = 0.45f; + + [Header("Water Constraint")] [Tooltip("接入 FLine 自定义约束时,使用求解器驱动水面目标,而不是脚本直接写世界坐标")] + public bool useSolverWaterConstraint = true; + + [Tooltip("水面对目标 XZ 的平面跟随强度")] [Range(0f, 1f)] + public float waterConstraintPlanarStrength = 0.12f; + + [Tooltip("浮漂低于目标水位时,向上托回去的强度")] [Range(0f, 1f)] + public float waterConstraintUpwardStrength = 0.35f; + + [Tooltip("浮漂高于目标水位时,向下拉回去的强度。建议明显小于向上强度,这样鱼线才能把它拉出水面")] [Range(0f, 1f)] + public float waterConstraintDownwardStrength = 0.05f; + + [Tooltip("每次约束迭代允许的最大修正位移(米)")] public float waterConstraintMaxCorrection = 0.01f; + + [Header("Sink By Weight / Tension")] [Tooltip("外部向下拉力映射为下沉量的系数。你可以把钩/铅/线组的等效向下拉力喂进来")] + public float downForceToSink = 0.0025f; + + [Tooltip("向下拉力下沉的最大附加量")] public float maxExtraSink = 0.08f; + + [Header("Bottom Touch")] [Tooltip("触底时是否启用修正")] + public bool enableBottomTouchAdjust = true; + + [Tooltip("触底后减少的下沉量(铅坠到底,漂会回升一点)")] public float bottomTouchLift = 0.01f; + + [Header("Posture Source")] [Tooltip("下方 Lure / 钩组 / 铅坠的刚体。姿态主要根据它和浮漂的相对位置判断")] + public Rigidbody lureBody; + + [Tooltip("用于归一化的参考长度。一般填:浮漂到 Lure 在正常拉直时的大致长度")] + public float referenceLength = 0.30f; + + [Header("Posture Threshold")] [Tooltip("最小入水比例。不够时优先躺漂")] + public float minSubmergeToStand = 0.16f; + + [Tooltip("垂直分量比低于该值时,优先躺漂")] public float verticalLieThreshold = 0.18f; + + [Tooltip("垂直分量比高于该值,且水平分量较小时,允许立漂")] public float verticalUprightThreshold = 0.75f; + + [Tooltip("水平分量比高于该值时,不允许完全立漂")] public float planarTiltThreshold = 0.30f; + + [Tooltip("水平分量明显大于垂直分量时,优先躺漂")] public float planarDominanceMultiplier = 1.20f; + + [Tooltip("姿态切换滞回,防止边界抖动")] public float postureHysteresis = 0.04f; + + [Header("Posture Stability")] [Tooltip("候选姿态需持续多久才真正切换")] + public float postureConfirmTime = 0.08f; + + [Tooltip("姿态切换后的最短冷却时间,避免来回闪烁")] public float postureSwitchCooldown = 0.10f; + + [Header("Posture Rotation")] [Tooltip("斜漂角度")] + public float tiltedAngle = 38f; + + [Tooltip("躺漂角度")] public float lyingAngle = 88f; + + [Tooltip("立漂时,平面拉力可附加的最大倾角(度)")] public float uprightMaxTiltAngle = 8f; + + [Tooltip("平面拉力对立漂附加倾角的灵敏度(度/ratio)。值越大,斜向拉力对立漂的影响越明显")] + public float planarTiltFactor = 120f; + + [Tooltip("平面方向死区,小于该值时保持上一帧方向")] public float planarDirectionDeadZone = 0.01f; + + [Tooltip("平面方向平滑速度")] public float planarDirectionLerpSpeed = 10f; + + [Tooltip("最终旋转 Slerp 速度")] public float rotationLerpSpeed = 8f; + + [Header("Posture Blend")] [Tooltip("躺漂 ↔ 斜漂 角度过渡平滑时间")] + public float postureBlendSmoothTime = 0.15f; + + [Tooltip("斜漂 ↔ 立漂 角度过渡平滑时间(通常稍慢,立漂更庄重)")] + public float postureBlendSmoothTimeUpright = 0.22f; + + [Header("Posture Wobble")] [Tooltip("姿态切换时是否启用旋转回弹抖动")] + public bool enablePostureWobble = true; + + [Tooltip("切换触发的旋转抖动初始角速度(度/秒)")] public float postureWobbleStrength = 10f; + + [Tooltip("旋转抖动弹簧衰减速率。越大衰减越快,值等于 sqrt(k) 的临界阻尼系数")] + public float postureWobbleDecay = 7f; + + [Header("Debug Input")] [Tooltip("调试:按 R 停止漂像")] + public bool debugResetKey = true; + + [Tooltip("调试:按 T 触发轻点")] public bool debugTapKey = true; + + [Tooltip("调试:按 Y 触发连顿")] public bool debugMultiTapKey = true; + + [Tooltip("调试:按 G 触发缓沉")] public bool debugSlowSinkKey = true; + + [Tooltip("调试:按 H 触发送漂")] public bool debugLiftKey = true; + + [Tooltip("调试:按 B 触发黑漂")] public bool debugBlackDriftKey = true; + + [Tooltip("调试:按 V 触发微颤")] public bool debugTrembleKey = true; + + [Tooltip("调试:按 N 触发移漂(向 transform.forward 移动 0.1m)")] + public bool debugDriftKey = true; + + [Header("Debug")] public bool drawDebug = false; + + public bool UseTestPosture; + public BobberPosture TestPosture; + + // ── 只读公开状态 ────────────────────────────────────────────── + public BobberControlMode CurrentMode => _mode; + public BobberPosture CurrentPosture => _posture; + public BobberWaterPhase CurrentWaterPhase => _waterPhase; + public float CurrentVerticalRatio => _verticalRatio; + public float CurrentPlanarRatio => _planarRatio; + public bool UsesSolverWaterConstraint => useSolverWaterConstraint && _logicNode != null; + + /// 连续姿态混合值:0=躺漂, 1=斜漂, 2=立漂。可直接驱动外部动画混合树。 + public float PostureBlendValue => _postureBlendValue; + + // ── 外部可写输入 ─────────────────────────────────────────────── + /// 等效向下拉力(不必须是真实力,作为输入信号即可) + public float ExternalDownForce { get; set; } + + /// 是否触底 + public bool IsBottomTouched { get; set; } + + /// 额外平面偏移(例如风、水流、拖拽) + public Vector2 ExternalPlanarOffset { get; set; } + + // ── 事件 ────────────────────────────────────────────────────── + /// 姿态切换完成时触发:(旧姿态, 新姿态) + public event System.Action OnPostureChanged; + + public bool TryGetWaterConstraintState(out BobberWaterConstraintState state) + { + state = default; + + if (!UsesSolverWaterConstraint || _mode != BobberControlMode.WaterPresentation) + return false; + + state.TargetPosition = _constraintTargetPosition; + state.PlanarStrength = Mathf.Clamp01(waterConstraintPlanarStrength); + state.UpwardStrength = Mathf.Clamp01(waterConstraintUpwardStrength); + state.DownwardStrength = Mathf.Clamp01(waterConstraintDownwardStrength); + state.MaxCorrection = Mathf.Max(0f, waterConstraintMaxCorrection); + return true; + } + + public bool TryGetConstraintState(out FLineNodeConstraintState state) + { + state = default; + + if (!TryGetWaterConstraintState(out BobberWaterConstraintState waterState)) + return false; + + state.TargetPosition = waterState.TargetPosition; + state.PlanarStrength = waterState.PlanarStrength; + state.UpwardStrength = waterState.UpwardStrength; + state.DownwardStrength = waterState.DownwardStrength; + state.MaxCorrection = waterState.MaxCorrection; + return true; + } + + // ── 核心私有字段 ─────────────────────────────────────────────── + private Rigidbody _rb; + private FLineLogicNode _logicNode; + private IWaterSurfaceProvider _waterProvider; + private BobberControlMode _mode = BobberControlMode.AirPhysics; + private BobberPosture _posture = BobberPosture.Lying; + private BobberWaterPhase _waterPhase = BobberWaterPhase.Stable; + + private float _defaultLinearDamping; + private float _defaultAngularDamping; + private bool _defaultUseGravity; + + private Vector3 _waterAnchorPos; + private Vector3 _xzSmoothVelocity; + private float _ySmoothVelocity; + + private float _biteOffsetY; + private float _biteOffsetYVelocity; + private Quaternion _targetRotation; + private Vector3 _constraintTargetPosition; + + // 漂像运行时 + private BobberBiteType _activeBiteType = BobberBiteType.None; + private float _biteTimer; + private float _biteDuration; + private float _biteAmplitude; + private Vector3 _blackDriftDirection; + private int _multiTapTotalCount; + private float _trembleRuntimeFreq = 10f; + + // 姿态判断运行时 + private float _verticalRatio; + private float _planarRatio; + private float _verticalDistance; + private float _planarDistance; + private BobberPosture _pendingPosture; + private float _pendingPostureTimer; + private float _postureCooldownTimer; + private Vector3 _stablePlanarDir = Vector3.forward; + + // 姿态平滑混合(0=躺, 1=斜, 2=立) + private float _postureBlendValue; + private float _postureBlendVelocity; + + // 旋转回弹弹簧(spring-damper) + private float _rotWobble; + private float _rotWobbleVel; + + // 入水稳定动画 + private float _entrySettleTimer; + private float _entrySettleOffsetY; + + // 移漂运行时:驱动水面锚点在 XZ 平面移动到目标距离后停下 + private bool _isDriftForceActive; + private Vector3 _driftStartAnchorPos; + private Vector3 _driftForceDirection; + private float _driftForceTimer; + private float _driftForceDuration; + + // 水面起伏实例随机相位 + private float _bobPhaseOffset; + + // Crest 波面查询 + private bool _hasCrestSampleThisFrame; + private readonly Vector3[] _waterQueryPoints = new Vector3[1]; + private readonly Vector3[] _waterQueryResultDisplacements = new Vector3[1]; + private readonly Vector3[] _waterQueryResultVelocities = new Vector3[1]; + private readonly Vector3[] _waterQueryResultNormal = new Vector3[1]; + + private void Awake() + { + _rb = GetComponent(); + _logicNode = GetComponent(); + + _defaultLinearDamping = _rb.linearDamping; + _defaultAngularDamping = _rb.angularDamping; + _defaultUseGravity = _rb.useGravity; + + if (waterProviderBehaviour != null) + _waterProvider = waterProviderBehaviour as IWaterSurfaceProvider; + + _pendingPosture = _posture; + _pendingPostureTimer = 0f; + _postureCooldownTimer = 0f; + + _stablePlanarDir = Vector3.ProjectOnPlane(transform.forward, Vector3.up); + if (_stablePlanarDir.sqrMagnitude < 1e-6f) _stablePlanarDir = Vector3.forward; + else _stablePlanarDir.Normalize(); + + _targetRotation = transform.rotation; + _constraintTargetPosition = transform.position; + _postureBlendValue = PostureToBlend(_posture); + + // 随机相位,避免多个浮漂同步起伏 + _bobPhaseOffset = Random.value * Mathf.PI * 2f; + } + + private void Update() + { + HandleDebugKeys(); + } + + private void FixedUpdate() + { + float waterY = GetWaterHeight(transform.position); + Vector3 bottomWorld = GetBottomWorldPosition(); + float submergeDepth = waterY - bottomWorld.y; + + switch (_mode) + { + case BobberControlMode.AirPhysics: + UpdateAirPhysics(waterY, submergeDepth); + break; + case BobberControlMode.WaterPresentation: + UpdateWaterPresentation(waterY, submergeDepth); + break; + } + + if (drawDebug) + DrawDebug(waterY); + } + + #region Main Update + + private void UpdateAirPhysics(float waterY, float submergeDepth) + { + RestoreAirPhysicsState(); + UpdateAirHangRotation(); + + if (submergeDepth > enterWaterDepth) + EnterWaterPresentationMode(waterY); + } + + private void UpdateWaterPresentation(float waterY, float submergeDepth) + { + if (submergeDepth < exitWaterDepth) + { + ExitWaterPresentationMode(); + return; + } + + if (UsesSolverWaterConstraint) + { + UpdateSolverDrivenWaterPresentation(waterY); + return; + } + + // 入水后由脚本/约束统一驱动目标位姿,刚体速度压制掉避免额外干扰 + _rb.useGravity = false; + _rb.linearVelocity = Vector3.zero; + _rb.angularVelocity = Vector3.zero; + _rb.linearDamping = 999f; + _rb.angularDamping = 999f; + + TickWaterPresentationState(); + + Vector3 pos = transform.position; + + // 1. 目标 Y + float targetY = CalculateTargetY(waterY); + + if (Mathf.Abs(pos.y - targetY) < yDeadZone) + { + pos.y = targetY; + _ySmoothVelocity = 0f; + } + else + { + pos.y = Mathf.SmoothDamp( + pos.y, targetY, + ref _ySmoothVelocity, + Mathf.Max(0.0001f, ySmoothTime), + maxYSpeed, + Time.fixedDeltaTime + ); + } + + // 2. 目标 XZ + Vector3 targetXZ = CalculateTargetXZ(); + Vector3 planarPos = new Vector3(pos.x, 0f, pos.z); + Vector3 planarTarget = new Vector3(targetXZ.x, 0f, targetXZ.z); + + planarPos = Vector3.SmoothDamp( + planarPos, planarTarget, + ref _xzSmoothVelocity, + Mathf.Max(0.0001f, xzSmoothTime), + Mathf.Infinity, + Time.fixedDeltaTime + ); + pos.x = planarPos.x; + pos.z = planarPos.z; + + transform.position = pos; + _constraintTargetPosition = pos; + + UpdateWaterPresentationRotation(waterY); + } + + private void UpdateSolverDrivenWaterPresentation(float waterY) + { + _rb.useGravity = false; + _rb.angularVelocity = Vector3.zero; + _rb.linearDamping = _defaultLinearDamping; + _rb.angularDamping = _defaultAngularDamping; + + TickWaterPresentationState(); + UpdateConstraintTargetPosition(waterY); + UpdateWaterPresentationRotation(waterY); + } + + private void TickWaterPresentationState() + { + if (_entrySettleTimer > 0f) + { + _entrySettleTimer -= Time.fixedDeltaTime; + if (_entrySettleTimer <= 0f) + { + _entrySettleTimer = 0f; + _waterPhase = _activeBiteType != BobberBiteType.None + ? BobberWaterPhase.Biting + : BobberWaterPhase.Stable; + } + } + + UpdateBiteAnimation(); + UpdateDriftForce(); + UpdateRotationWobble(); + } + + private void UpdateConstraintTargetPosition(float waterY) + { + Vector3 pos = _constraintTargetPosition; + + float targetY = CalculateTargetY(waterY); + if (Mathf.Abs(pos.y - targetY) < yDeadZone) + { + pos.y = targetY; + _ySmoothVelocity = 0f; + } + else + { + pos.y = Mathf.SmoothDamp( + pos.y, targetY, + ref _ySmoothVelocity, + Mathf.Max(0.0001f, ySmoothTime), + maxYSpeed, + Time.fixedDeltaTime + ); + } + + Vector3 targetXZ = CalculateTargetXZ(); + Vector3 planarPos = new Vector3(pos.x, 0f, pos.z); + Vector3 planarTarget = new Vector3(targetXZ.x, 0f, targetXZ.z); + + planarPos = Vector3.SmoothDamp( + planarPos, planarTarget, + ref _xzSmoothVelocity, + Mathf.Max(0.0001f, xzSmoothTime), + Mathf.Infinity, + Time.fixedDeltaTime + ); + + pos.x = planarPos.x; + pos.z = planarPos.z; + _constraintTargetPosition = pos; + } + + private void UpdateWaterPresentationRotation(float waterY) + { + EvaluatePostureByComponents(waterY); + UpdateTargetRotationByPosture(); + + transform.rotation = Quaternion.Slerp( + transform.rotation, + _targetRotation, + 1f - Mathf.Exp(-rotationLerpSpeed * Time.fixedDeltaTime) + ); + } + + #endregion + + #region Mode Switch + + private void EnterWaterPresentationMode(float waterY) + { + _mode = BobberControlMode.WaterPresentation; + + _waterAnchorPos = transform.position; + _constraintTargetPosition = transform.position; + _ySmoothVelocity = 0f; + _xzSmoothVelocity = Vector3.zero; + _biteOffsetY = 0f; + _biteOffsetYVelocity = 0f; + _activeBiteType = BobberBiteType.None; + _biteTimer = 0f; + + // 启动入水稳定动画 + _entrySettleTimer = Mathf.Max(0f, entrySettleDuration); + _entrySettleOffsetY = CalculateInitialEntrySettleOffset(waterY); + _waterPhase = BobberWaterPhase.Settling; + + // 重置姿态至躺漂 + _posture = BobberPosture.Lying; + _verticalRatio = 0f; + _planarRatio = 0f; + _verticalDistance = 0f; + _planarDistance = 0f; + _pendingPosture = _posture; + _pendingPostureTimer = 0f; + _postureCooldownTimer = 0f; + _postureBlendValue = PostureToBlend(_posture); + _postureBlendVelocity = 0f; + + // 重置旋转弹簧 + _rotWobble = 0f; + _rotWobbleVel = 0f; + + // 重置移漂 + _isDriftForceActive = false; + _driftStartAnchorPos = _waterAnchorPos; + _driftForceDirection = Vector3.zero; + _driftForceTimer = 0f; + _driftForceDuration = 0f; + + _stablePlanarDir = Vector3.ProjectOnPlane(transform.forward, Vector3.up); + if (_stablePlanarDir.sqrMagnitude < 1e-6f) _stablePlanarDir = Vector3.forward; + else _stablePlanarDir.Normalize(); + + _rb.useGravity = false; + _rb.linearVelocity = Vector3.zero; + _rb.angularVelocity = Vector3.zero; + _rb.linearDamping = 999f; + _rb.angularDamping = 999f; + } + + private void ExitWaterPresentationMode() + { + _mode = BobberControlMode.AirPhysics; + _waterPhase = BobberWaterPhase.Stable; + _constraintTargetPosition = transform.position; + _entrySettleOffsetY = 0f; + RestoreAirPhysicsState(); + } + + private void RestoreAirPhysicsState() + { + _rb.useGravity = _defaultUseGravity; + _rb.linearDamping = _defaultLinearDamping; + _rb.angularDamping = _defaultAngularDamping; + } + + private void UpdateAirHangRotation() + { + if (!enableAirHangRotation || !_rb || _rb.isKinematic) + return; + + Vector3 gravity = Physics.gravity; + if (gravity.sqrMagnitude < 1e-6f) + return; + + Vector3 gravityDown = gravity.normalized; + Vector3 gravityUp = -gravityDown; + + Vector3 supportUp = gravityUp; + bool hasUpperSupport = TryGetAirHangSupportDirection(gravityUp, out supportUp); + + Vector3 targetDown = gravityDown; + + Vector3 forwardHint = Vector3.zero; + if (hasUpperSupport) + { + Vector3 supportPlanar = Vector3.ProjectOnPlane(supportUp, targetDown); + if (supportPlanar.sqrMagnitude > 1e-6f) + { + supportPlanar.Normalize(); + + Vector3 stablePlanar = Vector3.ProjectOnPlane(_stablePlanarDir, targetDown); + if (stablePlanar.sqrMagnitude < 1e-6f) + stablePlanar = supportPlanar; + else + stablePlanar.Normalize(); + + forwardHint = Vector3.Slerp(stablePlanar, supportPlanar, Mathf.Clamp01(airHangLineInfluence)); + } + } + + if (forwardHint.sqrMagnitude < 1e-6f) + forwardHint = Vector3.ProjectOnPlane(_stablePlanarDir, targetDown); + + if (forwardHint.sqrMagnitude < 1e-6f) + forwardHint = Vector3.ProjectOnPlane(transform.forward, targetDown); + + if (forwardHint.sqrMagnitude < 1e-6f) + forwardHint = Vector3.ProjectOnPlane(Vector3.forward, targetDown); + + if (forwardHint.sqrMagnitude < 1e-6f) + forwardHint = Vector3.ProjectOnPlane(Vector3.right, targetDown); + + forwardHint.Normalize(); + + if (_stablePlanarDir.sqrMagnitude > 1e-6f && Vector3.Dot(forwardHint, _stablePlanarDir) < 0f) + forwardHint = -forwardHint; + + Vector3 localDown = ResolveAirHangDownAxisLocal(); + Quaternion targetRotation = BuildAxisAlignedRotation(targetDown, forwardHint, localDown); + float blend = 1f - Mathf.Exp(-Mathf.Max(0.01f, airHangRotationSpeed) * Time.fixedDeltaTime); + Quaternion nextRotation = Quaternion.Slerp(_rb.rotation, targetRotation, blend); + + _rb.angularVelocity = Vector3.zero; + _rb.MoveRotation(nextRotation); + + Vector3 projectedForward = Vector3.ProjectOnPlane(nextRotation * Vector3.forward, targetDown); + if (projectedForward.sqrMagnitude > 1e-6f) + _stablePlanarDir = projectedForward.normalized; + } + + private bool TryGetAirHangSupportDirection(Vector3 gravityUp, out Vector3 supportUp) + { + supportUp = gravityUp; + + if (_logicNode == null || + !_logicNode.TryGetAdjacentBodies(out Rigidbody previousBody, out Rigidbody nextBody)) + return false; + + Vector3 currentPos = _rb.worldCenterOfMass; + Vector3 upperDirection = Vector3.zero; + float bestUpperDot = float.NegativeInfinity; + + TryConsumeNeighbor(previousBody, currentPos, gravityUp, ref upperDirection, ref bestUpperDot); + TryConsumeNeighbor(nextBody, currentPos, gravityUp, ref upperDirection, ref bestUpperDot); + + if (upperDirection.sqrMagnitude > 1e-6f && bestUpperDot > 0.05f) + { + supportUp = upperDirection; + return true; + } + + return false; + } + + private static void TryConsumeNeighbor( + Rigidbody neighborBody, + Vector3 currentPos, + Vector3 gravityUp, + ref Vector3 upperDirection, + ref float bestUpperDot) + { + if (!neighborBody) + return; + + Vector3 toNeighbor = neighborBody.worldCenterOfMass - currentPos; + if (toNeighbor.sqrMagnitude < 1e-6f) + return; + + Vector3 dir = toNeighbor.normalized; + float upDot = Vector3.Dot(dir, gravityUp); + if (upDot > bestUpperDot) + { + bestUpperDot = upDot; + upperDirection = dir; + } + } + + private Vector3 ResolveAirHangDownAxisLocal() + { + if (preferAirHangCenterOfMass && _rb) + { + Vector3 centerOfMassLocal = _rb.centerOfMass; + if (centerOfMassLocal.sqrMagnitude > 1e-6f) + return centerOfMassLocal.normalized; + } + + return airHangDownAxisLocal.sqrMagnitude > 1e-6f + ? airHangDownAxisLocal.normalized + : Vector3.down; + } + + private Quaternion BuildAxisAlignedRotation(Vector3 targetDown, Vector3 forwardHint, Vector3 localDownAxis) + { + Vector3 safeDown = targetDown.sqrMagnitude > 1e-6f ? targetDown.normalized : Vector3.down; + Vector3 safeUp = -safeDown; + Vector3 safeForward = Vector3.ProjectOnPlane(forwardHint, safeDown); + if (safeForward.sqrMagnitude < 1e-6f) + safeForward = Vector3.ProjectOnPlane(Vector3.forward, safeDown); + if (safeForward.sqrMagnitude < 1e-6f) + safeForward = Vector3.ProjectOnPlane(Vector3.right, safeDown); + safeForward.Normalize(); + + Vector3 localDown = localDownAxis.sqrMagnitude > 1e-6f ? localDownAxis.normalized : Vector3.down; + Vector3 localUp = -localDown; + Vector3 localForward = Vector3.ProjectOnPlane(airHangForwardAxisLocal, localDown); + if (localForward.sqrMagnitude < 1e-6f) + localForward = Vector3.ProjectOnPlane(Vector3.forward, localDown); + if (localForward.sqrMagnitude < 1e-6f) + localForward = Vector3.ProjectOnPlane(Vector3.right, localDown); + localForward.Normalize(); + + Quaternion worldBasis = Quaternion.LookRotation(safeForward, safeUp); + Quaternion localBasis = Quaternion.LookRotation(localForward, localUp); + return worldBasis * Quaternion.Inverse(localBasis); + } + + private float CalculateInitialEntrySettleOffset(float waterY) + { + float baseTargetY = CalculateBaseTargetY(waterY); + float currentOffset = Mathf.Min(0f, transform.position.y - baseTargetY); + float configuredDip = -Mathf.Max(0f, entryDipAmplitude); + return Mathf.Min(currentOffset, configuredDip); + } + + #endregion + + #region Target Calculation + + private float CalculateTargetY(float waterY) + { + float targetPivotY = CalculateBaseTargetY(waterY); + + if (_entrySettleTimer <= 0f || entrySettleDuration <= 0f) + return targetPivotY; + + float phase = 1f - Mathf.Clamp01(_entrySettleTimer / Mathf.Max(0.001f, entrySettleDuration)); + float riseT = Mathf.SmoothStep(0f, 1f, phase); + return targetPivotY + Mathf.Lerp(_entrySettleOffsetY, 0f, riseT); + } + + private float CalculateBaseTargetY(float waterY) + { + float baseSinkDepth = floatHeight * Mathf.Clamp01(baseSubmergeRatio); + + float sinkByForce = Mathf.Clamp( + ExternalDownForce * downForceToSink, + 0f, maxExtraSink + ); + + float bottomAdjust = 0f; + if (enableBottomTouchAdjust && IsBottomTouched) + bottomAdjust -= bottomTouchLift; + + // 多层水面起伏:主波 + 次波(黄金比例频率),各实例相位随机 + float surfaceBob = 0f; + if (enableSurfaceBobbing && !_hasCrestSampleThisFrame) + { + float t = Time.time; + float primary = Mathf.Sin(t * surfaceBobFrequency * Mathf.PI * 2f + _bobPhaseOffset) + * surfaceBobAmplitude; + float secondary = Mathf.Sin(t * surfaceBobFrequency * 1.618f * Mathf.PI * 2f + _bobPhaseOffset * 2.1f) + * surfaceBobAmplitude * surfaceBobSecondaryRatio; + surfaceBob = primary + secondary; + } + + float totalSink = baseSinkDepth + sinkByForce + bottomAdjust; + float targetBottomY = waterY - totalSink; + float targetPivotY = targetBottomY - bottomOffsetLocalY + surfaceBob + _biteOffsetY; + + return targetPivotY; + } + + private Vector3 CalculateTargetXZ() + { + Vector2 planarOffset = Vector2.ClampMagnitude(ExternalPlanarOffset, maxPlanarOffset); + Vector3 basePos = lockXZAroundAnchor || _isDriftForceActive + ? _waterAnchorPos + : transform.position; + + if (_activeBiteType == BobberBiteType.BlackDrift) + { + float t = Mathf.Clamp01(_biteDuration > 0f ? _biteTimer / _biteDuration : 1f); + float drift = Mathf.SmoothStep(0f, 1f, t) * 0.08f; + Vector3 bd = _blackDriftDirection * drift; + basePos += new Vector3(bd.x, 0f, bd.z); + } + + return new Vector3( + basePos.x + planarOffset.x, + transform.position.y, + basePos.z + planarOffset.y + ); + } + + private void EvaluatePostureByComponents(float waterY) + { + float submergeRatio = Mathf.Clamp01( + (waterY - GetBottomWorldPosition().y) / Mathf.Max(0.0001f, floatHeight) + ); + + bool hasLure = lureBody != null; + + if (!hasLure) + { + _verticalDistance = 0f; + _planarDistance = 0f; + _verticalRatio = 0f; + _planarRatio = 0f; + } + else + { + Vector3 bobberPos = _rb.worldCenterOfMass; + Vector3 lurePos = lureBody.worldCenterOfMass; + Vector3 delta = lurePos - bobberPos; + + _verticalDistance = Mathf.Max(0f, Vector3.Dot(delta, Vector3.down)); + _planarDistance = Vector3.ProjectOnPlane(delta, Vector3.up).magnitude; + + float refLen = Mathf.Max(0.0001f, referenceLength); + _verticalRatio = _verticalDistance / refLen; + _planarRatio = _planarDistance / refLen; + } + + BobberPosture desired = DeterminePostureState(submergeRatio, hasLure); + ApplyPostureWithStability(desired); + } + + /// + /// 姿态状态判断的唯一入口。改规则只改这里,外部负责数据采样和旋转平滑。 + /// + private BobberPosture DeterminePostureState(float submergeRatio, bool hasLure) + { + if (UseTestPosture) + return TestPosture; + + // 无 Lure 时的兜底规则 + if (!hasLure) + { + if (submergeRatio < minSubmergeToStand) + return BobberPosture.Lying; + if (ExternalPlanarOffset.magnitude > 0.01f) + return BobberPosture.Tilted; + return BobberPosture.Upright; + } + + // 带滞回的状态机:从当前状态出发,减少来回切换 + switch (_posture) + { + case BobberPosture.Lying: + { + bool canStandUpright = + submergeRatio >= minSubmergeToStand && + _verticalRatio > verticalUprightThreshold + postureHysteresis && + _planarRatio < planarTiltThreshold - postureHysteresis; + + bool canTilt = + submergeRatio >= minSubmergeToStand * 0.8f && + _verticalRatio > verticalLieThreshold + postureHysteresis; + + if (canStandUpright) return BobberPosture.Upright; + if (canTilt) return BobberPosture.Tilted; + return BobberPosture.Lying; + } + + case BobberPosture.Tilted: + { + bool shouldLie = + submergeRatio < minSubmergeToStand * 0.75f || + _verticalRatio < verticalLieThreshold - postureHysteresis || + _planarDistance > _verticalDistance * planarDominanceMultiplier; + + bool shouldStand = + submergeRatio >= minSubmergeToStand && + _verticalRatio > verticalUprightThreshold + postureHysteresis && + _planarRatio < planarTiltThreshold - postureHysteresis; + + if (shouldLie) return BobberPosture.Lying; + if (shouldStand) return BobberPosture.Upright; + return BobberPosture.Tilted; + } + + default: // Upright + { + bool shouldLie = + submergeRatio < minSubmergeToStand * 0.75f || + _verticalRatio < verticalLieThreshold - postureHysteresis || + _planarDistance > _verticalDistance * (planarDominanceMultiplier + 0.15f); + + bool shouldTilt = + _verticalRatio < verticalUprightThreshold - postureHysteresis || + _planarRatio > planarTiltThreshold + postureHysteresis; + + if (shouldLie) return BobberPosture.Lying; + if (shouldTilt) return BobberPosture.Tilted; + return BobberPosture.Upright; + } + } + } + + private void ApplyPostureWithStability(BobberPosture desiredPosture) + { + _postureCooldownTimer = Mathf.Max(0f, _postureCooldownTimer - Time.fixedDeltaTime); + + if (desiredPosture == _posture) + { + _pendingPosture = _posture; + _pendingPostureTimer = 0f; + return; + } + + if (_postureCooldownTimer > 0f) + { + _pendingPosture = desiredPosture; + _pendingPostureTimer = 0f; + return; + } + + if (_pendingPosture != desiredPosture) + { + _pendingPosture = desiredPosture; + _pendingPostureTimer = 0f; + return; + } + + _pendingPostureTimer += Time.fixedDeltaTime; + if (_pendingPostureTimer >= Mathf.Max(0f, postureConfirmTime)) + { + BobberPosture oldPosture = _posture; + _posture = desiredPosture; + _pendingPosture = _posture; + _pendingPostureTimer = 0f; + _postureCooldownTimer = Mathf.Max(0f, postureSwitchCooldown); + + OnPostureTransition(oldPosture, _posture); + } + } + + /// + /// 姿态切换完成时:触发外部事件,并向弹簧注入回弹初速。 + /// + private void OnPostureTransition(BobberPosture from, BobberPosture to) + { + OnPostureChanged?.Invoke(from, to); + + if (!enablePostureWobble) return; + + // (int)Lying=0 < Tilted=1 < Upright=2 + // 向更立漂方向切换 → 角度减小 → 初始抖动为负(先过冲再弹回) + // 向更躺漂方向切换 → 角度增大 → 初始抖动为正 + float sign = (int)to > (int)from ? -1f : 1f; + _rotWobbleVel += sign * postureWobbleStrength; + } + + private void UpdateTargetRotationByPosture() + { + // ── 更新平面稳定方向 ──────────────────────────────────────── + Vector3 candidateDir = Vector3.zero; + + if (lureBody != null) + candidateDir = Vector3.ProjectOnPlane( + lureBody.worldCenterOfMass - _rb.worldCenterOfMass, Vector3.up); + + if (candidateDir.sqrMagnitude < 1e-6f) + candidateDir = new Vector3(_xzSmoothVelocity.x, 0f, _xzSmoothVelocity.z); + + if (candidateDir.sqrMagnitude < 1e-6f) + candidateDir = new Vector3(ExternalPlanarOffset.x, 0f, ExternalPlanarOffset.y); + + if (_stablePlanarDir.sqrMagnitude < 1e-6f) + { + _stablePlanarDir = Vector3.ProjectOnPlane(transform.forward, Vector3.up); + if (_stablePlanarDir.sqrMagnitude < 1e-6f) _stablePlanarDir = Vector3.forward; + } + + _stablePlanarDir.Normalize(); + + float dirDeadZone = Mathf.Max(0.0001f, planarDirectionDeadZone); + if (candidateDir.sqrMagnitude > dirDeadZone * dirDeadZone) + { + candidateDir.Normalize(); + + // 避免 180° 翻转闪烁 + if (Vector3.Dot(candidateDir, _stablePlanarDir) < 0f) + candidateDir = -candidateDir; + + float k = 1f - Mathf.Exp(-Mathf.Max(0.01f, planarDirectionLerpSpeed) * Time.fixedDeltaTime); + _stablePlanarDir = Vector3.Slerp(_stablePlanarDir, candidateDir, k); + _stablePlanarDir.Normalize(); + } + + // ── 姿态混合值平滑(0=躺, 1=斜, 2=立)────────────────────── + float targetBlend = PostureToBlend(_posture); + + // 躺↔斜 用较短时间,斜↔立 用较长时间(立漂更稳重) + bool involveUpright = (_postureBlendValue > 1f) || (targetBlend > 1f); + float blendTime = involveUpright ? postureBlendSmoothTimeUpright : postureBlendSmoothTime; + + _postureBlendValue = Mathf.SmoothDamp( + _postureBlendValue, targetBlend, + ref _postureBlendVelocity, + Mathf.Max(0.001f, blendTime), + Mathf.Infinity, + Time.fixedDeltaTime + ); + + // ── 从混合值计算目标倾角 ──────────────────────────────────── + float baseAngle; + if (_postureBlendValue <= 1f) + { + // 躺漂(lyingAngle) ↔ 斜漂(tiltedAngle) + baseAngle = Mathf.Lerp(lyingAngle, tiltedAngle, _postureBlendValue); + } + else + { + // 斜漂(tiltedAngle) ↔ 立漂(uprightTilt) + // 立漂时根据平面拉力给出微小附加倾角,planarTiltFactor 控制灵敏度 + float uprightTilt = Mathf.Clamp(_planarRatio * planarTiltFactor, 0f, uprightMaxTiltAngle); + baseAngle = Mathf.Lerp(tiltedAngle, uprightTilt, _postureBlendValue - 1f); + } + + // 叠加旋转回弹抖动 + float finalAngle = baseAngle + _rotWobble; + + // ── 构建目标旋转 ───────────────────────────────────────────── + Vector3 tiltAxis = Vector3.Cross(Vector3.up, _stablePlanarDir); + if (tiltAxis.sqrMagnitude < 1e-6f) + tiltAxis = transform.right; + + _targetRotation = Quaternion.AngleAxis(finalAngle, tiltAxis.normalized); + } + + /// + /// 临界阻尼弹簧:k = decay², damper = 2*decay,每帧调用以衰减旋转抖动。 + /// + private void UpdateRotationWobble() + { + if (Mathf.Abs(_rotWobble) < 0.01f && Mathf.Abs(_rotWobbleVel) < 0.01f) + { + _rotWobble = 0f; + _rotWobbleVel = 0f; + return; + } + + float d = Mathf.Max(0.01f, postureWobbleDecay); + float spring = -(d * d) * _rotWobble; + float damper = -(2f * d) * _rotWobbleVel; + + _rotWobbleVel += (spring + damper) * Time.fixedDeltaTime; + _rotWobble += _rotWobbleVel * Time.fixedDeltaTime; + } + + #endregion + + #region Bite Presentation + + /// 轻点:快速下顿再回弹 + public void PlayTap(float amplitude = 0.008f, float duration = 0.18f) + { + StartBite(BobberBiteType.Tap, amplitude, duration); + } + + /// 连顿:count 次连续下顿,每顿之间轻微回弹,振幅略微衰减 + public void PlayMultiTap(int count = 3, float amplitude = 0.006f, float intervalPerTap = 0.22f) + { + _multiTapTotalCount = Mathf.Max(1, count); + StartBite(BobberBiteType.MultiTap, amplitude, intervalPerTap * _multiTapTotalCount); + } + + /// 缓沉:分段下沉,40% 处有短暂停顿感(鱼吞饵试探) + public void PlaySlowSink(float amplitude = 0.025f, float duration = 1.2f) + { + StartBite(BobberBiteType.SlowSink, amplitude, duration); + } + + /// 送漂:快速上抬至峰值,之后轻微振荡稳住 + public void PlayLift(float amplitude = 0.015f, float duration = 1.2f) + { + StartBite(BobberBiteType.Lift, amplitude, duration); + } + + /// 黑漂:快速深沉并可配合平面拖拽 + public void PlayBlackDrift(float amplitude = 0.06f, float duration = 0.8f, Vector3? driftDirection = null) + { + StartBite(BobberBiteType.BlackDrift, amplitude, duration); + _blackDriftDirection = (driftDirection ?? transform.forward).normalized; + } + + /// 微颤:高频小幅抖动,振幅随时间衰减(鱼蹭饵试探) + public void PlayTremble(float amplitude = 0.004f, float duration = 1.5f, float frequency = 10f) + { + _trembleRuntimeFreq = Mathf.Max(1f, frequency); + StartBite(BobberBiteType.Tremble, amplitude, duration); + } + + /// 移漂:按给定世界方向在 XZ 平面平移指定距离。 + public void PlayDrift(Vector3 direction, float distance) + { + PlayDrift(direction, distance, driftForceDuration); + } + + /// 移漂:沿给定方向在 XZ 平面移动指定距离,并在目标点停下。 + public void PlayDrift(Vector3 direction, float distance, float duration) + { + if (_mode != BobberControlMode.WaterPresentation) + return; + + Vector3 planarDirection = Vector3.ProjectOnPlane(direction, Vector3.up); + if (planarDirection.sqrMagnitude < 1e-6f || Mathf.Approximately(distance, 0f)) + return; + + float safeDuration = Mathf.Max(0.02f, duration); + + SyncWaterAnchorToCurrentXZ(); + + _driftStartAnchorPos = _waterAnchorPos; + _driftForceDirection = planarDirection.normalized * distance; + _driftForceTimer = 0f; + _driftForceDuration = safeDuration; + _isDriftForceActive = true; + _xzSmoothVelocity = Vector3.zero; + } + + public void StopDrift() + { + _isDriftForceActive = false; + _driftForceTimer = 0f; + _driftForceDuration = 0f; + _driftForceDirection = Vector3.zero; + _xzSmoothVelocity = Vector3.zero; + SyncWaterAnchorToCurrentXZ(); + } + + public void StopBite() + { + _activeBiteType = BobberBiteType.None; + _biteTimer = 0f; + _biteDuration = 0f; + _biteAmplitude = 0f; + _biteOffsetY = 0f; + _biteOffsetYVelocity = 0f; + + if (_waterPhase == BobberWaterPhase.Biting) + _waterPhase = BobberWaterPhase.Stable; + } + + private void UpdateDriftForce() + { + if (!_isDriftForceActive) + return; + + _driftForceTimer += Time.fixedDeltaTime; + float t = Mathf.Clamp01(_driftForceTimer / Mathf.Max(0.0001f, _driftForceDuration)); + float easedT = Mathf.SmoothStep(0f, 1f, t); + _waterAnchorPos = _driftStartAnchorPos + _driftForceDirection * easedT; + + if (t < 1f) + return; + + _waterAnchorPos = _driftStartAnchorPos + _driftForceDirection; + _isDriftForceActive = false; + _driftForceTimer = 0f; + _driftForceDuration = 0f; + _driftForceDirection = Vector3.zero; + _xzSmoothVelocity = Vector3.zero; + } + + private void StartBite(BobberBiteType type, float amplitude, float duration) + { + if (_mode != BobberControlMode.WaterPresentation) + return; + + _activeBiteType = type; + _biteTimer = 0f; + _biteDuration = Mathf.Max(0.01f, duration); + _biteAmplitude = amplitude; + _biteOffsetYVelocity = 0f; + + if (type == BobberBiteType.BlackDrift && _blackDriftDirection.sqrMagnitude < 1e-6f) + _blackDriftDirection = transform.forward.sqrMagnitude > 1e-6f + ? transform.forward.normalized + : Vector3.forward; + + if (_waterPhase != BobberWaterPhase.Settling) + _waterPhase = BobberWaterPhase.Biting; + } + + private void UpdateBiteAnimation() + { + if (_activeBiteType == BobberBiteType.None) + { + _biteOffsetY = Mathf.SmoothDamp( + _biteOffsetY, 0f, + ref _biteOffsetYVelocity, + 0.08f, Mathf.Infinity, Time.fixedDeltaTime + ); + return; + } + + _biteTimer += Time.fixedDeltaTime; + float t = Mathf.Clamp01(_biteTimer / _biteDuration); + float targetOffset = 0f; + + switch (_activeBiteType) + { + case BobberBiteType.Tap: + { + // 前 35% 快速下顿,后 65% 回弹 + targetOffset = t < 0.35f + ? -Mathf.SmoothStep(0f, _biteAmplitude, t / 0.35f) + : -Mathf.Lerp(_biteAmplitude, 0f, (t - 0.35f) / 0.65f); + break; + } + + case BobberBiteType.MultiTap: + { + // 每顿时间均分,每顿内模拟单次 Tap 曲线,振幅随顿次轻微衰减 + int totalTaps = Mathf.Max(1, _multiTapTotalCount); + float tapLength = 1f / totalTaps; + float cycleT = Mathf.Repeat(t, tapLength) / tapLength; + float tapIndex = Mathf.Floor(t / tapLength); + float decay = 1f - tapIndex / totalTaps * 0.25f; // 末顿约 75% 振幅 + + targetOffset = cycleT < 0.35f + ? -Mathf.SmoothStep(0f, _biteAmplitude * decay, cycleT / 0.35f) + : -Mathf.Lerp(_biteAmplitude * decay, 0f, (cycleT - 0.35f) / 0.65f); + break; + } + + case BobberBiteType.SlowSink: + { + // 三段式缓沉:0~40% 渐沉至一半,40~60% 短暂停顿,60~100% 继续下沉 + float sinkOffset; + if (t < 0.4f) + sinkOffset = Mathf.SmoothStep(0f, _biteAmplitude * 0.5f, t / 0.4f); + else if (t < 0.6f) + sinkOffset = _biteAmplitude * 0.5f; + else + sinkOffset = Mathf.SmoothStep(_biteAmplitude * 0.5f, _biteAmplitude, (t - 0.6f) / 0.4f); + targetOffset = -sinkOffset; + break; + } + + case BobberBiteType.Lift: + { + // 前 60% 平滑送起,60%~100% 顶部轻微振荡后稳住 + if (t < 0.6f) + { + targetOffset = Mathf.SmoothStep(0f, _biteAmplitude, t / 0.6f); + } + else + { + float wobbleT = (t - 0.6f) / 0.4f; + float wobble = Mathf.Sin(wobbleT * Mathf.PI * 3f) + * _biteAmplitude * 0.12f * (1f - wobbleT); + targetOffset = _biteAmplitude + wobble; + } + + break; + } + + case BobberBiteType.BlackDrift: + { + // 前 60% 快速深沉,之后维持最大深度 + float sinkT = Mathf.SmoothStep(0f, 1f, Mathf.Min(t / 0.6f, 1f)); + targetOffset = -_biteAmplitude * sinkT; + break; + } + + case BobberBiteType.Tremble: + { + // 高频振荡,振幅线性衰减至 0 + float decay2 = 1f - t; + targetOffset = Mathf.Sin(Time.time * _trembleRuntimeFreq * Mathf.PI * 2f) + * _biteAmplitude * decay2; + break; + } + } + + // Tremble 需要快速响应,其余用标准平滑时间 + float smoothTime = _activeBiteType == BobberBiteType.Tremble ? 0.01f : 0.03f; + _biteOffsetY = Mathf.SmoothDamp( + _biteOffsetY, targetOffset, + ref _biteOffsetYVelocity, + smoothTime, Mathf.Infinity, Time.fixedDeltaTime + ); + + // 持续类漂像(缓沉/黑漂)到达终点后不自动结束,等外部调用 StopBite + if (_biteTimer >= _biteDuration) + { + if (_activeBiteType == BobberBiteType.SlowSink || + _activeBiteType == BobberBiteType.BlackDrift) + return; + + _activeBiteType = BobberBiteType.None; + if (_waterPhase == BobberWaterPhase.Biting) + _waterPhase = BobberWaterPhase.Stable; + } + } + + #endregion + + #region Utilities + + private static float PostureToBlend(BobberPosture posture) => posture switch + { + BobberPosture.Lying => 0f, + BobberPosture.Tilted => 1f, + _ => 2f + }; + + private float GetWaterHeight(Vector3 worldPos) + { + if (_waterProvider != null) + { + _hasCrestSampleThisFrame = false; + return _waterProvider.GetWaterHeight(worldPos); + } + + _hasCrestSampleThisFrame = false; + return fallbackWaterLevel; + } + + private Vector3 GetBottomWorldPosition() + { + return transform.TransformPoint(new Vector3(0f, bottomOffsetLocalY, 0f)); + } + + private void SyncWaterAnchorToCurrentXZ() + { + Vector2 planarOffset = Vector2.ClampMagnitude(ExternalPlanarOffset, maxPlanarOffset); + Vector3 pos = transform.position; + _waterAnchorPos = new Vector3( + pos.x - planarOffset.x, + _waterAnchorPos.y, + pos.z - planarOffset.y + ); + } + + private void HandleDebugKeys() + { + if (!Application.isPlaying) return; + + if (debugResetKey && Input.GetKeyDown(KeyCode.R)) StopBite(); + if (debugTapKey && Input.GetKeyDown(KeyCode.T)) PlayTap(); + if (debugMultiTapKey && Input.GetKeyDown(KeyCode.Y)) PlayMultiTap(); + if (debugSlowSinkKey && Input.GetKeyDown(KeyCode.G)) PlaySlowSink(); + if (debugLiftKey && Input.GetKeyDown(KeyCode.H)) PlayLift(); + if (debugBlackDriftKey && Input.GetKeyDown(KeyCode.B)) PlayBlackDrift(); + if (debugTrembleKey && Input.GetKeyDown(KeyCode.V)) PlayTremble(); + if (debugDriftKey && Input.GetKeyDown(KeyCode.N)) PlayDrift(transform.forward, 0.1f); + } + + private void DrawDebug(float waterY) + { + Vector3 p = transform.position; + Vector3 b = GetBottomWorldPosition(); + + Debug.DrawLine( + new Vector3(p.x - 0.05f, waterY, p.z), + new Vector3(p.x + 0.05f, waterY, p.z), + Color.cyan + ); + Debug.DrawLine(b, b + Vector3.up * floatHeight, Color.yellow); + + if (_mode == BobberControlMode.AirPhysics && enableAirHangRotation) + { + Vector3 hangDown = transform.TransformDirection(ResolveAirHangDownAxisLocal()); + Debug.DrawLine(p, p + hangDown * 0.08f, Color.gray); + } + + if (_mode == BobberControlMode.WaterPresentation) + { + Vector3 a = _waterAnchorPos; + Debug.DrawLine(a + Vector3.left * 0.03f, a + Vector3.right * 0.03f, Color.green); + Debug.DrawLine(a + Vector3.forward * 0.03f, a + Vector3.back * 0.03f, Color.green); + + // 姿态混合值可视化:白线高度代表 PostureBlendValue(0~2) + Debug.DrawLine(p, p + Vector3.up * (_postureBlendValue * 0.02f), Color.white); + + if (UsesSolverWaterConstraint) + { + Debug.DrawLine(p, _constraintTargetPosition, Color.cyan); + Debug.DrawLine( + _constraintTargetPosition + Vector3.left * 0.02f, + _constraintTargetPosition + Vector3.right * 0.02f, + Color.cyan + ); + } + } + + if (lureBody != null) + { + Vector3 bobber = _rb.worldCenterOfMass; + Vector3 lure = lureBody.worldCenterOfMass; + Debug.DrawLine(bobber, lure, Color.magenta); + + Vector3 verticalEnd = bobber + Vector3.down * _verticalDistance; + Debug.DrawLine(bobber, verticalEnd, Color.red); + + Vector3 planar = Vector3.ProjectOnPlane(lure - bobber, Vector3.up); + Debug.DrawLine(verticalEnd, verticalEnd + planar, Color.blue); + } + } + +#if UNITY_EDITOR + private void OnValidate() + { + floatHeight = Mathf.Max(0.001f, floatHeight); + airHangRotationSpeed = Mathf.Max(0.01f, airHangRotationSpeed); + airHangLineInfluence = Mathf.Clamp01(airHangLineInfluence); + ySmoothTime = Mathf.Max(0.001f, ySmoothTime); + maxYSpeed = Mathf.Max(0.01f, maxYSpeed); + xzSmoothTime = Mathf.Max(0.001f, xzSmoothTime); + driftForceDuration = Mathf.Max(0.02f, driftForceDuration); + waterConstraintMaxCorrection = Mathf.Max(0f, waterConstraintMaxCorrection); + rotationLerpSpeed = Mathf.Max(0.01f, rotationLerpSpeed); + maxPlanarOffset = Mathf.Max(0f, maxPlanarOffset); + waterConstraintPlanarStrength = Mathf.Clamp01(waterConstraintPlanarStrength); + waterConstraintUpwardStrength = Mathf.Clamp01(waterConstraintUpwardStrength); + waterConstraintDownwardStrength = Mathf.Clamp01(waterConstraintDownwardStrength); + downForceToSink = Mathf.Max(0f, downForceToSink); + maxExtraSink = Mathf.Max(0f, maxExtraSink); + surfaceBobAmplitude = Mathf.Max(0f, surfaceBobAmplitude); + surfaceBobFrequency = Mathf.Max(0f, surfaceBobFrequency); + surfaceBobSecondaryRatio = Mathf.Clamp01(surfaceBobSecondaryRatio); + yDeadZone = Mathf.Max(0f, yDeadZone); + + if (airHangDownAxisLocal.sqrMagnitude < 1e-6f) + airHangDownAxisLocal = Vector3.down; + + if (airHangForwardAxisLocal.sqrMagnitude < 1e-6f) + airHangForwardAxisLocal = Vector3.forward; + + referenceLength = Mathf.Max(0.0001f, referenceLength); + minSubmergeToStand = Mathf.Clamp01(minSubmergeToStand); + verticalLieThreshold = Mathf.Clamp(verticalLieThreshold, 0f, 2f); + verticalUprightThreshold = Mathf.Max(verticalLieThreshold, verticalUprightThreshold); + planarTiltThreshold = Mathf.Clamp(planarTiltThreshold, 0f, 2f); + planarDominanceMultiplier = Mathf.Max(0.1f, planarDominanceMultiplier); + postureHysteresis = Mathf.Clamp(postureHysteresis, 0f, 0.3f); + postureConfirmTime = Mathf.Max(0f, postureConfirmTime); + postureSwitchCooldown = Mathf.Max(0f, postureSwitchCooldown); + + tiltedAngle = Mathf.Clamp(tiltedAngle, 0f, 89f); + lyingAngle = Mathf.Clamp(lyingAngle, tiltedAngle, 89.9f); + uprightMaxTiltAngle = Mathf.Clamp(uprightMaxTiltAngle, 0f, tiltedAngle); + planarTiltFactor = Mathf.Max(0f, planarTiltFactor); + planarDirectionDeadZone = Mathf.Max(0.0001f, planarDirectionDeadZone); + planarDirectionLerpSpeed = Mathf.Max(0.01f, planarDirectionLerpSpeed); + + postureBlendSmoothTime = Mathf.Max(0.001f, postureBlendSmoothTime); + postureBlendSmoothTimeUpright = Mathf.Max(0.001f, postureBlendSmoothTimeUpright); + postureWobbleStrength = Mathf.Max(0f, postureWobbleStrength); + postureWobbleDecay = Mathf.Max(0.01f, postureWobbleDecay); + entryDipAmplitude = Mathf.Max(0f, entryDipAmplitude); + entrySettleDuration = Mathf.Max(0f, entrySettleDuration); + } +#endif + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs.meta b/Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs.meta new file mode 100644 index 000000000..1c78c24ed --- /dev/null +++ b/Assets/Scripts/Fishing/New/View/FishingLine/Provider/FLineNodeBobberProvider.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5ff7196c0f1441d4807ea7be8f921eb6 +timeCreated: 1777011145 \ No newline at end of file diff --git a/Assets/Scripts/Test/New/SimpleWaterSurfaceProvider.cs b/Assets/Scripts/Fishing/New/View/FishingLine/SimpleWaterSurfaceProvider.cs similarity index 90% rename from Assets/Scripts/Test/New/SimpleWaterSurfaceProvider.cs rename to Assets/Scripts/Fishing/New/View/FishingLine/SimpleWaterSurfaceProvider.cs index 6d110dba4..164112b3e 100644 --- a/Assets/Scripts/Test/New/SimpleWaterSurfaceProvider.cs +++ b/Assets/Scripts/Fishing/New/View/FishingLine/SimpleWaterSurfaceProvider.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using NBF; +using UnityEngine; public class SimpleWaterSurfaceProvider : MonoBehaviour, IWaterSurfaceProvider { diff --git a/Assets/Scripts/Test/New/SimpleWaterSurfaceProvider.cs.meta b/Assets/Scripts/Fishing/New/View/FishingLine/SimpleWaterSurfaceProvider.cs.meta similarity index 100% rename from Assets/Scripts/Test/New/SimpleWaterSurfaceProvider.cs.meta rename to Assets/Scripts/Fishing/New/View/FishingLine/SimpleWaterSurfaceProvider.cs.meta diff --git a/Assets/Scripts/Fishing/New/View/Player/Mono/JointPinchController.cs b/Assets/Scripts/Fishing/New/View/Player/Mono/JointPinchController.cs index 3b644dd5c..bf8ef4ac7 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Mono/JointPinchController.cs +++ b/Assets/Scripts/Fishing/New/View/Player/Mono/JointPinchController.cs @@ -20,7 +20,7 @@ namespace NBF public bool isPinched { get; private set; } - + private bool moveToTargetDone; private float _speed; @@ -44,11 +44,6 @@ namespace NBF } } - private void LateUpdate() - { - // SyncPosition(); - } - private void Update() { SyncPosition(); diff --git a/Assets/Scripts/Fishing/New/View/Player/States/IPlayerThrowAnimation.cs b/Assets/Scripts/Fishing/New/View/Player/States/IPlayerThrowAnimation.cs index 06a3a7ee7..c87320901 100644 --- a/Assets/Scripts/Fishing/New/View/Player/States/IPlayerThrowAnimation.cs +++ b/Assets/Scripts/Fishing/New/View/Player/States/IPlayerThrowAnimation.cs @@ -13,7 +13,7 @@ namespace NBF public struct ThrowAnimationRequest { - public LureController Lure; + public FLineLogicNode Lure; public Vector3 ThrowOriginPosition; public Vector3 StartPosition; public Vector3 Forward; diff --git a/Assets/Scripts/Fishing/New/View/Player/States/ParabolaPlayerThrowAnimation.cs b/Assets/Scripts/Fishing/New/View/Player/States/ParabolaPlayerThrowAnimation.cs index 1d0195944..afe4470a0 100644 --- a/Assets/Scripts/Fishing/New/View/Player/States/ParabolaPlayerThrowAnimation.cs +++ b/Assets/Scripts/Fishing/New/View/Player/States/ParabolaPlayerThrowAnimation.cs @@ -22,7 +22,7 @@ namespace NBF private float _castElapsedTime; private Vector3 _castStartPos; private Vector3 _castTargetPos; - private LureController _castingLure; + private FLineLogicNode _castingLure; public bool IsPlaying => _castingLure != null; @@ -51,7 +51,7 @@ namespace NBF _chargedProgress = Mathf.Clamp01(request.ChargedProgress); _castElapsedTime = 0f; - var lureBody = request.Lure.RBody; + var lureBody = request.Lure.Rigidbody; _castStartPos = request.StartPosition; Vector3 forward = GetHorizontalForward(request.Forward); @@ -81,7 +81,7 @@ namespace NBF return; } - var lureBody = _castingLure.RBody; + var lureBody = _castingLure.Rigidbody; if (snapToTarget) { _castingLure.transform.position = _castTargetPos; @@ -150,4 +150,4 @@ namespace NBF return position; } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewBase.cs b/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewBase.cs index 98d5c68b9..5b3cb6daa 100644 --- a/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewBase.cs +++ b/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewBase.cs @@ -101,9 +101,11 @@ namespace NBF var handItemView = Player.HandItem.GetComponent(); if (handItemView != null && handItemView.Rod != null) { - if (handItemView.Rod.Line.PinchController != null) + var endNode = handItemView.Rod.Line.GetNode(FLineLogicNodeType.End); + var pinch = endNode.gameObject.GetComponent(); + if (pinch != null) { - handItemView.Rod.Line.PinchController.StartPinch(view.Unity.ModelAsset.Pinch); + pinch.StartPinch(view.Unity.ModelAsset.Pinch); } } } @@ -118,9 +120,12 @@ namespace NBF var handItemView = Player.HandItem.GetComponent(); if (handItemView != null && handItemView.Rod != null) { - if (handItemView.Rod.Line.PinchController != null) + var endNode = handItemView.Rod.Line.GetNode(FLineLogicNodeType.End); + var pinch = endNode.gameObject.GetComponent(); + if (pinch != null) { - handItemView.Rod.Line.PinchController.ReleasePinch(); + pinch.ReleasePinch(); + ; } } } diff --git a/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewThrow.cs b/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewThrow.cs index a47e9c474..3a5ee9b20 100644 --- a/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewThrow.cs +++ b/Assets/Scripts/Fishing/New/View/Player/States/PlayerStageViewThrow.cs @@ -61,18 +61,19 @@ namespace NBF PlayerView.Unity.ModelAsset.PlayerAnimator.StartThrow = false; var rod = GetRod(); - if (rod == null || rod.Line == null || rod.Line.Lure == null) + if (rod == null || rod.Line == null) { return; } + var endNode = rod.Line.GetNode(FLineLogicNodeType.End); _throwAnimation = CreateThrowAnimation(rod); _throwAnimation.Player = Player; _throwAnimation?.Play(new ThrowAnimationRequest { - Lure = rod.Line.Lure, + Lure = endNode, ThrowOriginPosition = PlayerView.Unity.transform.position, - StartPosition = rod.Line.Lure.RBody.position, + StartPosition = endNode.Rigidbody.position, Forward = PlayerView.Unity.transform.forward, ChargedProgress = ChargedProgress }); @@ -108,4 +109,4 @@ namespace NBF } } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/Player/Tackle/FBobber.cs b/Assets/Scripts/Fishing/New/View/Player/Tackle/FBobber.cs index 72600e90f..7d580a222 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Tackle/FBobber.cs +++ b/Assets/Scripts/Fishing/New/View/Player/Tackle/FBobber.cs @@ -7,7 +7,8 @@ namespace NBF protected override void OnInit() { // transform.position = Rod.lineHandler.LineConnector_1.transform.position; - SetParent(Rod.Line.Bobber.transform); + var endNode = Rod.Line.GetNode(FLineLogicNodeType.Bobber); + SetParent(endNode.transform); transform.localPosition = Vector3.zero; // var buoyancy = GetComponentInParent(); // buoyancy.InitBobber(); diff --git a/Assets/Scripts/Fishing/New/View/Player/Tackle/FHook.cs b/Assets/Scripts/Fishing/New/View/Player/Tackle/FHook.cs index 777d046c3..ac4938766 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Tackle/FHook.cs +++ b/Assets/Scripts/Fishing/New/View/Player/Tackle/FHook.cs @@ -10,18 +10,17 @@ namespace NBF { hookAsset = GetComponent(); } - + protected override void OnInit() { - // transform.position = Rod.lineHandler.LineConnector_2.transform.position; // transform.rotation = Rod.lineHandler.LineConnector_2.transform.rotation; // 确保旋转也同步 // SetParent(Rod.lineHandler.LineConnector_2.transform); - - - SetParent(Rod.Line.Lure.transform); + + var endNode = Rod.Line.GetNode(FLineLogicNodeType.End); + SetParent(endNode.transform); transform.localPosition = Vector3.zero; - + // var target = lineHandler.LineConnector_2.GetComponent(); // var joint = Hook.gameObject.GetComponent(); // joint.connectedBody = target; diff --git a/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs b/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs index 0dd442155..e25706981 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs +++ b/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs @@ -1,171 +1,1042 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using NBC; -// using Obi; using UnityEngine; +using System.Collections.Generic; +using NBC; namespace NBF { + public struct FLineNodeConstraintState + { + public Vector3 TargetPosition; + public float PlanarStrength; + public float UpwardStrength; + public float DownwardStrength; + public float MaxCorrection; + } + + /// + /// 为 FLine 节点提供附加软约束。求解器只依赖这个通用接口,不依赖具体玩法组件。 + /// + public interface IFLineNodeConstraintProvider + { + bool TryGetConstraintState(out FLineNodeConstraintState state); + } + public enum LineType { - Hand, - HandDouble, Spinning, SpinningFloat, + Hand, + HandDouble, } public class FLine : FGearBase { - public LineType LineType; + [Header("基本参数设置")] public LineType LineType; + [Header("连接点配置")] [SerializeField] private Transform anchorTransform; + [SerializeField] private List lineNodes = new List(); - [SerializeField] private bool isLureConnect; - [SerializeField] private RodLine rodLine; + [Header("物理参数")] [SerializeField] private float positionCorrectionForce = 100f; + [SerializeField] private float dampingCoefficient = 10f; + [SerializeField] private int constraintIterations = 10; + [SerializeField] private bool useMassWeighting = true; - /// - /// 主线 - /// - [SerializeField] private Rope fishingRope; + [Header("动态间距设置")] [SerializeField] private float defaultTransitionSpeed = 2f; // 默认长度变化速度(单位/秒) - /// - /// 浮漂和鱼钩线 - /// - [SerializeField] private Rope bobberRope; + [Header("调试")] [SerializeField] private bool showDebugInfo = true; - public LureController Lure; - public BobberController Bobber; + private readonly List _constraints = new List(); - public JointPinchController PinchController; + private readonly List _nodeConstraintProviders = + new List(); + [System.Serializable] + public class ConnectionConstraint + { + public Rigidbody bodyA; + public Rigidbody bodyB; + public float maxDistance; + public float minDistance; + public float currentDistance; + public Vector3 direction; - public float LinelenghtDiferent; + // 动态目标距离(用于平滑过渡) + public float targetMaxDistance; + public float targetMinDistance; + public bool hasPendingTransition; + public bool hasPendingMaxTransition; + public bool hasPendingMinTransition; + public float maxTransitionSpeed; + public float minTransitionSpeed; + + public ConnectionConstraint(Rigidbody a, Rigidbody b, float maxDist, float minDist = 0f) + { + bodyA = a; + bodyB = b; + maxDistance = maxDist; + minDistance = minDist; + targetMaxDistance = maxDist; + targetMinDistance = minDist; + hasPendingTransition = false; + hasPendingMaxTransition = false; + hasPendingMinTransition = false; + maxTransitionSpeed = 0f; + minTransitionSpeed = 0f; + } + + public void UpdateCurrentState() + { + if (bodyA && bodyB) + { + Vector3 delta = bodyB.position - bodyA.position; + currentDistance = delta.magnitude; + direction = currentDistance > 0.0001f ? delta.normalized : Vector3.right; + } + } + } + + void Awake() + { + BuildConstraints(); + } protected override void OnInit() { - var tipRb = Rod.Asset.LineConnectorRigidbody; - if (isLureConnect) - { - Lure.SetJoint(tipRb); - Lure.EnableCollision(false); - } - else - { - fishingRope.startAnchor = tipRb; - Bobber.SetJoint(tipRb); - Lure.SetJoint(Bobber.rbody); - Lure.gameObject.SetActive(true); - Lure.EnableCollision(false); - Lure.SetKinematic(false); - } - - GetComponentsInChildren(includeInactive: true).ToList().ForEach(delegate(Transform i) - { - i.gameObject.SetActive(true); - }); - - StartCoroutine(LureUseGravity()); - if (isLureConnect) - { - fishingRope.Init(Rod); - } - else - { - fishingRope.Init(Rod); - bobberRope.Init(Rod); - } - - // rodLine.GenerateLineRendererRope(guides.ToArray(), _LineThickness); } - public void InitTest(Rigidbody tipRb) + void Start() { - if (isLureConnect) + if (_constraints.Count == 0) { - Lure.SetJoint(tipRb); - Lure.EnableCollision(false); - } - else - { - fishingRope.startAnchor = tipRb; - Bobber.SetJoint(tipRb); - Lure.SetJoint(Bobber.rbody); - Lure.gameObject.SetActive(true); - Lure.EnableCollision(false); - Lure.SetKinematic(false); - } - - GetComponentsInChildren(includeInactive: true).ToList().ForEach(delegate(Transform i) - { - i.gameObject.SetActive(true); - }); - - StartCoroutine(LureUseGravity()); - if (isLureConnect) - { - fishingRope.Init(Rod); - } - else - { - fishingRope.Init(Rod); - bobberRope.Init(Rod); + Debug.LogWarning("FLine需要至少2个有效节点"); + enabled = false; } } - private IEnumerator LureUseGravity() + void FixedUpdate() { - yield return 1; - Lure.gameObject.SetActive(false); - Lure.gameObject.SetActive(true); - yield return 1; - Lure.RBody.useGravity = true; - } + if (!enabled || _constraints.Count == 0) return; - public void SetTargetLength(float value) - { - Log.Error($"SetObiRopeStretch={value}"); - if (value > 3) + UpdateAnchorNode(); + // 更新动态过渡 + UpdateTransitions(); + + for (int iteration = 0; iteration < constraintIterations; iteration++) { - // value -= 0.2f; + ApplyDistanceConstraints(); + ApplyNodeConstraints(); } - fishingRope.SetTargetLength(value); + ApplyDamping(); + UpdateBreakCountdown(Time.fixedDeltaTime); } - public void SetLureLength(float value) + private void BuildConstraints() { - Log.Error($"SetObiRopeStretch={value}"); - bobberRope.SetTargetLength(value); - } + _constraints.Clear(); + _nodeConstraintProviders.Clear(); + if (lineNodes.Count < 2) return; - - private void Update() - { - LinelenghtDiferent = GetLineDistance(); - - //非钓鱼状态 - Rod.PlayerItem.Tension = Mathf.Clamp(LinelenghtDiferent, 0f, 0.05f); - } - - #region Tension - - private float GetLineDistance() - { - if (!Bobber.JointRb) + for (int i = 0; i < lineNodes.Count; i++) { - return 0; + if (lineNodes[i]) + { + lineNodes[i].AttachToCable(this); + _nodeConstraintProviders.Add(CollectNodeConstraintProviders(lineNodes[i])); + } + else + { + _nodeConstraintProviders.Add(Array.Empty()); + } } - // return 0; - - //第一个节点到竿稍的位置-第一段鱼线长度 - return Vector3.Distance(Bobber.transform.position, Bobber.JointRb.transform.position) - - fishingRope.GetCurrentLength(); + // 创建约束 + for (int i = 0; i < lineNodes.Count - 1; i++) + { + FLineLogicNode currentNode = lineNodes[i]; + FLineLogicNode nextNode = lineNodes[i + 1]; + Rigidbody bodyA = currentNode ? currentNode.Rigidbody : null; + Rigidbody bodyB = nextNode ? nextNode.Rigidbody : null; + + if (bodyA != null && bodyB != null) + { + var constraint = new ConnectionConstraint( + bodyA, + bodyB, + currentNode.NextSegmentMaxLength, + currentNode.NextSegmentMinLength + ); + _constraints.Add(constraint); + } + } } - public float GetTension(float weight) + private FLineLogicNode GetSegmentNode(int segmentIndex) { - return weight * GetLineDistance(); + if (segmentIndex < 0 || segmentIndex >= lineNodes.Count - 1) + { + return null; + } + + return lineNodes[segmentIndex]; + } + + private Rigidbody GetBodyAt(int nodeIndex) + { + if (nodeIndex < 0 || nodeIndex >= lineNodes.Count) + { + return null; + } + + FLineLogicNode node = lineNodes[nodeIndex]; + return node ? node.Rigidbody : null; + } + + private IFLineNodeConstraintProvider[] GetNodeConstraintProvidersAt(int nodeIndex) + { + if (nodeIndex < 0 || nodeIndex >= _nodeConstraintProviders.Count) + { + return Array.Empty(); + } + + return _nodeConstraintProviders[nodeIndex]; + } + + private static IFLineNodeConstraintProvider[] CollectNodeConstraintProviders(FLineLogicNode node) + { + MonoBehaviour[] behaviours = node.GetComponents(); + List providers = new List(); + + for (int i = 0; i < behaviours.Length; i++) + { + MonoBehaviour behaviour = behaviours[i]; + if (behaviour is IFLineNodeConstraintProvider provider) + { + providers.Add(provider); + } + } + + return providers.ToArray(); + } + + private void SyncSegmentMaxLength(int segmentIndex, float maxLength) + { + FLineLogicNode node = GetSegmentNode(segmentIndex); + if (node) + { + node.NextSegmentMaxLength = maxLength; + } + } + + private void SyncSegmentMinLength(int segmentIndex, float minLength) + { + FLineLogicNode node = GetSegmentNode(segmentIndex); + if (node) + { + node.NextSegmentMinLength = minLength; + } + } + + private bool ContainsBody(Rigidbody targetBody) + { + for (int i = 0; i < lineNodes.Count; i++) + { + if (GetBodyAt(i) == targetBody) + { + return true; + } + } + + return false; + } + + /// + /// 更新所有活跃的过渡 + /// + private void UpdateTransitions() + { + float deltaTime = Time.fixedDeltaTime; + + for (int i = 0; i < _constraints.Count; i++) + { + var constraint = _constraints[i]; + + if (constraint.hasPendingMaxTransition) + { + float nextMaxDistance = Mathf.MoveTowards( + constraint.maxDistance, + constraint.targetMaxDistance, + constraint.maxTransitionSpeed * deltaTime + ); + constraint.maxDistance = nextMaxDistance; + SyncSegmentMaxLength(i, nextMaxDistance); + + if (Mathf.Abs(nextMaxDistance - constraint.targetMaxDistance) < 0.0001f) + { + constraint.maxDistance = constraint.targetMaxDistance; + constraint.hasPendingMaxTransition = false; + SyncSegmentMaxLength(i, constraint.targetMaxDistance); + } + } + + if (constraint.hasPendingMinTransition) + { + float nextMinDistance = Mathf.MoveTowards( + constraint.minDistance, + constraint.targetMinDistance, + constraint.minTransitionSpeed * deltaTime + ); + constraint.minDistance = nextMinDistance; + SyncSegmentMinLength(i, nextMinDistance); + + if (Mathf.Abs(nextMinDistance - constraint.targetMinDistance) < 0.0001f) + { + constraint.minDistance = constraint.targetMinDistance; + constraint.hasPendingMinTransition = false; + SyncSegmentMinLength(i, constraint.targetMinDistance); + } + } + + constraint.hasPendingTransition = + constraint.hasPendingMaxTransition || constraint.hasPendingMinTransition; + } + } + + private void ApplyDistanceConstraints() + { + for (int i = 0; i < _constraints.Count; i++) + { + var constraint = _constraints[i]; + if (!constraint.bodyA || !constraint.bodyB) continue; + + constraint.UpdateCurrentState(); + + float currentDist = constraint.currentDistance; + float maxDist = constraint.maxDistance; + float minDist = constraint.minDistance; + + float error = 0f; + bool needCorrection = false; + + if (currentDist > maxDist) + { + error = currentDist - maxDist; + needCorrection = true; + } + + if (!needCorrection || Mathf.Abs(error) < 0.0001f) continue; + + float invMassA = constraint.bodyA.isKinematic ? 0f : 1f / constraint.bodyA.mass; + float invMassB = constraint.bodyB.isKinematic ? 0f : 1f / constraint.bodyB.mass; + float totalInvMass = invMassA + invMassB; + + if (totalInvMass < 0.0001f) continue; + + float weightA = useMassWeighting ? (invMassA / totalInvMass) : 0.5f; + float weightB = useMassWeighting ? (invMassB / totalInvMass) : 0.5f; + + Vector3 correction = constraint.direction * error; + Vector3 positionCorrectionA = correction * weightA; + Vector3 positionCorrectionB = -correction * weightB; + + constraint.bodyA.position += positionCorrectionA; + constraint.bodyB.position += positionCorrectionB; + + Vector3 velocityCorrectionA = positionCorrectionA / Time.fixedDeltaTime; + Vector3 velocityCorrectionB = positionCorrectionB / Time.fixedDeltaTime; + + constraint.bodyA.AddForce(velocityCorrectionA * constraint.bodyA.mass, ForceMode.Impulse); + constraint.bodyB.AddForce(velocityCorrectionB * constraint.bodyB.mass, ForceMode.Impulse); + } + } + + private void ApplyNodeConstraints() + { + for (int i = 0; i < lineNodes.Count; i++) + { + Rigidbody body = GetBodyAt(i); + IFLineNodeConstraintProvider[] providers = GetNodeConstraintProvidersAt(i); + + if (!body || body.isKinematic || providers.Length == 0) + { + continue; + } + + for (int providerIndex = 0; providerIndex < providers.Length; providerIndex++) + { + IFLineNodeConstraintProvider provider = providers[providerIndex]; + if (provider == null) + { + continue; + } + + if (provider is Behaviour behaviour && !behaviour.isActiveAndEnabled) + { + continue; + } + + if (!provider.TryGetConstraintState(out FLineNodeConstraintState constraint)) + { + continue; + } + + ApplyWorldTargetConstraint(body, constraint); + } + } + } + + private static void ApplyWorldTargetConstraint(Rigidbody body, FLineNodeConstraintState constraint) + { + Vector3 delta = constraint.TargetPosition - body.position; + Vector3 planarDelta = Vector3.ProjectOnPlane(delta, Vector3.up); + Vector3 correction = planarDelta * Mathf.Clamp01(constraint.PlanarStrength); + + float verticalStrength = delta.y >= 0f + ? Mathf.Clamp01(constraint.UpwardStrength) + : Mathf.Clamp01(constraint.DownwardStrength); + correction.y = delta.y * verticalStrength; + + float maxCorrection = Mathf.Max(0f, constraint.MaxCorrection); + if (maxCorrection > 0f && correction.magnitude > maxCorrection) + { + correction = correction.normalized * maxCorrection; + } + + if (correction.sqrMagnitude < 1e-8f) + { + return; + } + + body.position += correction; + + Vector3 velocityCorrection = correction / Mathf.Max(Time.fixedDeltaTime, 0.0001f); + body.AddForce(velocityCorrection * body.mass, ForceMode.Impulse); + } + + private void ApplyDamping() + { + for (int i = 0; i < _constraints.Count; i++) + { + var constraint = _constraints[i]; + if (!constraint.bodyA || !constraint.bodyB) continue; + + if (constraint.currentDistance <= constraint.maxDistance) continue; + + Vector3 relativeVelocity = constraint.bodyB.linearVelocity - constraint.bodyA.linearVelocity; + float velocityInConstraintDir = Vector3.Dot(relativeVelocity, constraint.direction); + + if (velocityInConstraintDir > 0) + { + float dampingForce = -velocityInConstraintDir * dampingCoefficient; + Vector3 dampingImpulse = constraint.direction * dampingForce * Time.fixedDeltaTime; + + constraint.bodyA.AddForce(-dampingImpulse * constraint.bodyA.mass, ForceMode.Impulse); + constraint.bodyB.AddForce(dampingImpulse * constraint.bodyB.mass, ForceMode.Impulse); + } + } + } + + private void UpdateAnchorNode() + { + if (anchorTransform == null || lineNodes.Count < 1) + { + return; + } + + var startNode = lineNodes[0].Rigidbody; + startNode.transform.SetPositionAndRotation(anchorTransform.position, anchorTransform.rotation); + + if (!startNode.isKinematic) + { + startNode.linearVelocity = Vector3.zero; + startNode.angularVelocity = Vector3.zero; + } + } + + #region 动态间距修改接口 + + public void SetLenght(float length) + { + SetSegmentMaxLength(0, length); + } + + /// + /// 按速度过渡某段的最大距离 + /// + public void SetSegmentMaxLength(int segmentIndex, float targetLength, float transitionSpeed = 2f) + { + if (segmentIndex < 0 || segmentIndex >= _constraints.Count) return; + + targetLength = Mathf.Max(0.01f, targetLength); + float speed = Mathf.Max(0.01f, transitionSpeed > 0 ? transitionSpeed : defaultTransitionSpeed); + + var constraint = _constraints[segmentIndex]; + constraint.targetMaxDistance = targetLength; + constraint.maxTransitionSpeed = speed; + constraint.hasPendingMaxTransition = Mathf.Abs(constraint.maxDistance - targetLength) >= 0.0001f; + constraint.hasPendingTransition = constraint.hasPendingMaxTransition || constraint.hasPendingMinTransition; + } + + /// + /// 按速度过渡某段的最小距离 + /// + public void SetSegmentMinLength(int segmentIndex, float targetLength, float transitionSpeed = -1) + { + if (segmentIndex < 0 || segmentIndex >= _constraints.Count) return; + + targetLength = Mathf.Max(0f, targetLength); + float speed = Mathf.Max(0.01f, transitionSpeed > 0 ? transitionSpeed : defaultTransitionSpeed); + + var constraint = _constraints[segmentIndex]; + constraint.targetMinDistance = targetLength; + constraint.minTransitionSpeed = speed; + constraint.hasPendingMinTransition = Mathf.Abs(constraint.minDistance - targetLength) >= 0.0001f; + constraint.hasPendingTransition = constraint.hasPendingMaxTransition || constraint.hasPendingMinTransition; + } + + /// + /// 同时按速度过渡某段的最大和最小距离 + /// + public void SetSegmentLengths(int segmentIndex, float targetMaxLength, float targetMinLength, + float transitionSpeed = -1) + { + if (segmentIndex < 0 || segmentIndex >= _constraints.Count) return; + + targetMaxLength = Mathf.Max(0.01f, targetMaxLength); + targetMinLength = Mathf.Max(0f, targetMinLength); + float speed = Mathf.Max(0.01f, transitionSpeed > 0 ? transitionSpeed : defaultTransitionSpeed); + + var constraint = _constraints[segmentIndex]; + constraint.targetMaxDistance = targetMaxLength; + constraint.targetMinDistance = targetMinLength; + constraint.maxTransitionSpeed = speed; + constraint.minTransitionSpeed = speed; + constraint.hasPendingMaxTransition = Mathf.Abs(constraint.maxDistance - targetMaxLength) >= 0.0001f; + constraint.hasPendingMinTransition = Mathf.Abs(constraint.minDistance - targetMinLength) >= 0.0001f; + constraint.hasPendingTransition = constraint.hasPendingMaxTransition || constraint.hasPendingMinTransition; + } + + /// + /// 扩展整个绳索(所有段均匀缩放) + /// + public void ExtendAllSegments(float scaleFactor, float transitionSpeed = -1) + { + float speed = transitionSpeed > 0 ? transitionSpeed : defaultTransitionSpeed; + + for (int i = 0; i < _constraints.Count; i++) + { + var constraint = _constraints[i]; + float newMaxLength = constraint.maxDistance * scaleFactor; + float newMinLength = constraint.minDistance * scaleFactor; + + SetSegmentLengths(i, newMaxLength, newMinLength, speed); + } + } + + /// + /// 收缩/拉紧绳索(所有段向目标长度过渡) + /// + public void TightenAllSegments(float targetLength, float transitionSpeed = -1) + { + float speed = transitionSpeed > 0 ? transitionSpeed : defaultTransitionSpeed; + + for (int i = 0; i < _constraints.Count; i++) + { + var constraint = _constraints[i]; + SetSegmentLengths(i, targetLength, Mathf.Min(constraint.minDistance, targetLength), speed); + } + } + + /// + /// 对特定段施加拉力(减小最大距离) + /// + public void PullSegment(int segmentIndex, float amount, float transitionSpeed = -1) + { + if (segmentIndex >= 0 && segmentIndex < _constraints.Count) + { + var constraint = _constraints[segmentIndex]; + float newMaxLength = Mathf.Max(0.01f, constraint.targetMaxDistance - amount); + SetSegmentMaxLength(segmentIndex, newMaxLength, transitionSpeed); + } + } + + /// + /// 放松特定段(增加最大距离) + /// + public void RelaxSegment(int segmentIndex, float amount, float transitionSpeed = -1) + { + if (segmentIndex >= 0 && segmentIndex < _constraints.Count) + { + var constraint = _constraints[segmentIndex]; + float newMaxLength = constraint.targetMaxDistance + amount; + SetSegmentMaxLength(segmentIndex, newMaxLength, transitionSpeed); + } + } + + /// + /// 移除指定段的过渡 + /// + private void RemoveExistingTransition(int segmentIndex, bool removeMax, bool removeMin) + { + if (segmentIndex < 0 || segmentIndex >= _constraints.Count) + { + return; + } + + var constraint = _constraints[segmentIndex]; + if (removeMax) + { + constraint.hasPendingMaxTransition = false; + constraint.targetMaxDistance = constraint.maxDistance; + } + + if (removeMin) + { + constraint.hasPendingMinTransition = false; + constraint.targetMinDistance = constraint.minDistance; + } + + constraint.hasPendingTransition = constraint.hasPendingMaxTransition || constraint.hasPendingMinTransition; + } + + /// + /// 取消所有正在进行的过渡 + /// + public void CancelAllTransitions() + { + foreach (var constraint in _constraints) + { + constraint.hasPendingTransition = false; + constraint.hasPendingMaxTransition = false; + constraint.hasPendingMinTransition = false; + constraint.targetMaxDistance = constraint.maxDistance; + constraint.targetMinDistance = constraint.minDistance; + } + } + + /// + /// 取消指定段的过渡 + /// + public void CancelTransition(int segmentIndex) + { + RemoveExistingTransition(segmentIndex, true, true); + if (segmentIndex < _constraints.Count) + { + _constraints[segmentIndex].hasPendingTransition = false; + } + } + + /// + /// 获取某个段是否正在进行过渡 + /// + public bool IsSegmentTransitioning(int segmentIndex) + { + if (segmentIndex >= 0 && segmentIndex < _constraints.Count) + { + return _constraints[segmentIndex].hasPendingTransition; + } + + return false; + } + + /// + /// 获取某段当前的目标最大距离 + /// + public float GetTargetMaxLength(int segmentIndex) + { + if (segmentIndex >= 0 && segmentIndex < _constraints.Count) + { + return _constraints[segmentIndex].targetMaxDistance; + } + + return -1f; + } + + /// + /// 获取某段当前的目标最小距离 + /// + public float GetTargetMinLength(int segmentIndex) + { + if (segmentIndex >= 0 && segmentIndex < _constraints.Count) + { + return _constraints[segmentIndex].targetMinDistance; + } + + return -1f; + } + + /// + /// 设置默认长度变化速度 + /// + public void SetDefaultTransitionSpeed(float speed) + { + defaultTransitionSpeed = Mathf.Max(0.01f, speed); + } + + #endregion + + #region 极限判定 + + /// + /// 当前逻辑链总长度超出配置总长度的部分,小于等于零时记为 0。 + /// + [Header("Limit Detection")] + public float CurrentStretchLength { get; private set; } + + /// + /// 总长度 + /// + public float TotalLength { get; private set; } + + [Min(0f)] + // 极限判定的长度容差,允许链路在总长或单段长度上存在少量误差。 + [SerializeField] + private float lengthLimitTolerance = 0.01f; + + [Min(0f)] + // 达到极限后,只有当前超长值大于该阈值时,才开始进入断线候选计时。 + [SerializeField] + private float breakStretchThreshold = 0.3f; + + [Min(0f)] + // UI 百分比开始起算的最小超长值;低于或等于该值时统一按 0% 处理。 + [SerializeField] + private float breakStretchPercentMinThreshold = 0.06f; + + [Min(0f)] + // 断线候选状态允许持续的最大时间;超过后会发出一次断线消息。 + [SerializeField] + private float breakLimitDuration = 3f; + + /// + /// 当鱼线达到断线条件时发出的一次性消息。 + /// 外部可订阅该事件,在回调中执行切线、播放表现或状态切换。 + /// + public event Action OnLineBreakRequested; + + /// + /// 当前是否处于极限状态。 + /// 只要整链超出总长度容差,或任一逻辑段超出单段容差,即认为到达极限。 + /// + public bool IsAtLimit { get; private set; } + + /// + /// 当前断线候选状态的累计时间。 + /// 只有在处于极限状态,且 CurrentStretchLength 大于断线阈值时才会累加;否则重置为 0。 + /// + public float LimitStateTime { get; private set; } + + /// + /// 当前极限断线消息是否已经发出过。 + /// 在退出断线候选状态前只会发一次,避免重复通知。 + /// + public bool HasBreakNotificationSent { get; private set; } + + /// + /// 当前拉力极限百分比。 + /// 当超长值小于等于 breakStretchPercentMinThreshold 时为 0; + /// 当超长值大于等于 breakStretchThreshold 时为 100; + /// 中间区间按线性比例映射,供 UI 显示使用。 + /// + public float CurrentBreakStretchPercent => EvaluateBreakStretchPercent(CurrentStretchLength); + + /// + /// 当前是否正在进行断线候选计时。 + /// + public bool IsBreakCountdownActive => IsAtLimit && CurrentStretchLength > breakStretchThreshold; + + private float EvaluateBreakStretchPercent(float stretchLength) + { + var percentMinThreshold = Mathf.Max(lengthLimitTolerance, breakStretchPercentMinThreshold); + + if (stretchLength <= percentMinThreshold) + { + return 0f; + } + + if (stretchLength >= breakStretchThreshold) + { + return 100f; + } + + if (breakStretchThreshold <= percentMinThreshold) + { + return 100f; + } + + return Mathf.InverseLerp(percentMinThreshold, breakStretchThreshold, stretchLength) * 100f; + } + + private void SetLimitState(bool isAtLimit) + { + IsAtLimit = isAtLimit; + } + + private void UpdateBreakCountdown(float deltaTime) + { + if (lineNodes.Count < 2) + { + SetLimitState(false); + ResetLimitState(); + return; + } + + var startNode = lineNodes[0]; + var endNode = lineNodes[^1]; + TotalLength = 0; + foreach (var node in lineNodes) + { + if (node.NodeType == FLineLogicNodeType.End) continue; + TotalLength += node.NextSegmentMaxLength; + } + + var realLen = Vector3.Distance(startNode.transform.position, endNode.transform.position); + CurrentStretchLength = realLen - TotalLength; + if (CurrentStretchLength < 0f) + { + CurrentStretchLength = 0f; + } + + SetLimitState(CurrentStretchLength > lengthLimitTolerance); + + if (CurrentStretchLength > 1) + { + Log.Error($"水电费 realLen={realLen} TotalLength={TotalLength}"); + } + + if (!IsBreakCountdownActive) + { + LimitStateTime = 0f; + HasBreakNotificationSent = false; + return; + } + + LimitStateTime += Mathf.Max(0f, deltaTime); + if (HasBreakNotificationSent || LimitStateTime < breakLimitDuration) + { + return; + } + + HasBreakNotificationSent = true; + NotifyLineBreakRequested(); + } + + /// + /// 发出鱼线达到断线条件的消息。 + /// 这里预留给外部订阅,当前不在求解器内部直接执行断线逻辑。 + /// + private void NotifyLineBreakRequested() + { + OnLineBreakRequested?.Invoke(this); + } + + private void ResetLimitState() + { + CurrentStretchLength = 0f; + IsAtLimit = false; + LimitStateTime = 0f; + HasBreakNotificationSent = false; + } + + #endregion + + #region 公共接口 + + /// + /// 获取一个节点 + /// + /// + /// + public FLineLogicNode GetNode(FLineLogicNodeType type) + { + foreach (var node in lineNodes) + { + if (node.NodeType == type) + { + return node; + } + } + + return null; + } + + + public float GetCurrentSegmentLength(int segmentIndex) + { + if (segmentIndex >= 0 && segmentIndex < _constraints.Count) + { + _constraints[segmentIndex].UpdateCurrentState(); + return _constraints[segmentIndex].currentDistance; + } + + return -1f; + } + + public void AddConnectedBody(Rigidbody rb, float maxLength = 1f, float minLength = 0f) + { + if (rb == null) + { + return; + } + + FLineLogicNode node = rb.GetComponent(); + if (!node) + { + Debug.LogWarning("AddConnectedBody需要目标刚体上挂有FLineLogicNode"); + return; + } + + if (!lineNodes.Contains(node)) + { + if (lineNodes.Count > 0 && lineNodes[lineNodes.Count - 1]) + { + lineNodes[lineNodes.Count - 1].SetSegmentLengths(maxLength, minLength); + } + + node.AttachToCable(this); + lineNodes.Add(node); + BuildConstraints(); + enabled = _constraints.Count > 0; + } + } + + public void RemoveConnectedBody(Rigidbody rb) + { + if (rb == null) + { + return; + } + + for (int i = 0; i < lineNodes.Count; i++) + { + if (GetBodyAt(i) == rb) + { + lineNodes.RemoveAt(i); + BuildConstraints(); + enabled = _constraints.Count > 0; + break; + } + } + } + + public List GetConnectedBodies() + { + List bodies = new List(lineNodes.Count); + for (int i = 0; i < lineNodes.Count; i++) + { + bodies.Add(GetBodyAt(i)); + } + + return bodies; + } + + public List GetLineNodes() + { + return new List(lineNodes); + } + + public bool TryGetAdjacentBodies(FLineLogicNode node, out Rigidbody previousBody, out Rigidbody nextBody) + { + previousBody = null; + nextBody = null; + + if (!node) + { + return false; + } + + int index = lineNodes.IndexOf(node); + if (index < 0) + { + return false; + } + + if (index > 0 && lineNodes[index - 1]) + { + previousBody = lineNodes[index - 1].Rigidbody; + } + + if (index < lineNodes.Count - 1 && lineNodes[index + 1]) + { + nextBody = lineNodes[index + 1].Rigidbody; + } + + return previousBody || nextBody; + } + + public void ApplyForceAtBody(Rigidbody targetBody, Vector3 force, ForceMode mode = ForceMode.Force) + { + if (targetBody && ContainsBody(targetBody)) + { + targetBody.AddForce(force, mode); + } + } + + public float GetSegmentMaxLength(int segmentIndex) + { + FLineLogicNode node = GetSegmentNode(segmentIndex); + if (node) + return node.NextSegmentMaxLength; + + return -1f; + } + + #endregion + + #region 可视化调试 + + void OnDrawGizmos() + { + if (!showDebugInfo || lineNodes.Count < 2) return; + + for (int i = 0; i < lineNodes.Count - 1; i++) + { + Rigidbody bodyA = GetBodyAt(i); + Rigidbody bodyB = GetBodyAt(i + 1); + FLineLogicNode segmentNode = GetSegmentNode(i); + + if (bodyA != null && bodyB != null) + { + float currentDist = Vector3.Distance(bodyA.position, bodyB.position); + float maxDist = segmentNode ? segmentNode.NextSegmentMaxLength : 1f; + float minDist = segmentNode ? segmentNode.NextSegmentMinLength : 0f; + + // 颜色:如果正在过渡用橙色,绿色=正常范围,红色=超出最大距离,蓝色=小于最小距离 + if (IsSegmentTransitioning(i)) + Gizmos.color = new Color(1f, 0.5f, 0f); // 橙色表示正在过渡 + else if (currentDist > maxDist) + Gizmos.color = Color.red; + else if (currentDist < minDist && minDist > 0) + Gizmos.color = Color.blue; + else + Gizmos.color = Color.green; + + Gizmos.DrawLine(bodyA.position, bodyB.position); + + Vector3 midPoint = (bodyA.position + bodyB.position) * 0.5f; + Gizmos.DrawWireSphere(midPoint, 0.1f); + +#if UNITY_EDITOR + string info = $"距离:{currentDist:F2}"; + if (IsSegmentTransitioning(i)) + info += $"\n过渡中→{GetTargetMaxLength(i):F2}"; + else + info += $" [最大:{maxDist:F2}"; + info += $"]"; + UnityEditor.Handles.Label(midPoint, info); +#endif + } + } + + Gizmos.color = Color.red; + for (int i = 0; i < lineNodes.Count; i++) + { + Rigidbody body = GetBodyAt(i); + if (body != null) + { + Gizmos.DrawSphere(body.position, 0.05f); + } + } } #endregion diff --git a/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs.meta b/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs.meta index a3ec9aebc..970afcb8d 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs.meta +++ b/Assets/Scripts/Fishing/New/View/Player/Tackle/FLine.cs.meta @@ -1,3 +1,3 @@ fileFormatVersion: 2 -guid: c0403ffd74ce46fab8bd4ef057e51432 -timeCreated: 1766582567 \ No newline at end of file +guid: c7095cf554c345839173044e4786b0ba +timeCreated: 1776948821 \ No newline at end of file diff --git a/Assets/Scripts/Fishing/New/View/Player/Tackle/FLure.cs b/Assets/Scripts/Fishing/New/View/Player/Tackle/FLure.cs index fa7af1814..c75b85b26 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Tackle/FLure.cs +++ b/Assets/Scripts/Fishing/New/View/Player/Tackle/FLure.cs @@ -13,8 +13,8 @@ namespace NBF // LureHookWaterDisplacement = Lure.GetComponent(); // SetParent(Rod.lineHandler.LineConnector_1.transform); - - SetParent(Rod.Line.Lure.transform); + var endNode = Rod.Line.GetNode(FLineLogicNodeType.End); + SetParent(endNode.transform); transform.localPosition = Vector3.zero; } } diff --git a/Assets/Scripts/Fishing/New/View/Player/Tackle/FRod.cs b/Assets/Scripts/Fishing/New/View/Player/Tackle/FRod.cs index eef8eff7b..1ce4e3c68 100644 --- a/Assets/Scripts/Fishing/New/View/Player/Tackle/FRod.cs +++ b/Assets/Scripts/Fishing/New/View/Player/Tackle/FRod.cs @@ -72,24 +72,14 @@ namespace NBF if (Line.LineType == LineType.Spinning) { //没有浮漂类型 - Line.Lure.SetJointDistance(PlayerItem.LineLength); - if (PlayerItem.StretchRope) - { - // Line.SetTargetLength(PlayerItem.Tension > 0f ? 0f : PlayerItem.LineLength); - Line.SetTargetLength(PlayerItem.LineLength); - } + Line.SetLenght(PlayerItem.LineLength); } else { //有浮漂 - Line.Lure.SetJointDistance(PlayerItem.FloatLength); - Line.Bobber.SetJointDistance(PlayerItem.LineLength - PlayerItem.FloatLength); - if (PlayerItem.StretchRope) - { - // Line.SetTargetLength(PlayerItem.Tension > 0f ? 0f : PlayerItem.LineLength - PlayerItem.FloatLength); - Line.SetTargetLength(PlayerItem.LineLength - PlayerItem.FloatLength); - Line.SetLureLength(PlayerItem.FloatLength); - } + Line.SetSegmentMaxLength(0, PlayerItem.LineLength - PlayerItem.FloatLength); + //浮漂位置 + Line.SetSegmentMaxLength(1, PlayerItem.FloatLength); } } @@ -338,12 +328,12 @@ namespace NBF var state = PlayerItem.Owner.State; - - Vector3 vector = Line.Lure.transform.position; + var endNode = Line.GetNode(FLineLogicNodeType.End); + Vector3 vector = endNode.transform.position; // 当前物体的朝向与指向 Lure 的方向之间的夹角,在 0(完全对齐)到 1(完全相反)之间的一个比例值 float headingAlignment = Vector3.Angle(base.transform.forward, - (Line.Lure.transform.position - transform.position).normalized) / 180f; + (endNode.transform.position - transform.position).normalized) / 180f; // 经过朝向调制后的有效张力 var effectiveTension = Mathf.Clamp(CurrentTension01 * headingAlignment, 0f, 1f); diff --git a/Assets/Scripts/Fishing/Rope/Rope.cs b/Assets/Scripts/Fishing/Rope/Rope.cs deleted file mode 100644 index 03a9cf3a8..000000000 --- a/Assets/Scripts/Fishing/Rope/Rope.cs +++ /dev/null @@ -1,1069 +0,0 @@ -using System; -using NBF; -using UnityEngine; - -[RequireComponent(typeof(LineRenderer))] -public class Rope : MonoBehaviour -{ - [Header("Anchors")] [SerializeField] public Rigidbody startAnchor; - [SerializeField] public Rigidbody endAnchor; - - /// 鱼线宽度倍数 - public int LineMultiple = 1; - - [Header("Physics (Dynamic Nodes, Fixed Segment Len)")] [SerializeField, Min(0.01f), Tooltip("物理每段固定长度(越小越细致越耗)")] - private float physicsSegmentLen = 0.15f; - - [SerializeField, Range(2, 200)] private int minPhysicsNodes = 12; - - [SerializeField, Range(2, 400), Tooltip("物理节点上限(仅用于性能保护;与“最大长度不限制”不是一回事)")] - private int maxPhysicsNodes = 120; - - [SerializeField] private float gravityStrength = 2.0f; - [SerializeField, Range(0f, 1f)] private float velocityDampen = 0.95f; - - [SerializeField, Range(0.0f, 1.0f), Tooltip("约束修正强度,越大越硬。0.6~0.9 常用")] - private float stiffness = 0.8f; - - [SerializeField, Range(1, 80), Tooltip("迭代次数。鱼线 10~30 通常够用")] - private int iterations = 20; - - [SerializeField, Range(0, 16), Tooltip("主求解后追加的硬长度约束次数。只负责把 poly 拉回到 rest total,不改变可变长度逻辑")] - private int hardTightenIterations = 2; - - [Header("Length Control (No Min/Max Clamp)")] - [Tooltip("初始总长度(米)。如果为 0,则用 physicsSegmentLen*(minPhysicsNodes-1) 作为初始长度")] - [SerializeField, Min(0f)] - private float initialLength = 0f; - - [Tooltip("长度变化平滑时间(越小越跟手,越大越稳)")] [SerializeField, Min(0.0001f)] - private float lengthSmoothTime = 0.15f; - - [Tooltip("当长度在变化时,额外把速度压掉一些(防抖)。0=不额外处理,1=变化时几乎清速度(建议只在收线生效)")] [SerializeField, Range(0f, 1f)] - private float lengthChangeVelocityKill = 0.6f; - - [Tooltip("允许的最小松弛余量(避免目标长度刚好等于锚点距离时抖动)")] [SerializeField, Min(0f)] - private float minSlack = 0.002f; - - [Header("Head Segment Clamp")] [Tooltip("第一段(起点->第1节点)允许的最小长度,避免收线时第一段被压到0导致数值炸")] [SerializeField, Min(0.0001f)] - private float headMinLen = 0.01f; - - [Header("Node Count Stability")] [SerializeField, Tooltip("节点数切换迟滞(米)。避免长度在临界点抖动导致节点数来回跳 -> 卡顿")] - private float nodeHysteresis = 0.05f; - - [Header("Simple Ground/Water Constraint (Cheap)")] [SerializeField] - private bool constrainToGround = true; - - [SerializeField] private LayerMask groundMask = ~0; - [SerializeField, Min(0f)] private float groundRadius = 0.01f; - [SerializeField, Min(0f)] private float groundCastHeight = 1.0f; - [SerializeField, Min(0.01f)] private float groundCastDistance = 2.5f; - - [SerializeField, Range(1, 8), Tooltip("每隔多少个节点做一次地面检测;越大越省")] - private int groundSampleStep = 3; - - [SerializeField, Tooltip("未采样的点用插值还是直接拷贝邻近采样值")] - private bool groundInterpolate = true; - - [SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次地面约束")] - private int groundUpdateEvery = 2; - - [SerializeField, Range(0, 8), Tooltip("地面约束后,再做几次长度约束,减少 poly 被地面抬长")] - private int groundPostConstraintIterations = 2; - - private int _groundFrameCounter; - - [Header("Simple Water Float (Cheap)")] [SerializeField, Tooltip("绳子落到水面以下时,是否把节点约束回水面")] - private bool constrainToWaterSurface = true; - - [SerializeField, Tooltip("静态水面高度;如果你后面接波浪水面,可改成采样函数")] - private float waterLevelY = 0f; - - [SerializeField, Min(0f), Tooltip("把线抬到水面上方一点,避免视觉穿插")] - private float waterSurfaceOffset = 0.002f; - - [SerializeField, Range(1, 8), Tooltip("每隔多少个节点做一次水面约束采样;越大越省")] - private int waterSampleStep = 2; - - [SerializeField, Tooltip("未采样节点是否插值水面高度")] - private bool waterInterpolate = true; - - [SerializeField, Range(1, 8), Tooltip("每隔多少次FixedUpdate更新一次水面约束")] - private int waterUpdateEvery = 1; - - [SerializeField, Range(0f, 1f), Tooltip("水面约束抬升强度(每次更新的插值强度),越小越渐进")] - private float waterLiftStrength = 0.25f; - - [SerializeField, Tooltip("startAnchor 在水下时,让其相邻端节点强制跟随 startAnchor,避免被抬到水面导致脱离")] - private bool keepStartAdjacentNodeFollow = true; - - [SerializeField, Range(0, 8), Tooltip("水面约束后,再做几次长度约束,减少局部折角")] - private int waterPostConstraintIterations = 2; - - private int _waterFrameCounter; - - [Header("Render (High Resolution)")] [SerializeField, Min(1), Tooltip("静止时每段物理线段插值加密数量(越大越顺,越耗)")] - private int renderSubdivisionsIdle = 6; - - [SerializeField, Min(1), Tooltip("甩动时每段物理线段插值加密数量(动态降LOD以防卡顿)")] - private int renderSubdivisionsMoving = 2; - - [SerializeField, Min(0f), Tooltip("平均速度超过该阈值认为在甩动(用于动态降 subdiv)")] - private float movingSpeedThreshold = 2.0f; - - [SerializeField, Tooltip("是否使用 Catmull-Rom 平滑(开启更顺,但更耗)")] - private bool smooth = true; - - [SerializeField, Min(0.0001f)] private float lineWidth = 0.001f; - - [Header("Performance")] [SerializeField, Tooltip("远端玩家鱼线不可见时,直接停止整条渲染线的模拟与绘制")] - private bool cullRemoteRopeWhenInvisible = true; - - [SerializeField, Tooltip("本地玩家自己的鱼线始终保持完整计算")] - private bool localOwnerAlwaysSimulate = true; - - [SerializeField, Range(1, 60), Tooltip("每隔多少个 FixedUpdate 重新判断一次可见性")] - private int visibilityCheckEvery = 10; - - [SerializeField, Range(0f, 0.5f), Tooltip("屏幕边缘额外留白,避免刚进视野就闪现")] - private float visibilityViewportPadding = 0.08f; - - [Header("Air Drag (Stable)")] [SerializeField, Range(0f, 5f), Tooltip("空气阻力(Y向),指数衰减,越大越不飘")] - private float airDrag = 0.9f; - - [SerializeField, Range(0f, 2f), Tooltip("横向额外阻力(XZ),指数衰减,越大越不左右飘")] - private float airDragXZ = 0.6f; - - private LineRenderer _lineRenderer; - - // physics - private int _physicsNodes; - private Vector3[] _pCurr; - private Vector3[] _pPrev; - - // render (一次性分配到最大,后续不再 new) - private Vector3[] _rPoints; - private int _rCapacity; - - private Vector3 _gravity; - - // length control runtime - private float _targetLength; - private float _currentLength; - private float _lengthSmoothVel; - - // rest length head - private float _headRestLen; - - // node stability - private int _lastDesiredNodes = 0; - - // caches - private Transform _startTr; - private Transform _endTr; - - // precomputed - private float _dt; - private float _dt2; - private float _kY; - private float _kXZ; - private Transform _cameraTr; - private int _visibilityCheckCounter; - private bool _isCulledByVisibility; - private int _tIdleSubdiv = -1; - private int _tMovingSubdiv = -1; - - private FRod _rod; - public void Init(FRod rod) - { - _rod = rod; - if (Application.isPlaying) - RefreshVisibilityState(true); - } - - // Catmull t caches(只缓存 idle/moving 两档,减少每帧重复乘法) - private struct TCaches - { - public float[] t; - public float[] t2; - public float[] t3; - } - - private TCaches _tIdle; - private TCaches _tMoving; - - private void Awake() - { - _lineRenderer = GetComponent(); - _gravity = new Vector3(0f, -gravityStrength, 0f); - - RefreshAnchorTransforms(); - - InitLengthSystem(); - AllocateAndInitNodes(); - EnsureRenderCaches(); - RefreshVisibilityState(true); - } - - private void OnValidate() - { - renderSubdivisionsIdle = Mathf.Max(renderSubdivisionsIdle, 1); - renderSubdivisionsMoving = Mathf.Max(renderSubdivisionsMoving, 1); - iterations = Mathf.Clamp(iterations, 1, 80); - hardTightenIterations = Mathf.Clamp(hardTightenIterations, 0, 16); - groundCastDistance = Mathf.Max(groundCastDistance, 0.01f); - groundCastHeight = Mathf.Max(groundCastHeight, 0f); - lineWidth = Mathf.Max(lineWidth, 0.0001f); - - lengthSmoothTime = Mathf.Max(lengthSmoothTime, 0.0001f); - - physicsSegmentLen = Mathf.Max(physicsSegmentLen, 0.01f); - minPhysicsNodes = Mathf.Max(minPhysicsNodes, 2); - maxPhysicsNodes = Mathf.Max(maxPhysicsNodes, minPhysicsNodes); - - headMinLen = Mathf.Max(headMinLen, 0.0001f); - nodeHysteresis = Mathf.Max(0f, nodeHysteresis); - - groundSampleStep = Mathf.Max(1, groundSampleStep); - groundUpdateEvery = Mathf.Max(1, groundUpdateEvery); - groundPostConstraintIterations = Mathf.Clamp(groundPostConstraintIterations, 0, 8); - - waterSampleStep = Mathf.Max(1, waterSampleStep); - waterUpdateEvery = Mathf.Max(1, waterUpdateEvery); - waterSurfaceOffset = Mathf.Max(0f, waterSurfaceOffset); - waterLiftStrength = Mathf.Clamp01(waterLiftStrength); - waterPostConstraintIterations = Mathf.Clamp(waterPostConstraintIterations, 0, 8); - visibilityCheckEvery = Mathf.Clamp(visibilityCheckEvery, 1, 60); - visibilityViewportPadding = Mathf.Clamp(visibilityViewportPadding, 0f, 0.5f); - } - - private void RefreshAnchorTransforms() - { - _startTr = startAnchor ? startAnchor.transform : null; - _endTr = endAnchor ? endAnchor.transform : null; - } - - private bool ShouldAlwaysSimulate() - { - if (!localOwnerAlwaysSimulate) - return false; - - var owner = _rod?.PlayerItem?.Owner; - return owner == null || owner.IsSelf; - } - - private Transform GetActiveCameraTransform() - { - Camera main = BaseCamera.Main; - if (main) - { - _cameraTr = main.transform; - return _cameraTr; - } - - if (!_cameraTr) - { - Camera fallback = Camera.main; - if (fallback) - _cameraTr = fallback.transform; - } - - return _cameraTr; - } - - private static bool IsViewportPointVisible(Vector3 viewportPoint, float padding) - { - if (viewportPoint.z <= 0f) - return false; - - return viewportPoint.x >= -padding && viewportPoint.x <= 1f + padding && - viewportPoint.y >= -padding && viewportPoint.y <= 1f + padding; - } - - private bool IsVisibleToMainCamera() - { - Transform camTr = GetActiveCameraTransform(); - if (!camTr) - return true; - - Camera cam = camTr.GetComponent(); - if (!cam) - cam = BaseCamera.Main ? BaseCamera.Main : Camera.main; - if (!cam) - return true; - - Vector3 start = _startTr ? _startTr.position : (startAnchor ? startAnchor.position : transform.position); - Vector3 end = _endTr ? _endTr.position : (endAnchor ? endAnchor.position : transform.position); - Vector3 middle = (start + end) * 0.5f; - float padding = visibilityViewportPadding; - - return IsViewportPointVisible(cam.WorldToViewportPoint(start), padding) || - IsViewportPointVisible(cam.WorldToViewportPoint(end), padding) || - IsViewportPointVisible(cam.WorldToViewportPoint(middle), padding); - } - - private void RefreshVisibilityState(bool force = false) - { - if (!cullRemoteRopeWhenInvisible || ShouldAlwaysSimulate()) - { - _isCulledByVisibility = false; - if (_lineRenderer) - _lineRenderer.enabled = true; - return; - } - - if (!force) - { - _visibilityCheckCounter++; - if (_visibilityCheckCounter < visibilityCheckEvery) - return; - } - - _visibilityCheckCounter = 0; - bool wasCulled = _isCulledByVisibility; - _isCulledByVisibility = !IsVisibleToMainCamera(); - - if (_lineRenderer) - _lineRenderer.enabled = !_isCulledByVisibility; - - if (wasCulled && !_isCulledByVisibility) - SyncVisibleStateAfterCulling(); - } - - private void SyncVisibleStateAfterCulling() - { - _currentLength = Mathf.Max(_targetLength, 0.01f); - UpdateNodesFromLength(); - UpdateHeadRestLenFromCurrentLength(); - ResetNodesBetweenAnchors(); - LockAnchorsHard(); - } - - private void ResetNodesBetweenAnchors() - { - if (_physicsNodes < 2) - return; - - Vector3 start = _startTr ? _startTr.position : (startAnchor ? startAnchor.position : transform.position); - Vector3 end = _endTr ? _endTr.position : (endAnchor ? endAnchor.position : transform.position); - int last = _physicsNodes - 1; - - for (int i = 0; i <= last; i++) - { - float t = (last > 0) ? i / (float)last : 0f; - Vector3 pos = Vector3.Lerp(start, end, t); - _pCurr[i] = pos; - _pPrev[i] = pos; - } - } - - private void EnsureRenderCaches() - { - int idle = Mathf.Max(1, renderSubdivisionsIdle); - if (_tIdleSubdiv != idle) - { - BuildTCaches(idle, ref _tIdle); - _tIdleSubdiv = idle; - } - - int moving = Mathf.Max(1, renderSubdivisionsMoving); - if (_tMovingSubdiv != moving) - { - BuildTCaches(moving, ref _tMoving); - _tMovingSubdiv = moving; - } - - int maxSubdiv = Mathf.Max(idle, moving); - int neededCapacity = (maxPhysicsNodes - 1) * maxSubdiv + 1; - if (_rPoints == null || neededCapacity > _rCapacity) - { - _rCapacity = neededCapacity; - _rPoints = new Vector3[_rCapacity]; - } - } - - private void InitLengthSystem() - { - float defaultLen = physicsSegmentLen * (Mathf.Max(minPhysicsNodes, 2) - 1); - _currentLength = (initialLength > 0f) ? initialLength : defaultLen; - _targetLength = _currentLength; - } - - private void AllocateAndInitNodes() - { - _physicsNodes = Mathf.Clamp(ComputeDesiredNodesStable(_currentLength), 2, maxPhysicsNodes); - - _pCurr = new Vector3[maxPhysicsNodes]; - _pPrev = new Vector3[maxPhysicsNodes]; - - Vector3 start = startAnchor ? startAnchor.position : transform.position; - Vector3 dir = Vector3.down; - - for (int i = 0; i < _physicsNodes; i++) - { - Vector3 pos = start + dir * (physicsSegmentLen * i); - _pCurr[i] = pos; - _pPrev[i] = pos; - } - - UpdateHeadRestLenFromCurrentLength(); - - if (startAnchor && endAnchor) - LockAnchorsHard(); - } - - private int ComputeDesiredNodes(float lengthMeters) - { - int desired = Mathf.RoundToInt(Mathf.Max(0f, lengthMeters) / physicsSegmentLen) + 1; - desired = Mathf.Clamp(desired, minPhysicsNodes, maxPhysicsNodes); - return desired; - } - - private int ComputeDesiredNodesStable(float lengthMeters) - { - int desired = ComputeDesiredNodes(lengthMeters); - - if (_lastDesiredNodes == 0) - { - _lastDesiredNodes = desired; - return desired; - } - - if (desired == _lastDesiredNodes) - return desired; - - float boundary = (_lastDesiredNodes - 1) * physicsSegmentLen; - if (Mathf.Abs(lengthMeters - boundary) < nodeHysteresis) - return _lastDesiredNodes; - - _lastDesiredNodes = desired; - return desired; - } - - public void SetTargetLength(float lengthMeters) => _targetLength = Mathf.Max(0f, lengthMeters); - public float GetCurrentLength() => _currentLength; - public float GetTargetLength() => _targetLength; - public float GetLengthSmoothVel() => _lengthSmoothVel; - - public float GetLengthByPoints() - { - if (!smooth) - return GetPhysicsPolylineLength(); - - if (_rPoints == null || _lineRenderer == null) return 0f; - - int count = _lineRenderer.positionCount; - if (count < 2) return 0f; - - float totalLength = 0f; - for (int i = 1; i < count; i++) - { - Vector3 a = _rPoints[i - 1]; - Vector3 b = _rPoints[i]; - totalLength += Vector3.Distance(a, b); - } - - return totalLength; - } - - public float GetPhysicsPolylineLength() - { - float total = 0f; - for (int i = 1; i < _physicsNodes; i++) - total += Vector3.Distance(_pCurr[i - 1], _pCurr[i]); - return total; - } - - public void DebugLength() - { - float solverRestTotal = (_physicsNodes - 2) * physicsSegmentLen + _headRestLen; - float poly = GetPhysicsPolylineLength(); - float maxSegDelta = 0f; - float avgSegDelta = 0f; - for (int i = 1; i < _physicsNodes; i++) - { - float rest = (i == 1) ? _headRestLen : physicsSegmentLen; - float segLen = Vector3.Distance(_pCurr[i - 1], _pCurr[i]); - float delta = segLen - rest; - if (delta > maxSegDelta) maxSegDelta = delta; - avgSegDelta += delta; - } - - if (_physicsNodes > 1) - avgSegDelta /= (_physicsNodes - 1); - - Debug.Log( - $"current={_currentLength}, target={_targetLength}, nodes={_physicsNodes}, " + - $"seg={physicsSegmentLen}, head={_headRestLen}, headMin={headMinLen}, " + - $"solverRestTotal={solverRestTotal}, poly={poly}, delta={poly - solverRestTotal}, " + - $"maxSegDelta={maxSegDelta}, avgSegDelta={avgSegDelta}" - ); - } - - private void FixedUpdate() - { - if (!startAnchor || !endAnchor) return; - - RefreshAnchorTransforms(); - RefreshVisibilityState(); - if (_isCulledByVisibility) - return; - - _dt = Time.fixedDeltaTime; - if (_dt < 1e-6f) _dt = 1e-6f; - _dt2 = _dt * _dt; - - _gravity.y = -gravityStrength; - - _kY = Mathf.Exp(-airDrag * _dt); - _kXZ = Mathf.Exp(-airDragXZ * _dt); - - UpdateLengthSmooth(); - UpdateNodesFromLength(); - UpdateHeadRestLenFromCurrentLength(); - - Simulate_VerletFast(); - - - for (int it = 0; it < iterations; it++) - { - LockAnchorsHard(); - SolveDistanceConstraints_HeadOnly_Fast(); - } - - SolveHardDistanceConstraints(hardTightenIterations); - LockAnchorsHard(); - - if (constrainToGround) - { - _groundFrameCounter++; - if (_groundFrameCounter >= groundUpdateEvery) - { - _groundFrameCounter = 0; - ConstrainToGround(); - SolveHardDistanceConstraints(groundPostConstraintIterations); - } - } - - if (constrainToWaterSurface) - { - _waterFrameCounter++; - if (_waterFrameCounter >= waterUpdateEvery) - { - _waterFrameCounter = 0; - ConstrainToWaterSurface(); - - // 水面抬升后补几次长度约束,让形状更顺一点 - SolveHardDistanceConstraints(waterPostConstraintIterations); - } - } - - LockAnchorsHard(); - } - - private void Update() - { - if (!startAnchor || !endAnchor || _pCurr == null || _physicsNodes < 2) return; - - RefreshAnchorTransforms(); - if (_isCulledByVisibility) - return; - - EnsureRenderCaches(); - - int last = _physicsNodes - 1; - - Vector3 s = _startTr.position; - Vector3 e = _endTr.position; - - _pCurr[0] = s; - _pCurr[last] = e; - // _pPrev[0] = s; - // _pPrev[last] = e; - - DrawHighResLine_Fast(); - } - - private void UpdateLengthSmooth() - { - float minFeasible = 0.01f; - float desired = Mathf.Max(_targetLength, minFeasible); - - _currentLength = Mathf.SmoothDamp( - _currentLength, - desired, - ref _lengthSmoothVel, - lengthSmoothTime, - Mathf.Infinity, - Time.fixedDeltaTime - ); - - // 长度变化时额外压一点速度,减少收放线时抖动 - float delta = Mathf.Abs(_targetLength - _currentLength); - if (delta > 0.0001f && lengthChangeVelocityKill > 0f) - { - float keep = 1f - Mathf.Clamp01(lengthChangeVelocityKill); - for (int i = 1; i < _physicsNodes - 1; i++) - { - Vector3 curr = _pCurr[i]; - Vector3 prev = _pPrev[i]; - Vector3 disp = curr - prev; - _pPrev[i] = curr - disp * keep; - } - } - } - - private void UpdateNodesFromLength() - { - int desired = ComputeDesiredNodesStable(_currentLength); - desired = Mathf.Clamp(desired, 2, maxPhysicsNodes); - if (desired == _physicsNodes) return; - - if (desired > _physicsNodes) AddNodesAtStart(desired - _physicsNodes); - else RemoveNodesAtStart(_physicsNodes - desired); - - _physicsNodes = desired; - } - - private void AddNodesAtStart(int addCount) - { - if (addCount <= 0) return; - - int oldCount = _physicsNodes; - int newCount = Mathf.Min(oldCount + addCount, maxPhysicsNodes); - addCount = newCount - oldCount; - if (addCount <= 0) return; - - Array.Copy(_pCurr, 1, _pCurr, 1 + addCount, oldCount - 1); - Array.Copy(_pPrev, 1, _pPrev, 1 + addCount, oldCount - 1); - - Vector3 s = _startTr ? _startTr.position : startAnchor.position; - - Vector3 dir = Vector3.down; - int firstOld = 1 + addCount; - if (oldCount >= 2 && firstOld < maxPhysicsNodes) - { - Vector3 toOld1 = (_pCurr[firstOld] - s); - float sq = toOld1.sqrMagnitude; - if (sq > 1e-6f) dir = toOld1 / Mathf.Sqrt(sq); - } - - Vector3 inheritDisp = Vector3.zero; - if (oldCount >= 2 && firstOld < maxPhysicsNodes) - inheritDisp = (_pCurr[firstOld] - _pPrev[firstOld]); - - for (int k = 1; k <= addCount; k++) - { - Vector3 pos = s + dir * (physicsSegmentLen * k); - _pCurr[k] = pos; - _pPrev[k] = pos - inheritDisp; - } - - LockAnchorsHard(); - } - - private void RemoveNodesAtStart(int removeCount) - { - if (removeCount <= 0) return; - - int oldCount = _physicsNodes; - int newCount = Mathf.Max(oldCount - removeCount, 2); - removeCount = oldCount - newCount; - if (removeCount <= 0) return; - - Array.Copy(_pCurr, 1 + removeCount, _pCurr, 1, newCount - 2); - Array.Copy(_pPrev, 1 + removeCount, _pPrev, 1, newCount - 2); - - LockAnchorsHard(); - } - - private void UpdateHeadRestLenFromCurrentLength() - { - int fixedSegCount = Mathf.Max(0, _physicsNodes - 2); - float baseLen = fixedSegCount * physicsSegmentLen; - - _headRestLen = _currentLength - baseLen; - _headRestLen = Mathf.Clamp(_headRestLen, headMinLen, physicsSegmentLen * 1.5f); - } - - private void Simulate_VerletFast() - { - for (int i = 1; i < _physicsNodes - 1; i++) - { - Vector3 disp = _pCurr[i] - _pPrev[i]; - - disp.x *= _kXZ; - disp.z *= _kXZ; - disp.y *= _kY; - - disp *= velocityDampen; - - Vector3 next = _pCurr[i] + disp + _gravity * _dt2; - - _pPrev[i] = _pCurr[i]; - _pCurr[i] = next; - } - } - - private void LockAnchorsHard() - { - if (!startAnchor || !endAnchor || _pCurr == null || _pPrev == null || _physicsNodes < 2) return; - - Vector3 s = _startTr ? _startTr.position : startAnchor.position; - Vector3 e = _endTr ? _endTr.position : endAnchor.position; - - _pCurr[0] = s; - _pPrev[0] = s - startAnchor.linearVelocity * _dt; - - int last = _physicsNodes - 1; - _pCurr[last] = e; - _pPrev[last] = e - endAnchor.linearVelocity * _dt; - } - - private void SolveDistanceConstraints_HeadOnly_Fast() - { - SolveDistanceConstraints_HeadOnly_Bidirectional(stiffness); - } - - private void SolveHardDistanceConstraints(int extraIterations) - { - for (int it = 0; it < extraIterations; it++) - { - LockAnchorsHard(); - SolveDistanceConstraints_HeadOnly_Hard(); - } - } - - private void SolveDistanceConstraints_HeadOnly_Hard() - { - SolveDistanceConstraints_HeadOnly_Bidirectional(1f); - } - - private void SolveDistanceConstraints_HeadOnly_Bidirectional(float combinedStiffness) - { - int last = _physicsNodes - 1; - if (last <= 0) return; - - float clamped = Mathf.Clamp01(combinedStiffness); - float sweepStiffness = (clamped >= 0.999999f) ? 1f : 1f - Mathf.Sqrt(1f - clamped); - SolveDistanceConstraintsSweep_Fast(0, last, 1, last, sweepStiffness); - SolveDistanceConstraintsSweep_Fast(last - 1, -1, -1, last, sweepStiffness); - } - - private void SolveDistanceConstraintsSweep_Fast(int start, int endExclusive, int step, int last, float sweepStiffness) - { - for (int i = start; i != endExclusive; i += step) - { - float rest = (i == 0) ? _headRestLen : physicsSegmentLen; - - Vector3 a = _pCurr[i]; - Vector3 b = _pCurr[i + 1]; - - Vector3 delta = b - a; - float sq = delta.sqrMagnitude; - if (sq < 1e-12f) continue; - - float dist = Mathf.Sqrt(sq); - float diff = (dist - rest) / dist; - Vector3 corr = delta * (diff * sweepStiffness); - - bool aLocked = (i == 0); - bool bLocked = (i + 1 == last); - - if (!aLocked && !bLocked) - { - _pCurr[i] = a + corr * 0.5f; - _pCurr[i + 1] = b - corr * 0.5f; - } - else if (aLocked && !bLocked) - { - _pCurr[i + 1] = b - corr; // 首段:node1 吃满 - } - else if (!aLocked) - { - _pCurr[i] = a + corr; // 尾段:last-1 吃满 - } - // 两边都锁的情况理论上不会出现 - } - } - - private void ConstrainToGround() - { - if (groundMask == 0) return; - - int last = _physicsNodes - 1; - int step = Mathf.Max(1, groundSampleStep); - - int prevSampleIdx = 1; - float prevMinY = SampleMinY(_pCurr[prevSampleIdx]); - - ApplyMinY(prevSampleIdx, prevMinY); - - for (int i = 1 + step; i < last; i += step) - { - float nextMinY = SampleMinY(_pCurr[i]); - ApplyMinY(i, nextMinY); - - if (groundInterpolate) - { - int a = prevSampleIdx; - int b = i; - int span = b - a; - for (int j = 1; j < span; j++) - { - int idx = a + j; - float t = j / (float)span; - float minY = Mathf.Lerp(prevMinY, nextMinY, t); - ApplyMinY(idx, minY); - } - } - else - { - for (int idx = prevSampleIdx + 1; idx < i; idx++) - ApplyMinY(idx, prevMinY); - } - - prevSampleIdx = i; - prevMinY = nextMinY; - } - - for (int i = prevSampleIdx + 1; i < last; i++) - ApplyMinY(i, prevMinY); - } - - private float SampleMinY(Vector3 p) - { - Vector3 origin = p + Vector3.up * groundCastHeight; - if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, groundCastDistance, groundMask, - QueryTriggerInteraction.Ignore)) - return hit.point.y + groundRadius; - - return float.NegativeInfinity; - } - - private void ApplyMinY(int i, float minY) - { - if (float.IsNegativeInfinity(minY)) return; - - Vector3 p = _pCurr[i]; - if (p.y < minY) - { - p.y = minY; - _pCurr[i] = p; - - // prev 同步抬上来,避免下一帧又被惯性拉回去造成抖动 - Vector3 prev = _pPrev[i]; - if (prev.y < minY) prev.y = minY; - _pPrev[i] = prev; - } - } - - private void ConstrainToWaterSurface() - { - int last = _physicsNodes - 1; - if (last <= 1) return; - - int step = Mathf.Max(1, waterSampleStep); - float surfaceY = waterLevelY + waterSurfaceOffset; - bool startUnderWater = _pCurr[0].y < surfaceY; - int startAdjacentIdx = GetStartAdjacentNodeIndex(last); - - int prevSampleIdx = 1; - float prevSurfaceY = surfaceY; - - ApplyWaterSurface(prevSampleIdx, prevSurfaceY, startUnderWater, startAdjacentIdx); - - for (int i = 1 + step; i < last; i += step) - { - float nextSurfaceY = surfaceY; - ApplyWaterSurface(i, nextSurfaceY, startUnderWater, startAdjacentIdx); - - if (waterInterpolate) - { - int a = prevSampleIdx; - int b = i; - int span = b - a; - for (int j = 1; j < span; j++) - { - int idx = a + j; - float t = j / (float)span; - float y = Mathf.Lerp(prevSurfaceY, nextSurfaceY, t); - ApplyWaterSurface(idx, y, startUnderWater, startAdjacentIdx); - } - } - else - { - for (int idx = prevSampleIdx + 1; idx < i; idx++) - ApplyWaterSurface(idx, prevSurfaceY, startUnderWater, startAdjacentIdx); - } - - prevSampleIdx = i; - prevSurfaceY = nextSurfaceY; - } - - for (int i = prevSampleIdx + 1; i < last; i++) - ApplyWaterSurface(i, prevSurfaceY, startUnderWater, startAdjacentIdx); - } - - private int GetStartAdjacentNodeIndex(int last) - { - if (last <= 1) return 1; - - Vector3 s = _pCurr[0]; - float d1 = (_pCurr[1] - s).sqrMagnitude; - float d2 = (_pCurr[last - 1] - s).sqrMagnitude; - return d1 <= d2 ? 1 : last - 1; - } - - private void ApplyWaterSurface(int i, float surfaceY, bool startUnderWater, int startAdjacentIdx) - { - if (keepStartAdjacentNodeFollow && startUnderWater && i == startAdjacentIdx) - { - Vector3 s = _pCurr[0]; - _pCurr[i] = s; - _pPrev[i] = s; - return; - } - - Vector3 p = _pCurr[i]; - if (p.y < surfaceY) - { - p.y = Mathf.Lerp(p.y, surfaceY, waterLiftStrength); - _pCurr[i] = p; - - // 渐进同步 prev,削弱向下惯性,避免反复穿透水面 - Vector3 prev = _pPrev[i]; - if (prev.y < p.y) prev.y = Mathf.Lerp(prev.y, p.y, waterLiftStrength); - _pPrev[i] = prev; - } - } - - private void DrawHighResLine_Fast() - { - if (_pCurr == null || _physicsNodes < 2) return; - - float w = lineWidth * LineMultiple; - _lineRenderer.startWidth = w; - _lineRenderer.endWidth = w; - - if (!smooth) - { - _lineRenderer.positionCount = _physicsNodes; - _lineRenderer.SetPositions(_pCurr); - return; - } - - int subdiv = PickRenderSubdivisions_Fast(); - TCaches tc = (subdiv == renderSubdivisionsMoving) ? _tMoving : _tIdle; - - int needed = (_physicsNodes - 1) * subdiv + 1; - if (needed > _rCapacity) - { - _rCapacity = needed; - _rPoints = new Vector3[_rCapacity]; - } - - int idx = 0; - int last = _physicsNodes - 1; - - for (int seg = 0; seg < last; seg++) - { - int i0 = seg - 1; - if (i0 < 0) i0 = 0; - int i1 = seg; - int i2 = seg + 1; - int i3 = seg + 2; - if (i3 > last) i3 = last; - - Vector3 p0 = _pCurr[i0]; - Vector3 p1 = _pCurr[i1]; - Vector3 p2 = _pCurr[i2]; - Vector3 p3 = _pCurr[i3]; - - for (int s = 0; s < subdiv; s++) - { - float t = tc.t[s]; - float t2 = tc.t2[s]; - float t3 = tc.t3[s]; - - Vector3 cr = - 0.5f * ( - (2f * p1) + - (-p0 + p2) * t + - (2f * p0 - 5f * p1 + 4f * p2 - p3) * t2 + - (-p0 + 3f * p1 - 3f * p2 + p3) * t3 - ); - - // y 也使用平滑曲线,再做单调夹紧;避免垂直时因为线性 y 插值导致切线断裂,看起来像折线。 - cr.y = ClampMonotonic(cr.y, p0.y, p1.y, p2.y, p3.y); - - _rPoints[idx++] = cr; - } - } - - _rPoints[idx++] = _pCurr[last]; - - _lineRenderer.positionCount = idx; - _lineRenderer.SetPositions(_rPoints); - } - - private static float ClampMonotonic(float value, float p0, float p1, float p2, float p3) - { - bool rising = p0 <= p1 && p1 <= p2 && p2 <= p3; - bool falling = p0 >= p1 && p1 >= p2 && p2 >= p3; - if (!rising && !falling) - return value; - - float min = Mathf.Min(p1, p2); - float max = Mathf.Max(p1, p2); - return Mathf.Clamp(value, min, max); - } - - private int PickRenderSubdivisions_Fast() - { - int idle = Mathf.Max(1, renderSubdivisionsIdle); - int moving = Mathf.Max(1, renderSubdivisionsMoving); - - float thr = movingSpeedThreshold; - float thrSq = (thr * _dt) * (thr * _dt); - - float sumSq = 0f; - int count = Mathf.Max(1, _physicsNodes - 2); - - for (int i = 1; i < _physicsNodes - 1; i++) - { - Vector3 disp = _pCurr[i] - _pPrev[i]; - sumSq += disp.sqrMagnitude; - } - - float avgSq = sumSq / count; - - return (avgSq > thrSq) ? moving : idle; - } - - private static void BuildTCaches(int subdiv, ref TCaches caches) - { - subdiv = Mathf.Max(1, subdiv); - caches.t = new float[subdiv]; - caches.t2 = new float[subdiv]; - caches.t3 = new float[subdiv]; - - float inv = 1f / subdiv; - for (int s = 0; s < subdiv; s++) - { - float t = s * inv; - float t2 = t * t; - caches.t[s] = t; - caches.t2[s] = t2; - caches.t3[s] = t2 * t; - } - } - - private void OnDrawGizmosSelected() - { - if (_pCurr == null) return; - Gizmos.color = Color.yellow; - for (int i = 0; i < _physicsNodes; i++) - Gizmos.DrawSphere(_pCurr[i], 0.01f); - } -} diff --git a/Assets/Scripts/Fishing/Rope/Rope.cs.meta b/Assets/Scripts/Fishing/Rope/Rope.cs.meta deleted file mode 100644 index 93d4824f7..000000000 --- a/Assets/Scripts/Fishing/Rope/Rope.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 98ba9d435a0e49c9bb527c34cc91894d -timeCreated: 1766759607 \ No newline at end of file diff --git a/Assets/Scripts/Test.meta b/Assets/Scripts/Test.meta deleted file mode 100644 index ecd875801..000000000 --- a/Assets/Scripts/Test.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2d71eb3d89064cc4aab3317e49dc3979 -timeCreated: 1772097895 \ No newline at end of file diff --git a/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs b/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs deleted file mode 100644 index 661d43614..000000000 --- a/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs +++ /dev/null @@ -1,209 +0,0 @@ -using UnityEngine; - -public interface IWaterProvider -{ - float GetWaterHeight(Vector3 worldPos); - Vector3 GetWaterNormal(Vector3 worldPos); - Vector3 GetWaterVelocity(Vector3 worldPos); -} -// -// /// -// /// 稳定优先的浮力(只支持 CapsuleCollider / SphereCollider) -// /// - 竖直方向:目标吃水深度 + PD 控制(稳定,不抖、不弹飞) -// /// - 姿态:Righting Torque 扶正(受 Rigidbody.centerOfMass 影响) -// /// - 入水比例:带平滑(避免水面附近开关抖动) -// /// -// [DisallowMultipleComponent] -// [RequireComponent(typeof(Rigidbody))] -// public class BuoyancyCapsuleSphere : MonoBehaviour -// { -// [Header("Collider (choose one)")] public CapsuleCollider capsule; -// public SphereCollider sphere; -// -// [Header("Water")] public MonoBehaviour waterProviderBehaviour; // 可选 -// private IWaterProvider waterProvider; -// -// [Tooltip("没有 provider 时的水面高度")] public float waterLevel = 0f; -// -// [Header("Density -> Draft")] [Tooltip("水密度 kg/m^3(淡水约1000)")] -// public float waterDensity = 1000f; -// -// [Tooltip("物体等效密度 kg/m^3。越小越浮。浮漂可 80~400 之间调")] -// public float objectDensity = 250f; -// -// [Tooltip("额外浮力比例(手感调整)。1=按密度算")] public float buoyancyScale = 1f; -// -// [Header("Vertical PD (Stability key)")] [Tooltip("竖直弹簧强度(越大越“顶住”目标吃水)")] -// public float verticalKp = 35f; -// -// [Tooltip("竖直阻尼(越大越不弹、不抖)")] public float verticalKd = 12f; -// -// [Tooltip("最大向上加速度 m/s^2(防止从高处落下入水被顶飞)")] -// public float maxUpAccel = 25f; -// -// [Tooltip("最大向下加速度 m/s^2(防止强行拉下去造成抖动)")] -// public float maxDownAccel = 10f; -// -// [Header("Submergence smoothing")] [Tooltip("入水比例变化速度(1/s)。越大越快响应,越小越稳")] -// public float submergenceSpeed = 8f; -// -// [Tooltip("水面外的缓冲(m),让浮力更平滑接管")] public float surfaceMargin = 0.01f; -// -// [Header("Righting (Rotation)")] [Tooltip("扶正强度(把 transform.up 拉向水面法线/世界上)")] -// public float rightingKp = 8f; -// -// [Tooltip("扶正阻尼(抑制旋转抖动)")] public float rightingKd = 3f; -// -// [Header("Water drag (optional but helpful)")] [Tooltip("入水时额外线阻尼(通过 rb.drag 混合)")] -// public float extraLinearDragInWater = 2.5f; -// -// [Tooltip("入水时额外角阻尼(通过 rb.angularDrag 混合)")] -// public float extraAngularDragInWater = 2.0f; -// -// [Header("Center of Mass")] [Tooltip("本地重心偏移:例如 (0,-0.02,0) 让底部更重、更容易站漂")] -// public Vector3 centerOfMassOffset = Vector3.zero; -// -// private Rigidbody rb; -// private float baseDrag, baseAngularDrag; -// -// // 关键:入水比例必须有“记忆”(滤波),否则水面边界必抖 -// private float subFiltered = 0f; -// -// void Reset() -// { -// rb = GetComponent(); -// rb.useGravity = true; -// rb.interpolation = RigidbodyInterpolation.Interpolate; -// rb.collisionDetectionMode = CollisionDetectionMode.Continuous; -// -// capsule = GetComponent(); -// sphere = GetComponent(); -// } -// -// void Awake() -// { -// rb = GetComponent(); -// rb.centerOfMass = centerOfMassOffset; -// -// baseDrag = rb.linearDamping; -// baseAngularDrag = rb.angularDamping; -// -// waterProvider = waterProviderBehaviour as IWaterProvider; -// -// // 只允许一个 -// if (capsule != null && sphere != null) -// sphere = null; -// } -// -// void OnValidate() -// { -// objectDensity = Mathf.Max(1e-3f, objectDensity); -// waterDensity = Mathf.Max(1e-3f, waterDensity); -// submergenceSpeed = Mathf.Max(0.1f, submergenceSpeed); -// surfaceMargin = Mathf.Max(0f, surfaceMargin); -// maxUpAccel = Mathf.Max(0f, maxUpAccel); -// maxDownAccel = Mathf.Max(0f, maxDownAccel); -// } -// -// void FixedUpdate() -// { -// if (!capsule && !sphere) return; -// -// waterProvider = waterProviderBehaviour as IWaterProvider; -// -// GetCenterAndHeight(out var centerWorld, out var shapeHeight); -// -// // 水面信息 -// float waterH = waterProvider?.GetWaterHeight(centerWorld) ?? waterLevel; -// Vector3 waterN = waterProvider?.GetWaterNormal(centerWorld) ?? Vector3.up; -// if (waterN.sqrMagnitude < 1e-6f) waterN = Vector3.up; -// waterN.Normalize(); -// -// // 当前中心“浸没深度”(>0 表示中心在水下) -// float centerDepth = waterH - centerWorld.y; -// -// // 近似入水比例:centerDepth = -H/2 -> 0; centerDepth = +H/2 -> 1 -// float rawSub = Mathf.Clamp01((centerDepth + (shapeHeight * 0.5f) + surfaceMargin) / -// (shapeHeight + 2f * surfaceMargin)); -// -// // 入水比例滤波(非常关键) -// float dt = Time.fixedDeltaTime; -// subFiltered = Mathf.MoveTowards(subFiltered, rawSub, submergenceSpeed * dt); -// -// // 混合拖拽(让水中更稳) -// rb.linearDamping = Mathf.Lerp(baseDrag, baseDrag + extraLinearDragInWater, subFiltered); -// rb.angularDamping = Mathf.Lerp(baseAngularDrag, baseAngularDrag + extraAngularDragInWater, subFiltered); -// -// if (subFiltered <= 1e-4f) -// return; // 基本没入水,不做任何浮力/扶正 -// -// // 目标吃水比例:理想静态平衡 ≈ objectDensity / waterDensity(<1 才会浮) -// float desiredSub = Mathf.Clamp01((objectDensity / waterDensity) * buoyancyScale); -// -// // 把 desiredSub 转成目标中心深度 -// // desiredSub=0 -> centerDepthTarget = -H/2(完全出水) -// // desiredSub=1 -> centerDepthTarget = +H/2(完全入水) -// float centerDepthTarget = desiredSub * shapeHeight - shapeHeight * 0.5f; -// -// // 竖直 PD:只沿“世界上/重力反方向”控制,最稳 -// Vector3 up = (-Physics.gravity).sqrMagnitude > 1e-6f ? (-Physics.gravity).normalized : Vector3.up; -// float vUp = Vector3.Dot(rb.linearVelocity, up); -// -// float error = centerDepth - centerDepthTarget; // 深了为正 -> 需要向上推 -// float accelUp = (-verticalKp * error) - (verticalKd * vUp); -// -// // 限制上下加速度,避免顶飞或强拉抖动 -// accelUp = Mathf.Clamp(accelUp, -maxDownAccel, maxUpAccel); -// -// // 随入水比例渐入(避免水面边界突然接管) -// accelUp *= subFiltered; -// -// // 施加竖直加速度(Acceleration 不受质量影响,更稳定) -// rb.AddForce(up * accelUp, ForceMode.Acceleration); -// -// // 扶正力矩:把物体 up 拉向 waterN(平静水就是 Vector3.up) -// // 注意:这个扶正与重心偏移一起工作,会形成“站漂/躺漂”的稳定姿态 -// Vector3 currentUp = transform.up; -// Vector3 axis = Vector3.Cross(currentUp, waterN); -// -// // 小角度近似:axis 的大小约等于 sin(theta) -// // 扶正加速度型扭矩(同样用 Acceleration,减少质量/惯量差带来的抖动) -// Vector3 angVel = rb.angularVelocity; -// Vector3 torqueAccel = axis * rightingKp - angVel * rightingKd; -// -// torqueAccel *= subFiltered; -// -// rb.AddTorque(torqueAccel, ForceMode.Acceleration); -// } -// -// private void GetCenterAndHeight(out Vector3 centerWorld, out float heightWorld) -// { -// if (sphere) -// { -// // sphere:center + 半径*缩放(近似取最大缩放) -// Transform t = sphere.transform; -// centerWorld = t.TransformPoint(sphere.center); -// -// Vector3 s = t.lossyScale; -// float r = sphere.radius * Mathf.Max(Mathf.Abs(s.x), Mathf.Abs(s.y), Mathf.Abs(s.z)); -// heightWorld = Mathf.Max(1e-6f, r * 2f); -// return; -// } -// -// // capsule -// Transform ct = capsule.transform; -// centerWorld = ct.TransformPoint(capsule.center); -// -// Vector3 ls = ct.lossyScale; -// float sx = Mathf.Abs(ls.x), sy = Mathf.Abs(ls.y), sz = Mathf.Abs(ls.z); -// -// float heightScale = capsule.direction switch -// { -// 0 => sx, -// 1 => sy, -// _ => sz, -// }; -// -// heightWorld = Mathf.Max(1e-6f, capsule.height * heightScale); -// } -// } \ No newline at end of file diff --git a/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs.meta b/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs.meta deleted file mode 100644 index b45fa287e..000000000 --- a/Assets/Scripts/Test/BuoyancyCapsuleSphere.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bad586cd447d4271b97ce1cf1c81897a -timeCreated: 1772460028 \ No newline at end of file diff --git a/Assets/Scripts/Test/BuoyancyWaterProvider.cs b/Assets/Scripts/Test/BuoyancyWaterProvider.cs deleted file mode 100644 index f4af21b5f..000000000 --- a/Assets/Scripts/Test/BuoyancyWaterProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UnityEngine; -using WaveHarmonic.Crest; - -public class BuoyancyWaterProvider : MonoBehaviour, IWaterProvider -{ - public WaterRenderer Water; - readonly SampleFlowHelper _SampleFlowHelper = new(); - public float waterLevel = 0f; - - public float GetWaterHeight(Vector3 worldPos) - { - return waterLevel; - } - - public Vector3 GetWaterNormal(Vector3 worldPos) - { - return Vector3.up; - } - - public Vector3 GetWaterVelocity(Vector3 worldPos) - { - return Vector3.zero; // 关键!不要乱给 - } -} \ No newline at end of file diff --git a/Assets/Scripts/Test/BuoyancyWaterProvider.cs.meta b/Assets/Scripts/Test/BuoyancyWaterProvider.cs.meta deleted file mode 100644 index 8909ca2ed..000000000 --- a/Assets/Scripts/Test/BuoyancyWaterProvider.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 06d107cece7c4cbb9825557923be567f -timeCreated: 1772380723 \ No newline at end of file diff --git a/Assets/Scripts/Test/CapsuleBuoyancyStable.cs b/Assets/Scripts/Test/CapsuleBuoyancyStable.cs deleted file mode 100644 index 7e0599735..000000000 --- a/Assets/Scripts/Test/CapsuleBuoyancyStable.cs +++ /dev/null @@ -1,268 +0,0 @@ -using System; -using UnityEngine; -using WaveHarmonic.Crest; - -[DisallowMultipleComponent] -[RequireComponent(typeof(Rigidbody))] -public class CapsuleBuoyancyStable : MonoBehaviour -{ - [Header("Buoyancy")] [Tooltip("完全浸没时总浮力 = mass*g*buoyancyScale。>1 更浮。")] - public float buoyancyScale = 1.6f; - - [Tooltip("沿胶囊轴向采样点数量(建议 7~11)。")] [Range(3, 15)] - public int samplePoints = 9; - - [Tooltip("浸没比例曲线(0=刚碰水, 1=充分在水下)。")] public AnimationCurve submergenceCurve = AnimationCurve.Linear(0, 0, 1, 1); - - [Header("Damping")] [Tooltip("上浮方向速度阻尼(越大越不弹)。本版本:只在“浮力中心”施加一次,不再在每个采样点施加,避免90°附近转不动。")] - public float verticalDamping = 0.6f; - - [Tooltip("整体角速度阻尼(只施加一次,不要太大)。")] public float angularDamping = 0.6f; - - [Header("Optional Upright Stabilizer (Recommended for bobber)")] [Tooltip("让胶囊轴向更倾向于对齐世界Up。0=关闭。")] - public float uprightSpring = 0.0f; - - [Tooltip("upright 的角速度阻尼。")] public float uprightDamping = 0.5f; - - [Tooltip("胶囊轴向:0=X,1=Y,2=Z(通常 CapsuleCollider.direction 也一样)。")] - public int uprightAxis = 1; - - [Header("Water Drag")] public float extraDragInWater = 0.8f; - public float extraAngularDragInWater = 0.8f; - - [Header("Anti-stiction near upright")] - [Tooltip("在接近竖直(例如90->80度附近)时,降低vertical damping,避免“粘住”。0=关闭。")] - [Range(0f, 1f)] - public float nearUprightDampingReduce = 0.6f; - - [Tooltip("接近竖直的判定角度(度)。例如 12 表示在 |angle| < 12° 附近逐步降低阻尼。")] [Range(1f, 30f)] - public float nearUprightAngleDeg = 12f; - - #region Crest5相关信息 - - public WaterRenderer _waterRenderer; - - [Tooltip("要瞄准哪一层水的碰撞层。")] [SerializeField] - CollisionLayer _Layer = CollisionLayer.AfterAnimatedWaves; - - [Header("波响应")] [Tooltip("用于物理计算的物体宽度。\n\n此值越大,波响应的滤波效果和平滑程度就越高。如果无法对较大波长进行滤波,则应增加 LOD 级别。")] [SerializeField] - float _ObjectWidth = 3f; - - readonly SampleFlowHelper _SampleFlowHelper = new(); - - Vector3[] _QueryPoints; - Vector3[] _QueryResultDisplacements; - Vector3[] _QueryResultVelocities; - Vector3[] _QueryResultNormal; - - #endregion - - [Header("Debug")] public bool drawDebug = false; - - Rigidbody _rb; - CapsuleCollider _cap; - float _baseDrag, _baseAngularDrag; - - [SerializeField] private bool _init = false; - - void Awake() - { - _rb = GetComponent(); - _baseDrag = _rb.linearDamping; - _baseAngularDrag = _rb.angularDamping; - } - - void Start() - { - int length = Mathf.Max(3, samplePoints); - _QueryPoints = new Vector3[length]; - _QueryResultDisplacements = new Vector3[length]; - _QueryResultVelocities = new Vector3[length]; - _QueryResultNormal = new Vector3[length]; - - } - - public void InitBobber() - { - if (_waterRenderer == null && SceneSettings.Instance) - { - _waterRenderer = SceneSettings.Instance.Water; - } - _cap = GetComponentInChildren(); - _init = true; - } - - void FixedUpdate() - { - if (!_init) return; - if (!_waterRenderer) return; - - GetWorldCapsule(out Vector3 a, out Vector3 b, out float radius); - - int n = Mathf.Max(3, samplePoints); - if (_QueryPoints == null || _QueryPoints.Length != n) - { - _QueryPoints = new Vector3[n]; - _QueryResultDisplacements = new Vector3[n]; - _QueryResultVelocities = new Vector3[n]; - _QueryResultNormal = new Vector3[n]; - } - - float fullBuoyancy = _rb.mass * Physics.gravity.magnitude * buoyancyScale; - float perPointMax = fullBuoyancy / n; - - // 采样点 - for (int i = 0; i < n; i++) - { - float t = (float)i / (n - 1); - _QueryPoints[i] = Vector3.Lerp(a, b, t); - } - - // Crest 查询 - var collisions = _waterRenderer.AnimatedWavesLod.Provider; - collisions.Query(GetHashCode(), _ObjectWidth, _QueryPoints, _QueryResultDisplacements, - _QueryResultNormal, _QueryResultVelocities, _Layer); - - float subSum = 0f; - int wetCount = 0; - - // 用于计算“浮力中心”(Center of Buoyancy)与水流速度平均 - Vector3 cobSum = Vector3.zero; - Vector3 wvSum = Vector3.zero; - float cobW = 0f; - - // 1) 多点只加浮力(不再在每点加vertical damping) - for (int i = 0; i < n; i++) - { - Vector3 p = _QueryPoints[i]; - - float waterH = _QueryResultDisplacements[i].y + _waterRenderer.SeaLevel; - float depth = waterH - p.y; - - float sub = Mathf.InverseLerp(-radius, radius, depth); - if (sub <= 0f) continue; - - sub = Mathf.Clamp01(submergenceCurve.Evaluate(sub)); - - subSum += sub; - wetCount++; - - cobSum += p * sub; - wvSum += _QueryResultVelocities[i] * sub; - cobW += sub; - - Vector3 buoyForce = Vector3.up * (perPointMax * sub); - _rb.AddForceAtPosition(buoyForce, p, ForceMode.Force); - - if (drawDebug) - { - Debug.DrawLine(p, p + buoyForce / (_rb.mass * 10f), Color.cyan, 0f, false); - } - } - - float subAvg = (wetCount > 0) ? (subSum / wetCount) : 0f; - - // 2) vertical damping:只在“浮力中心”施加一次(关键修复:不再产生抑制旋转的力矩) - if (subAvg > 0f && cobW > 1e-6f) - { - Vector3 cob = cobSum / cobW; - Vector3 waterVelAvg = wvSum / cobW; - - // 接近竖直时降低vertical damping,避免90->80度“粘住” - float vdScale = 1f; - if (nearUprightDampingReduce > 0f) - { - Vector3 axisWorld = GetAxisWorld(uprightAxis); - float angleFromUp = Vector3.Angle(axisWorld, Vector3.up); // 0=竖直 - float t = Mathf.Clamp01(angleFromUp / Mathf.Max(0.001f, nearUprightAngleDeg)); - // t=0(很竖直) -> 1(离开竖直) - vdScale = Mathf.Lerp(1f - nearUprightDampingReduce, 1f, t); - } - - Vector3 pointVel = _rb.GetPointVelocity(cob); - Vector3 relVel = pointVel - waterVelAvg; - float vUp = Vector3.Dot(relVel, Vector3.up); - - Vector3 dampForce = -Vector3.up * (vUp * verticalDamping * _rb.mass * subAvg * vdScale); - _rb.AddForceAtPosition(dampForce, cob, ForceMode.Force); - - if (drawDebug) - { - Debug.DrawLine(cob, cob + dampForce / (_rb.mass * 10f), Color.yellow, 0f, false); - } - } - - // 3) 角阻尼:只加一次 - if (subAvg > 0f) - { - _rb.AddTorque(-_rb.angularVelocity * (angularDamping * _rb.mass * subAvg), ForceMode.Force); - } - - // 4) upright(保持你原逻辑) - if (subAvg > 0f && uprightSpring > 0f) - { - Vector3 axisWorld = GetAxisWorld(uprightAxis); - Vector3 targetUp = Vector3.up; - - Vector3 errorAxis = Vector3.Cross(axisWorld, targetUp); - float errorMag = errorAxis.magnitude; - - if (errorMag > 1e-6f) - { - errorAxis /= errorMag; - - Vector3 springTorque = errorAxis * (uprightSpring * errorMag * _rb.mass); - Vector3 dampTorque = -_rb.angularVelocity * (uprightDamping * _rb.mass); - - _rb.AddTorque((springTorque + dampTorque) * subAvg, ForceMode.Force); - } - } - - // 5) 入水 drag - if (subAvg > 0.001f) - { - _rb.linearDamping = _baseDrag + extraDragInWater * subAvg; - _rb.angularDamping = _baseAngularDrag + extraAngularDragInWater * subAvg; - } - else - { - _rb.linearDamping = _baseDrag; - _rb.angularDamping = _baseAngularDrag; - } - } - - Vector3 GetAxisWorld(int axis) - { - return axis switch - { - 0 => transform.right, - 2 => transform.forward, - _ => transform.up, - }; - } - - void GetWorldCapsule(out Vector3 a, out Vector3 b, out float radius) - { - Vector3 lossy = transform.lossyScale; - int dir = _cap.direction; - - float scaleAlong = (dir == 0) ? Mathf.Abs(lossy.x) : (dir == 1) ? Mathf.Abs(lossy.y) : Mathf.Abs(lossy.z); - - float scaleR; - if (dir == 0) scaleR = Mathf.Max(Mathf.Abs(lossy.y), Mathf.Abs(lossy.z)); - else if (dir == 1) scaleR = Mathf.Max(Mathf.Abs(lossy.x), Mathf.Abs(lossy.z)); - else scaleR = Mathf.Max(Mathf.Abs(lossy.x), Mathf.Abs(lossy.y)); - - radius = _cap.radius * scaleR; - - Vector3 center = transform.TransformPoint(_cap.center); - Vector3 axisWorld = (dir == 0) ? transform.right : (dir == 1) ? transform.up : transform.forward; - - float heightWorld = Mathf.Max(0f, _cap.height * scaleAlong); - float cylinderLen = Mathf.Max(0f, heightWorld - 2f * radius); - - Vector3 half = axisWorld * (cylinderLen * 0.5f); - a = center - half; - b = center + half; - } -} \ No newline at end of file diff --git a/Assets/Scripts/Test/CapsuleBuoyancyStable.cs.meta b/Assets/Scripts/Test/CapsuleBuoyancyStable.cs.meta deleted file mode 100644 index 1baa145b5..000000000 --- a/Assets/Scripts/Test/CapsuleBuoyancyStable.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f91c9d873c83492ca6d5e3e3a67c1760 -timeCreated: 1772522093 \ No newline at end of file diff --git a/Assets/Scripts/Test/CollisionTest.cs b/Assets/Scripts/Test/CollisionTest.cs deleted file mode 100644 index 1d2c17f01..000000000 --- a/Assets/Scripts/Test/CollisionTest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UnityEngine; - -namespace Test -{ - public class CollisionTest : MonoBehaviour - { - private void OnCollisionEnter(Collision other) - { - Debug.Log($"OnCollisionEnter:{other.gameObject.name}"); - } - private void OnCollisionExit(Collision other) - { - Debug.Log($"OnCollisionExit:{other.gameObject.name}"); - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Test/CollisionTest.cs.meta b/Assets/Scripts/Test/CollisionTest.cs.meta deleted file mode 100644 index ba80e1dbf..000000000 --- a/Assets/Scripts/Test/CollisionTest.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d5bfa3f53f894e7a87315e5cbc220e12 -timeCreated: 1772767361 \ No newline at end of file diff --git a/Assets/Scripts/Test/FishingLineTensionModel.cs b/Assets/Scripts/Test/FishingLineTensionModel.cs deleted file mode 100644 index 187afeef6..000000000 --- a/Assets/Scripts/Test/FishingLineTensionModel.cs +++ /dev/null @@ -1,337 +0,0 @@ -using UnityEngine; - -/// -/// 鱼线张力参考模型 -/// -/// 这个脚本不负责真正的鱼线渲染,也不负责完整鱼AI, -/// 只负责根据“竿尖 - 鱼”的关系,计算一个较合理的张力模型。 -/// -/// 适合先拿来验证: -/// 1. 当前张力是否合理 -/// 2. 鱼竿弯曲是否合理 -/// 3. 卸力出线是否自然 -/// 4. 断线判定是否符合预期 -/// -public class FishingLineTensionModel : MonoBehaviour -{ - [Header("References")] [Tooltip("鱼竿竿尖挂点")] - public Transform rodTip; - - [Tooltip("鱼对象(位置来源)")] public Transform fishTarget; - - [Tooltip("鱼刚体,用来取速度并施加线的拉力")] public Rigidbody fishRb; - - [Tooltip("玩家/竿尖所在刚体,可选。若为空则竿尖速度按0处理")] public Rigidbody rodTipRb; - - [Header("Line State")] [Tooltip("当前放线长度(米)")] - public float lineLength = 5f; - - [Tooltip("最短允许线长,防止收线收到过小")] public float minLineLength = 0.5f; - - [Tooltip("最长允许线长")] public float maxLineLength = 100f; - - [Tooltip("手动收线速度(米/秒),这里只是参考参数")] public float reelInSpeed = 1.5f; - - [Tooltip("手动放线速度(米/秒),这里只是参考参数")] public float reelOutSpeed = 3f; - - [Header("Line Tension")] [Tooltip("鱼线系统等效刚度。越大,拉直后越硬")] - public float lineStiffness = 120f; - - [Tooltip("沿鱼线方向的阻尼。鱼外冲越快,附加张力越大")] public float lineDamping = 20f; - - [Tooltip("接近绷直时保留的一点最小张力,避免完全没手感")] public float minTensionWhenNearTight = 1f; - - [Tooltip("进入预张力区域的比例。比如0.95表示距离达到线长95%就开始有一点点手感")] [Range(0.7f, 1f)] - public float nearTightRatio = 0.95f; - - [Header("Rod Buffer / Flex")] [Tooltip("鱼竿最大承载参考值。张力越接近这个值,竿越弯")] - public float rodMaxLoad = 40f; - - [Tooltip("鱼竿最大缓冲长度(米)。竿越弯,等效可多“吃掉”一些长度")] - public float rodFlexMax = 0.35f; - - [Header("Drag / Spool")] [Tooltip("绕线轮卸力阈值。张力超过它就开始自动出线")] - public float dragThreshold = 18f; - - [Tooltip("超过卸力阈值后,每多1单位张力,对应的自动出线速度倍率")] - public float dragSpoolFactor = 0.08f; - - [Header("Break / Damage")] [Tooltip("安全张力。超过它开始累计损伤")] - public float safeTension = 22f; - - [Tooltip("绝对极限张力。超过它可以直接判定断线")] public float breakTension = 35f; - - [Tooltip("超安全张力时的损伤累计速度倍率")] public float lineDamageRate = 1.5f; - - [Tooltip("累计损伤达到此值后断线")] public float lineDamageLimit = 10f; - - [Header("Fish Force")] [Tooltip("是否把张力反向施加给鱼刚体")] - public bool applyForceToFish = true; - - [Tooltip("对鱼施加拉力时的倍率,用来调手感")] public float forceToFishScale = 1f; - - [Header("Runtime Debug (Read Only)")] [SerializeField] - private float currentDistance; - - [SerializeField] private float currentRelativeSpeedAlongLine; - [SerializeField] private float currentRodFlexOffset; - [SerializeField] private float currentOverStretch; - [SerializeField] private float currentTension; - [SerializeField] private float currentRodBend01; - [SerializeField] private float currentLineDamage; - [SerializeField] private bool isLineBroken; - [SerializeField] private bool isAutoSpooling; - - /// 当前张力,对外只读 - public float CurrentTension => currentTension; - - /// 当前鱼竿弯曲比例(0~1) - public float CurrentRodBend01 => currentRodBend01; - - /// 当前是否断线 - public bool IsLineBroken => isLineBroken; - - /// 当前累计损伤 - public float CurrentLineDamage => currentLineDamage; - - private void Reset() - { - lineLength = 5f; - minLineLength = 0.5f; - maxLineLength = 100f; - - lineStiffness = 120f; - lineDamping = 20f; - minTensionWhenNearTight = 1f; - nearTightRatio = 0.95f; - - rodMaxLoad = 40f; - rodFlexMax = 0.35f; - - dragThreshold = 18f; - dragSpoolFactor = 0.08f; - - safeTension = 22f; - breakTension = 35f; - lineDamageRate = 1.5f; - lineDamageLimit = 10f; - - applyForceToFish = true; - forceToFishScale = 1f; - } - - private void Update() - { - // 这里只演示输入,实际项目你可能会改成输入系统控制 - HandleManualLineInput(); - } - - private void FixedUpdate() - { - if (isLineBroken) - { - currentTension = 0f; - currentRodBend01 = 0f; - currentRodFlexOffset = 0f; - currentOverStretch = 0f; - currentRelativeSpeedAlongLine = 0f; - isAutoSpooling = false; - return; - } - - if (rodTip == null || fishTarget == null) - return; - - // -------------------------------------------------- - // 1. 计算竿尖到鱼的几何关系 - // -------------------------------------------------- - Vector3 delta = fishTarget.position - rodTip.position; - float distance = delta.magnitude; - Vector3 lineDir = distance > 0.0001f ? delta / distance : Vector3.forward; - - currentDistance = distance; - - // -------------------------------------------------- - // 2. 计算沿鱼线方向的相对速度 - // > 0 代表鱼在远离竿尖,拉力应增加 - // < 0 代表鱼在靠近竿尖,拉力应减小 - // -------------------------------------------------- - Vector3 fishVel = fishRb != null ? fishRb.linearVelocity : Vector3.zero; - Vector3 tipVel = rodTipRb != null ? rodTipRb.linearVelocity : Vector3.zero; - - float relativeSpeedAlongLine = Vector3.Dot(fishVel - tipVel, lineDir); - currentRelativeSpeedAlongLine = relativeSpeedAlongLine; - - // -------------------------------------------------- - // 3. 根据“上一帧张力”估算当前鱼竿弯曲带来的缓冲长度 - // 张力越大,竿越弯,可额外缓冲一些长度 - // -------------------------------------------------- - currentRodBend01 = rodMaxLoad > 0.0001f - ? Mathf.Clamp01(currentTension / rodMaxLoad) - : 0f; - - currentRodFlexOffset = currentRodBend01 * rodFlexMax; - - // -------------------------------------------------- - // 4. 计算“超限量” - // 当距离 <= 线长 + 竿缓冲时,认为线没有真正被硬拉伸 - // 当距离 > 线长 + 竿缓冲时,多出来的部分转化为张力 - // -------------------------------------------------- - float effectiveLength = lineLength + currentRodFlexOffset; - float overStretch = Mathf.Max(0f, distance - effectiveLength); - currentOverStretch = overStretch; - - // -------------------------------------------------- - // 5. 计算基础张力 - // T = 刚度项 + 阻尼项 - // -------------------------------------------------- - float tension = 0f; - - // 刚度项:超过可承受长度才会产生明显张力 - tension += lineStiffness * overStretch; - - // 阻尼项:只有“往外冲”的速度才增加张力 - if (relativeSpeedAlongLine > 0f) - { - tension += lineDamping * relativeSpeedAlongLine; - } - - // -------------------------------------------------- - // 6. 接近绷直时给一点最小预张力 - // 避免 D 接近 lineLength 时,手感突然从0跳到有力 - // -------------------------------------------------- - float nearTightDistance = lineLength * nearTightRatio; - if (distance >= nearTightDistance) - { - tension = Mathf.Max(tension, minTensionWhenNearTight); - } - - // 线完全松很多时,可直接视为无有效张力 - if (distance < nearTightDistance && overStretch <= 0f) - { - tension = 0f; - } - - currentTension = Mathf.Max(0f, tension); - - // -------------------------------------------------- - // 7. 卸力:当张力超过绕线轮设定值时,自动出线 - // 这样大鱼冲刺时不会硬顶到瞬间爆线 - // -------------------------------------------------- - isAutoSpooling = false; - - if (currentTension > dragThreshold) - { - float extraTension = currentTension - dragThreshold; - float autoSpoolSpeed = extraTension * dragSpoolFactor; - - lineLength += autoSpoolSpeed * Time.fixedDeltaTime; - lineLength = Mathf.Clamp(lineLength, minLineLength, maxLineLength); - - isAutoSpooling = true; - } - - // -------------------------------------------------- - // 8. 断线逻辑 - // 8.1 超过极限值:可直接断 - // 8.2 超过安全值:持续累计损伤 - // -------------------------------------------------- - if (currentTension >= breakTension) - { - BreakLine(); - return; - } - - if (currentTension > safeTension) - { - float overload = currentTension - safeTension; - currentLineDamage += overload * lineDamageRate * Time.fixedDeltaTime; - - if (currentLineDamage >= lineDamageLimit) - { - BreakLine(); - return; - } - } - else - { - // 张力安全时,损伤缓慢恢复一点 - currentLineDamage -= Time.fixedDeltaTime; - currentLineDamage = Mathf.Max(0f, currentLineDamage); - } - - // -------------------------------------------------- - // 9. 把鱼线张力反向施加给鱼 - // 鱼越往外冲,线张力越大,反向拉回鱼的力也越大 - // -------------------------------------------------- - if (applyForceToFish && fishRb != null && currentTension > 0f) - { - Vector3 pullForce = -lineDir * currentTension * forceToFishScale; - fishRb.AddForce(pullForce, ForceMode.Force); - } - - // -------------------------------------------------- - // 10. 重新根据当前张力更新鱼竿弯曲值(给外部表现层用) - // -------------------------------------------------- - currentRodBend01 = rodMaxLoad > 0.0001f - ? Mathf.Clamp01(currentTension / rodMaxLoad) - : 0f; - } - - /// - /// 示例输入: - /// R = 收线 - /// F = 放线 - /// 实际项目建议接你自己的输入系统 - /// - private void HandleManualLineInput() - { - if (isLineBroken) - return; - - if (Input.GetKey(KeyCode.R)) - { - lineLength -= reelInSpeed * Time.deltaTime; - } - - if (Input.GetKey(KeyCode.F)) - { - lineLength += reelOutSpeed * Time.deltaTime; - } - - lineLength = Mathf.Clamp(lineLength, minLineLength, maxLineLength); - } - - /// - /// 断线 - /// - private void BreakLine() - { - isLineBroken = true; - currentTension = 0f; - currentRodBend01 = 0f; - currentRodFlexOffset = 0f; - currentOverStretch = 0f; - isAutoSpooling = false; - - Debug.Log("鱼线断了"); - } - - /// - /// 外部调用:修复鱼线 - /// - public void RepairLine(float repairedLength) - { - isLineBroken = false; - currentLineDamage = 0f; - lineLength = Mathf.Clamp(repairedLength, minLineLength, maxLineLength); - } - - /// - /// 外部调用:直接设置线长 - /// - public void SetLineLength(float length) - { - lineLength = Mathf.Clamp(length, minLineLength, maxLineLength); - } -} \ No newline at end of file diff --git a/Assets/Scripts/Test/FishingLineTensionModel.cs.meta b/Assets/Scripts/Test/FishingLineTensionModel.cs.meta deleted file mode 100644 index 66bd87eb1..000000000 --- a/Assets/Scripts/Test/FishingLineTensionModel.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 1a6c0b4a2030426c807730fe3837b9b9 -timeCreated: 1775379112 \ No newline at end of file diff --git a/Assets/Scripts/Test/New.meta b/Assets/Scripts/Test/New.meta deleted file mode 100644 index b173c04af..000000000 --- a/Assets/Scripts/Test/New.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bc8dcefa76944b33bc63ffe5f0280067 -timeCreated: 1774185300 \ No newline at end of file diff --git a/Assets/Scripts/Test/New/BobberPresentationController.cs b/Assets/Scripts/Test/New/BobberPresentationController.cs deleted file mode 100644 index 8c3601949..000000000 --- a/Assets/Scripts/Test/New/BobberPresentationController.cs +++ /dev/null @@ -1,936 +0,0 @@ -using UnityEngine; - -using WaveHarmonic.Crest; - -/// -/// 简单水面接口。你可以替换成自己的水系统。 -/// -public interface IWaterSurfaceProvider -{ - float GetWaterHeight(Vector3 worldPos); - Vector3 GetWaterNormal(Vector3 worldPos); -} - -/// -/// 浮漂控制模式: -/// 1. AirPhysics:空中/未入水,使用刚体物理 -/// 2. WaterPresentation:入水后,关闭重力,Y 和旋转由脚本控制 -/// -public enum BobberControlMode -{ - AirPhysics, - WaterPresentation -} - -/// -/// 漂像事件类型 -/// -public enum BobberBiteType -{ - None, - Tap, // 轻点 - SlowSink, // 缓沉 - Lift, // 送漂 - BlackDrift // 黑漂/快速拖入 -} - -public enum BobberPosture -{ - Lying, - Tilted, - Upright -} - -[DisallowMultipleComponent] -[RequireComponent(typeof(Rigidbody))] -public class BobberPresentationController : MonoBehaviour -{ - [Header("Water")] [Tooltip("没有水提供器时使用固定水位")] - public float fallbackWaterLevel = 0f; - - [Tooltip("Crest 水体。为空时会尝试从 SceneSettings 读取")] - public WaterRenderer waterRenderer; - - [Tooltip("Crest 查询层级")] public CollisionLayer waterCollisionLayer = CollisionLayer.AfterAnimatedWaves; - - [Tooltip("Crest 波面查询宽度(参考 BobberFloating)")] - public float waterQueryObjectWidth = 0.5f; - - [Tooltip("可选:挂实现了 IWaterSurfaceProvider 的组件")] - public MonoBehaviour waterProviderBehaviour; - - [Header("Enter Water")] [Tooltip("底部进入水面多少米后切换为漂像控制")] - public float enterWaterDepth = 0.002f; - - [Tooltip("离开水面多少米后回到空中物理。一般给负值做滞回")] public float exitWaterDepth = -0.01f; - - [Header("Geometry")] [Tooltip("浮漂总高度(米)")] - public float floatHeight = 0.08f; - - [Tooltip("如果 Pivot 在浮漂底部,这里填 0;如果 Pivot 在模型中心,就填底部相对 Pivot 的本地 Y")] - public float bottomOffsetLocalY = 0f; - - [Header("Base Float")] [Tooltip("基础吃铅比例,决定静止时有多少在水下")] [Range(0.05f, 0.95f)] - public float baseSubmergeRatio = 0.28f; - - [Tooltip("Y 轴平滑时间,越小响应越快")] public float ySmoothTime = 0.08f; - - [Tooltip("最大竖直速度限制(用于 SmoothDamp)")] public float maxYSpeed = 2f; - - [Tooltip("静止小死区,减少微抖")] public float yDeadZone = 0.0005f; - - [Header("Surface Motion")] [Tooltip("是否启用轻微水面起伏")] - public bool enableSurfaceBobbing = true; - - [Tooltip("水面轻微起伏振幅(米)")] public float surfaceBobAmplitude = 0.0015f; - - [Tooltip("水面轻微起伏频率")] public float surfaceBobFrequency = 1.2f; - - [Header("XZ Motion")] [Tooltip("入水后是否锁定 XZ 到入水点附近")] - public bool lockXZAroundAnchor = true; - - [Tooltip("XZ 跟随平滑时间")] public float xzSmoothTime = 0.15f; - - [Tooltip("水流/拖拽带来的额外平面偏移最大值")] public float maxPlanarOffset = 0.15f; - - [Header("Sink By Weight / Tension")] [Tooltip("外部向下拉力映射为下沉量的系数。你可以把钩/铅/线组的等效向下拉力喂进来")] - public float downForceToSink = 0.0025f; - - [Tooltip("向下拉力下沉的最大附加量")] public float maxExtraSink = 0.08f; - - [Header("Bottom Touch")] [Tooltip("触底时是否启用修正")] - public bool enableBottomTouchAdjust = true; - - [Tooltip("触底后减少的下沉量(例如铅坠到底,漂会回升一点)")] public float bottomTouchLift = 0.01f; - - [Header("Posture Source")] [Tooltip("下方 Lure / 钩组 / 铅坠的刚体。姿态主要根据它和浮漂的相对位置判断")] - public Rigidbody lureBody; - - [Tooltip("用于归一化的参考长度。一般填:浮漂到 Lure 在“正常拉直”时的大致长度")] - public float referenceLength = 0.30f; - - [Header("Posture Threshold")] [Tooltip("最小入水比例。不够时优先躺漂")] - public float minSubmergeToStand = 0.16f; - - [Tooltip("垂直分量比低于该值时,优先躺漂")] public float verticalLieThreshold = 0.18f; - - [Tooltip("垂直分量比高于该值,且水平分量较小时,允许立漂")] public float verticalUprightThreshold = 0.75f; - - [Tooltip("水平分量比高于该值时,不允许完全立漂")] public float planarTiltThreshold = 0.30f; - - [Tooltip("水平分量明显大于垂直分量时,优先躺漂")] public float planarDominanceMultiplier = 1.20f; - - [Tooltip("姿态切换滞回")] public float postureHysteresis = 0.04f; - - [Header("Posture Stability")] [Tooltip("候选姿态需持续多久才真正切换")] - public float postureConfirmTime = 0.08f; - - [Tooltip("姿态切换后的最短冷却时间,避免来回闪烁")] - public float postureSwitchCooldown = 0.10f; - - [Header("Posture Rotation")] [Tooltip("倾斜状态角度")] - public float tiltedAngle = 38f; - - [Tooltip("躺漂角度")] public float lyingAngle = 88f; - - [Tooltip("立漂时允许的最大附加倾角")] public float uprightMaxTiltAngle = 8f; - - [Tooltip("平面方向对立漂/斜漂附加倾角的影响强度")] public float planarTiltFactor = 120f; - - [Tooltip("平面方向死区,小于该值时保持上一帧方向")] public float planarDirectionDeadZone = 0.01f; - - [Tooltip("平面方向平滑速度")] public float planarDirectionLerpSpeed = 10f; - - [Tooltip("姿态平滑速度")] public float rotationLerpSpeed = 8f; - - [Header("Debug Input")] [Tooltip("调试:按 R 恢复默认")] - public bool debugResetKey = true; - - [Tooltip("调试:按 T 触发轻点")] public bool debugTapKey = true; - - [Tooltip("调试:按 G 触发缓沉")] public bool debugSlowSinkKey = true; - - [Tooltip("调试:按 H 触发送漂")] public bool debugLiftKey = true; - - [Tooltip("调试:按 B 触发黑漂")] public bool debugBlackDriftKey = true; - - [Header("Debug")] public bool drawDebug = false; - - public bool UseTestPosture; - public BobberPosture TestPosture; - - public BobberControlMode CurrentMode => _mode; - public BobberPosture CurrentPosture => _posture; - public float CurrentVerticalRatio => _verticalRatio; - public float CurrentPlanarRatio => _planarRatio; - - /// 外部可写:等效向下拉力(不是必须是真实力,作为输入信号即可) - public float ExternalDownForce { get; set; } - - /// 外部可写:是否触底 - public bool IsBottomTouched { get; set; } - - /// 外部可写:额外平面偏移(例如风、水流、拖拽) - public Vector2 ExternalPlanarOffset { get; set; } - - private Rigidbody _rb; - private IWaterSurfaceProvider _waterProvider; - private BobberControlMode _mode = BobberControlMode.AirPhysics; - private BobberPosture _posture = BobberPosture.Lying; - - private float _defaultLinearDamping; - private float _defaultAngularDamping; - private bool _defaultUseGravity; - - private Vector3 _waterAnchorPos; - private Vector3 _xzSmoothVelocity; - private float _ySmoothVelocity; - - private float _biteOffsetY; - private float _biteOffsetYVelocity; - - private Quaternion _targetRotation; - - // bite event runtime - private BobberBiteType _activeBiteType = BobberBiteType.None; - private float _biteTimer; - private float _biteDuration; - private float _biteAmplitude; - private Vector3 _blackDriftDirection; - - // posture runtime - private float _verticalRatio; - private float _planarRatio; - private float _verticalDistance; - private float _planarDistance; - private BobberPosture _pendingPosture; - private float _pendingPostureTimer; - private float _postureCooldownTimer; - private Vector3 _stablePlanarDir = Vector3.forward; - - private bool _hasCrestSampleThisFrame; - private readonly Vector3[] _waterQueryPoints = new Vector3[1]; - private readonly Vector3[] _waterQueryResultDisplacements = new Vector3[1]; - private readonly Vector3[] _waterQueryResultVelocities = new Vector3[1]; - private readonly Vector3[] _waterQueryResultNormal = new Vector3[1]; - - private void Awake() - { - _rb = GetComponent(); - - _defaultLinearDamping = _rb.linearDamping; - _defaultAngularDamping = _rb.angularDamping; - _defaultUseGravity = _rb.useGravity; - - if (waterProviderBehaviour != null) - _waterProvider = waterProviderBehaviour as IWaterSurfaceProvider; - - if (waterRenderer == null && SceneSettings.Instance != null) - waterRenderer = SceneSettings.Instance.Water; - - _pendingPosture = _posture; - _pendingPostureTimer = 0f; - _postureCooldownTimer = 0f; - _stablePlanarDir = Vector3.ProjectOnPlane(transform.forward, Vector3.up); - if (_stablePlanarDir.sqrMagnitude < 1e-6f) - _stablePlanarDir = Vector3.forward; - else - _stablePlanarDir.Normalize(); - - _targetRotation = transform.rotation; - } - - private void Update() - { - HandleDebugKeys(); - } - - private void FixedUpdate() - { - float waterY = GetWaterHeight(transform.position); - Vector3 bottomWorld = GetBottomWorldPosition(); - float submergeDepth = waterY - bottomWorld.y; - - switch (_mode) - { - case BobberControlMode.AirPhysics: - UpdateAirPhysics(submergeDepth); - break; - - case BobberControlMode.WaterPresentation: - UpdateWaterPresentation(waterY, submergeDepth); - break; - } - - if (drawDebug) - { - DrawDebug(waterY); - } - } - - #region Main Update - - private void UpdateAirPhysics(float submergeDepth) - { - RestoreAirPhysicsState(); - - if (submergeDepth > enterWaterDepth) - { - EnterWaterPresentationMode(); - } - } - - private void UpdateWaterPresentation(float waterY, float submergeDepth) - { - if (submergeDepth < exitWaterDepth) - { - ExitWaterPresentationMode(); - return; - } - - // 完全关闭刚体干扰 - _rb.useGravity = false; - _rb.linearVelocity = Vector3.zero; - _rb.angularVelocity = Vector3.zero; - _rb.linearDamping = 999f; - _rb.angularDamping = 999f; - - UpdateBiteAnimation(); - - Vector3 pos = transform.position; - - // 1. 算目标 Y - float targetY = CalculateTargetY(waterY); - - if (Mathf.Abs(pos.y - targetY) < yDeadZone) - { - pos.y = targetY; - _ySmoothVelocity = 0f; - } - else - { - pos.y = Mathf.SmoothDamp( - current: pos.y, - target: targetY, - currentVelocity: ref _ySmoothVelocity, - smoothTime: Mathf.Max(0.0001f, ySmoothTime), - maxSpeed: maxYSpeed, - deltaTime: Time.fixedDeltaTime - ); - } - - // 2. 算目标 XZ - Vector3 targetXZ = CalculateTargetXZ(); - Vector3 planarPos = new Vector3(pos.x, 0f, pos.z); - Vector3 planarTarget = new Vector3(targetXZ.x, 0f, targetXZ.z); - - planarPos = Vector3.SmoothDamp( - planarPos, - planarTarget, - ref _xzSmoothVelocity, - Mathf.Max(0.0001f, xzSmoothTime), - Mathf.Infinity, - Time.fixedDeltaTime - ); - - pos.x = planarPos.x; - pos.z = planarPos.z; - - transform.position = pos; - - // 3. 姿态判定 + 目标旋转 - EvaluatePostureByComponents(waterY); - UpdateTargetRotationByPosture(); - - transform.rotation = Quaternion.Slerp( - transform.rotation, - _targetRotation, - 1f - Mathf.Exp(-rotationLerpSpeed * Time.fixedDeltaTime) - ); - } - - #endregion - - #region Mode Switch - - private void EnterWaterPresentationMode() - { - _mode = BobberControlMode.WaterPresentation; - - _waterAnchorPos = transform.position; - _ySmoothVelocity = 0f; - _xzSmoothVelocity = Vector3.zero; - _biteOffsetY = 0f; - _biteOffsetYVelocity = 0f; - _activeBiteType = BobberBiteType.None; - _biteTimer = 0f; - - _posture = BobberPosture.Lying; - _verticalRatio = 0f; - _planarRatio = 0f; - _verticalDistance = 0f; - _planarDistance = 0f; - _pendingPosture = _posture; - _pendingPostureTimer = 0f; - _postureCooldownTimer = 0f; - _stablePlanarDir = Vector3.ProjectOnPlane(transform.forward, Vector3.up); - if (_stablePlanarDir.sqrMagnitude < 1e-6f) - _stablePlanarDir = Vector3.forward; - else - _stablePlanarDir.Normalize(); - - _rb.useGravity = false; - _rb.linearVelocity = Vector3.zero; - _rb.angularVelocity = Vector3.zero; - _rb.linearDamping = 999f; - _rb.angularDamping = 999f; - } - - private void ExitWaterPresentationMode() - { - _mode = BobberControlMode.AirPhysics; - RestoreAirPhysicsState(); - } - - private void RestoreAirPhysicsState() - { - _rb.useGravity = _defaultUseGravity; - _rb.linearDamping = _defaultLinearDamping; - _rb.angularDamping = _defaultAngularDamping; - } - - #endregion - - #region Target Calculation - - private float CalculateTargetY(float waterY) - { - float baseSinkDepth = floatHeight * Mathf.Clamp01(baseSubmergeRatio); - - float sinkByForce = Mathf.Clamp( - ExternalDownForce * downForceToSink, - 0f, - maxExtraSink - ); - - float bottomAdjust = 0f; - if (enableBottomTouchAdjust && IsBottomTouched) - { - bottomAdjust -= bottomTouchLift; - } - - float surfaceBob = 0f; - if (enableSurfaceBobbing && !_hasCrestSampleThisFrame) - { - surfaceBob = Mathf.Sin(Time.time * surfaceBobFrequency * Mathf.PI * 2f) * surfaceBobAmplitude; - } - - float totalSink = baseSinkDepth + sinkByForce + bottomAdjust; - float targetBottomY = waterY - totalSink; - float targetPivotY = targetBottomY - bottomOffsetLocalY + surfaceBob + _biteOffsetY; - - return targetPivotY; - } - - private Vector3 CalculateTargetXZ() - { - Vector2 planarOffset = Vector2.ClampMagnitude(ExternalPlanarOffset, maxPlanarOffset); - - Vector3 basePos = lockXZAroundAnchor ? _waterAnchorPos : transform.position; - - if (_activeBiteType == BobberBiteType.BlackDrift) - { - float t = Mathf.Clamp01(_biteDuration > 0f ? _biteTimer / _biteDuration : 1f); - float drift = Mathf.SmoothStep(0f, 1f, t) * 0.08f; - Vector3 blackDrift = _blackDriftDirection * drift; - basePos += new Vector3(blackDrift.x, 0f, blackDrift.z); - } - - return new Vector3( - basePos.x + planarOffset.x, - transform.position.y, - basePos.z + planarOffset.y - ); - } - - private void EvaluatePostureByComponents(float waterY) - { - float submergeRatio = Mathf.Clamp01( - (waterY - GetBottomWorldPosition().y) / Mathf.Max(0.0001f, floatHeight) - ); - - bool hasLure = lureBody != null; - - if (lureBody == null) - { - _verticalDistance = 0f; - _planarDistance = 0f; - _verticalRatio = 0f; - _planarRatio = 0f; - } - else - { - Vector3 bobberPos = _rb.worldCenterOfMass; - Vector3 lurePos = lureBody.worldCenterOfMass; - Vector3 delta = lurePos - bobberPos; - - _verticalDistance = Mathf.Max(0f, Vector3.Dot(delta, Vector3.down)); - _planarDistance = Vector3.ProjectOnPlane(delta, Vector3.up).magnitude; - - float refLen = Mathf.Max(0.0001f, referenceLength); - _verticalRatio = _verticalDistance / refLen; - _planarRatio = _planarDistance / refLen; - } - - BobberPosture desiredPosture = DeterminePostureState(submergeRatio, hasLure); - ApplyPostureWithStability(desiredPosture); - } - - /// - /// 只在这个函数里写姿态状态判断。 - /// 你后续要改逻辑,改这里即可,外面只负责采样数据和旋转平滑。 - /// - private BobberPosture DeterminePostureState(float submergeRatio, bool hasLure) - { - if (UseTestPosture) - { - return TestPosture; - } - // 没有 Lure 时,保留简单兜底规则。 - if (!hasLure) - { - if (submergeRatio < minSubmergeToStand) - return BobberPosture.Lying; - - if (ExternalPlanarOffset.magnitude > 0.01f) - return BobberPosture.Tilted; - - return BobberPosture.Upright; - } - - // 这里是完整状态判断入口(可按你的需求自由改)。 - switch (_posture) - { - case BobberPosture.Lying: - { - bool canStandUpright = - submergeRatio >= minSubmergeToStand && - _verticalRatio > verticalUprightThreshold + postureHysteresis && - _planarRatio < planarTiltThreshold - postureHysteresis; - - bool canTilt = - submergeRatio >= minSubmergeToStand * 0.8f && - _verticalRatio > verticalLieThreshold + postureHysteresis; - - if (canStandUpright) - return BobberPosture.Upright; - if (canTilt) - return BobberPosture.Tilted; - return BobberPosture.Lying; - } - - case BobberPosture.Tilted: - { - bool shouldLie = - submergeRatio < minSubmergeToStand * 0.75f || - _verticalRatio < verticalLieThreshold - postureHysteresis || - _planarDistance > _verticalDistance * planarDominanceMultiplier; - - bool shouldStand = - submergeRatio >= minSubmergeToStand && - _verticalRatio > verticalUprightThreshold + postureHysteresis && - _planarRatio < planarTiltThreshold - postureHysteresis; - - if (shouldLie) - return BobberPosture.Lying; - if (shouldStand) - return BobberPosture.Upright; - return BobberPosture.Tilted; - } - - default: - { - bool shouldLie = - submergeRatio < minSubmergeToStand * 0.75f || - _verticalRatio < verticalLieThreshold - postureHysteresis || - _planarDistance > _verticalDistance * (planarDominanceMultiplier + 0.15f); - - bool shouldTilt = - _verticalRatio < verticalUprightThreshold - postureHysteresis || - _planarRatio > planarTiltThreshold + postureHysteresis; - - if (shouldLie) - return BobberPosture.Lying; - if (shouldTilt) - return BobberPosture.Tilted; - return BobberPosture.Upright; - } - } - } - - private void ApplyPostureWithStability(BobberPosture desiredPosture) - { - _postureCooldownTimer = Mathf.Max(0f, _postureCooldownTimer - Time.fixedDeltaTime); - - if (desiredPosture == _posture) - { - _pendingPosture = _posture; - _pendingPostureTimer = 0f; - return; - } - - if (_postureCooldownTimer > 0f) - { - _pendingPosture = desiredPosture; - _pendingPostureTimer = 0f; - return; - } - - if (_pendingPosture != desiredPosture) - { - _pendingPosture = desiredPosture; - _pendingPostureTimer = 0f; - return; - } - - _pendingPostureTimer += Time.fixedDeltaTime; - if (_pendingPostureTimer >= Mathf.Max(0f, postureConfirmTime)) - { - _posture = desiredPosture; - _pendingPosture = _posture; - _pendingPostureTimer = 0f; - _postureCooldownTimer = Mathf.Max(0f, postureSwitchCooldown); - } - } - - private void UpdateTargetRotationByPosture() - { - Vector3 candidateDir = Vector3.zero; - - if (lureBody != null) - { - Vector3 delta = lureBody.worldCenterOfMass - _rb.worldCenterOfMass; - candidateDir = Vector3.ProjectOnPlane(delta, Vector3.up); - } - - if (candidateDir.sqrMagnitude < 1e-6f) - { - candidateDir = new Vector3(_xzSmoothVelocity.x, 0f, _xzSmoothVelocity.z); - } - - if (candidateDir.sqrMagnitude < 1e-6f) - { - candidateDir = new Vector3(ExternalPlanarOffset.x, 0f, ExternalPlanarOffset.y); - } - - if (_stablePlanarDir.sqrMagnitude < 1e-6f) - { - _stablePlanarDir = Vector3.ProjectOnPlane(transform.forward, Vector3.up); - if (_stablePlanarDir.sqrMagnitude < 1e-6f) - _stablePlanarDir = Vector3.forward; - } - _stablePlanarDir.Normalize(); - - float dirDeadZone = Mathf.Max(0.0001f, planarDirectionDeadZone); - if (candidateDir.sqrMagnitude > dirDeadZone * dirDeadZone) - { - candidateDir.Normalize(); - - // 保持与上一帧同向,避免 180 度翻转造成左右闪。 - if (Vector3.Dot(candidateDir, _stablePlanarDir) < 0f) - candidateDir = -candidateDir; - - float k = 1f - Mathf.Exp(-Mathf.Max(0.01f, planarDirectionLerpSpeed) * Time.fixedDeltaTime); - _stablePlanarDir = Vector3.Slerp(_stablePlanarDir, candidateDir, k); - _stablePlanarDir.Normalize(); - } - - Vector3 planarDir = _stablePlanarDir; - - Vector3 tiltAxis = Vector3.Cross(Vector3.up, planarDir); - if (tiltAxis.sqrMagnitude < 1e-6f) - { - tiltAxis = transform.right; - } - - float angle = _posture switch - { - BobberPosture.Lying => lyingAngle, - BobberPosture.Tilted => tiltedAngle, - _ => 0f - }; - - _targetRotation = Quaternion.AngleAxis(angle, tiltAxis.normalized); - } - - #endregion - - #region Bite Presentation - - /// - /// 轻点:快速下顿再回弹 - /// - public void PlayTap(float amplitude = 0.008f, float duration = 0.18f) - { - StartBite(BobberBiteType.Tap, amplitude, duration); - } - - /// - /// 缓沉:在持续时间内逐渐下沉 - /// - public void PlaySlowSink(float amplitude = 0.025f, float duration = 1.2f) - { - StartBite(BobberBiteType.SlowSink, amplitude, duration); - } - - /// - /// 送漂:向上抬 - /// - public void PlayLift(float amplitude = 0.015f, float duration = 1.2f) - { - StartBite(BobberBiteType.Lift, amplitude, duration); - } - - /// - /// 黑漂:快速下沉,并可配合平面拖拽 - /// - public void PlayBlackDrift(float amplitude = 0.06f, float duration = 0.8f, Vector3? driftDirection = null) - { - StartBite(BobberBiteType.BlackDrift, amplitude, duration); - _blackDriftDirection = (driftDirection ?? transform.forward).normalized; - } - - public void StopBite() - { - _activeBiteType = BobberBiteType.None; - _biteTimer = 0f; - _biteDuration = 0f; - _biteAmplitude = 0f; - _biteOffsetY = 0f; - _biteOffsetYVelocity = 0f; - } - - private void StartBite(BobberBiteType type, float amplitude, float duration) - { - if (_mode != BobberControlMode.WaterPresentation) - return; - - _activeBiteType = type; - _biteTimer = 0f; - _biteDuration = Mathf.Max(0.01f, duration); - _biteAmplitude = amplitude; - _biteOffsetYVelocity = 0f; - - if (type == BobberBiteType.BlackDrift && _blackDriftDirection.sqrMagnitude < 1e-6f) - { - _blackDriftDirection = - transform.forward.sqrMagnitude > 1e-6f ? transform.forward.normalized : Vector3.forward; - } - } - - private void UpdateBiteAnimation() - { - if (_activeBiteType == BobberBiteType.None) - { - _biteOffsetY = Mathf.SmoothDamp( - _biteOffsetY, - 0f, - ref _biteOffsetYVelocity, - 0.08f, - Mathf.Infinity, - Time.fixedDeltaTime - ); - return; - } - - _biteTimer += Time.fixedDeltaTime; - float t = Mathf.Clamp01(_biteTimer / _biteDuration); - - float targetOffset = 0f; - - switch (_activeBiteType) - { - case BobberBiteType.Tap: - if (t < 0.35f) - { - float k = t / 0.35f; - targetOffset = -Mathf.SmoothStep(0f, _biteAmplitude, k); - } - else - { - float k = (t - 0.35f) / 0.65f; - targetOffset = -Mathf.Lerp(_biteAmplitude, 0f, k); - } - - break; - - case BobberBiteType.SlowSink: - targetOffset = -Mathf.SmoothStep(0f, _biteAmplitude, t); - break; - - case BobberBiteType.Lift: - targetOffset = Mathf.SmoothStep(0f, _biteAmplitude, t); - break; - - case BobberBiteType.BlackDrift: - targetOffset = -Mathf.SmoothStep(0f, _biteAmplitude, t); - break; - } - - _biteOffsetY = Mathf.SmoothDamp( - _biteOffsetY, - targetOffset, - ref _biteOffsetYVelocity, - 0.03f, - Mathf.Infinity, - Time.fixedDeltaTime - ); - - if (_biteTimer >= _biteDuration) - { - if (_activeBiteType == BobberBiteType.SlowSink || _activeBiteType == BobberBiteType.BlackDrift) - { - return; - } - - _activeBiteType = BobberBiteType.None; - } - } - - #endregion - - #region Utilities - - private float GetWaterHeight(Vector3 worldPos) - { - if (_waterProvider != null) - { - _hasCrestSampleThisFrame = false; - return _waterProvider.GetWaterHeight(worldPos); - } - - if ( - waterRenderer != null - && waterRenderer.AnimatedWavesLod != null - && waterRenderer.AnimatedWavesLod.Provider != null - ) - { - _waterQueryPoints[0] = worldPos; - waterRenderer.AnimatedWavesLod.Provider.Query( - GetHashCode(), - Mathf.Max(0.001f, waterQueryObjectWidth), - _waterQueryPoints, - _waterQueryResultDisplacements, - _waterQueryResultNormal, - _waterQueryResultVelocities, - waterCollisionLayer - ); - - _hasCrestSampleThisFrame = true; - return _waterQueryResultDisplacements[0].y + waterRenderer.SeaLevel; - } - - _hasCrestSampleThisFrame = false; - return fallbackWaterLevel; - } - - private Vector3 GetBottomWorldPosition() - { - return transform.TransformPoint(new Vector3(0f, bottomOffsetLocalY, 0f)); - } - - private void HandleDebugKeys() - { - if (!Application.isPlaying) - return; - - if (debugResetKey && Input.GetKeyDown(KeyCode.R)) - { - StopBite(); - } - - if (debugTapKey && Input.GetKeyDown(KeyCode.T)) - PlayTap(); - - if (debugSlowSinkKey && Input.GetKeyDown(KeyCode.G)) - PlaySlowSink(); - - if (debugLiftKey && Input.GetKeyDown(KeyCode.H)) - PlayLift(); - - if (debugBlackDriftKey && Input.GetKeyDown(KeyCode.B)) - PlayBlackDrift(); - } - - private void DrawDebug(float waterY) - { - Vector3 p = transform.position; - Vector3 b = GetBottomWorldPosition(); - - Debug.DrawLine( - new Vector3(p.x - 0.05f, waterY, p.z), - new Vector3(p.x + 0.05f, waterY, p.z), - Color.cyan - ); - - Debug.DrawLine(b, b + Vector3.up * floatHeight, Color.yellow); - - if (_mode == BobberControlMode.WaterPresentation) - { - Vector3 a = _waterAnchorPos; - Debug.DrawLine(a + Vector3.left * 0.03f, a + Vector3.right * 0.03f, Color.green); - Debug.DrawLine(a + Vector3.forward * 0.03f, a + Vector3.back * 0.03f, Color.green); - } - - if (lureBody != null) - { - Vector3 bobber = _rb.worldCenterOfMass; - Vector3 lure = lureBody.worldCenterOfMass; - Debug.DrawLine(bobber, lure, Color.magenta); - - Vector3 verticalEnd = bobber + Vector3.down * _verticalDistance; - Debug.DrawLine(bobber, verticalEnd, Color.red); - - Vector3 planar = Vector3.ProjectOnPlane(lure - bobber, Vector3.up); - Debug.DrawLine(verticalEnd, verticalEnd + planar, Color.blue); - } - } - -#if UNITY_EDITOR - private void OnValidate() - { - floatHeight = Mathf.Max(0.001f, floatHeight); - ySmoothTime = Mathf.Max(0.001f, ySmoothTime); - maxYSpeed = Mathf.Max(0.01f, maxYSpeed); - xzSmoothTime = Mathf.Max(0.001f, xzSmoothTime); - rotationLerpSpeed = Mathf.Max(0.01f, rotationLerpSpeed); - - maxPlanarOffset = Mathf.Max(0f, maxPlanarOffset); - downForceToSink = Mathf.Max(0f, downForceToSink); - maxExtraSink = Mathf.Max(0f, maxExtraSink); - surfaceBobAmplitude = Mathf.Max(0f, surfaceBobAmplitude); - surfaceBobFrequency = Mathf.Max(0f, surfaceBobFrequency); - waterQueryObjectWidth = Mathf.Max(0.001f, waterQueryObjectWidth); - yDeadZone = Mathf.Max(0f, yDeadZone); - - referenceLength = Mathf.Max(0.0001f, referenceLength); - minSubmergeToStand = Mathf.Clamp01(minSubmergeToStand); - verticalLieThreshold = Mathf.Clamp(verticalLieThreshold, 0f, 2f); - verticalUprightThreshold = Mathf.Max(verticalLieThreshold, verticalUprightThreshold); - planarTiltThreshold = Mathf.Clamp(planarTiltThreshold, 0f, 2f); - planarDominanceMultiplier = Mathf.Max(0.1f, planarDominanceMultiplier); - postureHysteresis = Mathf.Clamp(postureHysteresis, 0f, 0.3f); - postureConfirmTime = Mathf.Max(0f, postureConfirmTime); - postureSwitchCooldown = Mathf.Max(0f, postureSwitchCooldown); - - tiltedAngle = Mathf.Clamp(tiltedAngle, 0f, 89f); - lyingAngle = Mathf.Clamp(lyingAngle, tiltedAngle, 89.9f); - uprightMaxTiltAngle = Mathf.Clamp(uprightMaxTiltAngle, 0f, tiltedAngle); - planarTiltFactor = Mathf.Max(0f, planarTiltFactor); - planarDirectionDeadZone = Mathf.Max(0.0001f, planarDirectionDeadZone); - planarDirectionLerpSpeed = Mathf.Max(0.01f, planarDirectionLerpSpeed); - } -#endif - - #endregion -} diff --git a/Assets/Scripts/Test/New/BobberPresentationController.cs.meta b/Assets/Scripts/Test/New/BobberPresentationController.cs.meta deleted file mode 100644 index a92c10768..000000000 --- a/Assets/Scripts/Test/New/BobberPresentationController.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 2dedfafdc2d747d98c682cde3e28e513 -timeCreated: 1774185233 \ No newline at end of file diff --git a/Assets/TerrainDef.mat b/Assets/TerrainDef.mat new file mode 100644 index 000000000..6b81ff2d0 --- /dev/null +++ b/Assets/TerrainDef.mat @@ -0,0 +1,229 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TerrainDef + m_Shader: {fileID: 4800000, guid: 69c1f799e772cb6438f56c23efccb782, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 1 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - MOTIONVECTORS + 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} + - _Control: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Control0: + 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} + - _Diffuse: + 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} + - _Mask0: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Mask1: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Mask2: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Mask3: + 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} + - _Normal0: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal1: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal2: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Normal3: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _NormalSAO: + 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} + - _PerPixelNormal: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _PerTexProps: + m_Texture: {fileID: -6551348070273646885, guid: c661901a630dc2544a9128ea4330e178, type: 2} + 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} + - _Splat0: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Splat1: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Splat2: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Splat3: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _TerrainHolesTexture: + 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: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Contrast: 0.4 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnableHeightBlend: 0 + - _EnableInstancedPerPixelNormal: 1 + - _EnvironmentReflections: 1 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _HeightTransition: 0 + - _HybridHeightBlendDistance: 300 + - _Metallic: 0 + - _Metallic0: 0 + - _Metallic1: 0 + - _Metallic2: 0 + - _Metallic3: 0 + - _NumLayersCount: 1 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Shininess: 0.078125 + - _Smoothness: 0.5 + - _Smoothness0: 0.5 + - _Smoothness1: 0.5 + - _Smoothness2: 0.5 + - _Smoothness3: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 1, g: 1, b: 1, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + - _TriplanarUVScale: {r: 1, g: 1, b: 0, a: 0} + - _UVScale: {r: 45, g: 45, b: 0, a: 0} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &4095775999777943649 +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: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion + version: 10 diff --git a/Assets/TerrainDef.mat.meta b/Assets/TerrainDef.mat.meta new file mode 100644 index 000000000..2d483e342 --- /dev/null +++ b/Assets/TerrainDef.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 95965ffe54835394fbe1c387dac39df6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TerrainDef_keywords.asset b/Assets/TerrainDef_keywords.asset new file mode 100644 index 000000000..06e2d10e4 --- /dev/null +++ b/Assets/TerrainDef_keywords.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 007677a8d215f46f78fdc4a57e84fb09, type: 3} + m_Name: TerrainDef_keywords + m_EditorClassIdentifier: JBooth.MicroSplat.Core::JBooth.MicroSplat.MicroSplatKeywords + keywords: + - _TERRAIN_INSTANCED_PERPIXEL_NORMAL diff --git a/Assets/TerrainDef_keywords.asset.meta b/Assets/TerrainDef_keywords.asset.meta new file mode 100644 index 000000000..bbcb237d8 --- /dev/null +++ b/Assets/TerrainDef_keywords.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f7a96b20e24fd24d8669431f1e31fc6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TerrainDef_propdata.asset b/Assets/TerrainDef_propdata.asset new file mode 100644 index 000000000..494716cb5 --- /dev/null +++ b/Assets/TerrainDef_propdata.asset @@ -0,0 +1,1153 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!28 &-6551348070273646885 +Texture2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: PropTex + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_IsAlphaChannelOptional: 0 + serializedVersion: 4 + m_Width: 32 + m_Height: 32 + m_CompleteImageSize: 16384 + m_MipsStripped: 0 + m_TextureFormat: 20 + m_MipCount: 1 + m_IsReadable: 1 + m_IsPreProcessed: 0 + m_IgnoreMipmapLimit: 1 + m_MipmapLimitGroupName: + m_StreamingMipmaps: 0 + m_StreamingMipmapsPriority: 0 + m_VTOnly: 0 + m_AlphaIsTransparency: 0 + m_ImageCount: 1 + m_TextureDimension: 2 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 0 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 1 + m_WrapV: 1 + m_WrapW: 1 + m_LightmapFormat: 0 + m_ColorSpace: 0 + m_PlatformBlob: + image data: 16384 + _typelessdata: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + m_StreamData: + serializedVersion: 2 + offset: 0 + size: 0 + path: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bfa2271e2fc864444b5b57e386e28d5d, type: 3} + m_Name: TerrainDef_propdata + m_EditorClassIdentifier: JBooth.MicroSplat.Core::JBooth.MicroSplat.MicroSplatPropData + values: + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + - {r: 0, g: 0, b: 0, a: 0} + propTex: {fileID: 0} + geoCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + geoTex: {fileID: 0} + geoSlopeFilter: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.2 + inSlope: 0 + outSlope: 2 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 0.4 + value: 1 + inSlope: 2 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + geoSlopeTex: {fileID: 0} + globalSlopeFilter: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.2 + inSlope: 0 + outSlope: 2 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 0.4 + value: 1 + inSlope: 2 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + globalSlopeTex: {fileID: 0} + maxTextures: 32 diff --git a/Assets/TerrainDef_propdata.asset.meta b/Assets/TerrainDef_propdata.asset.meta new file mode 100644 index 000000000..2e5ccf5be --- /dev/null +++ b/Assets/TerrainDef_propdata.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c661901a630dc2544a9128ea4330e178 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/URPProjectSettings.asset b/ProjectSettings/URPProjectSettings.asset index 64a8674a2..6ad563183 100644 --- a/ProjectSettings/URPProjectSettings.asset +++ b/ProjectSettings/URPProjectSettings.asset @@ -13,3 +13,4 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: m_LastMaterialVersion: 10 + m_ProjectSettingFolderPath: URPDefaultResources