From a60a92e7ba5e48f12d31728ab6aba5b72b3f1e63 Mon Sep 17 00:00:00 2001 From: BobSong <605277374@qq.com> Date: Wed, 26 Nov 2025 23:44:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=AE=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Resources/gfx/test.meta | 8 + .../gfx/test/bob_25002-bob_25002_emissive.mat | 140 ++++++ .../bob_25002-bob_25002_emissive.mat.meta | 8 + .../gfx/test/bob_25002-bob_25002_mat.mat | 144 ++++++ .../gfx/test/bob_25002-bob_25002_mat.mat.meta | 8 + Assets/Scenes/BobberTest.unity | 56 ++- .../Editor/FloatBobberControllerEditor.cs | 40 ++ .../FloatBobberControllerEditor.cs.meta | 3 + .../Editor/FloatBobberControllerProEditor.cs | 40 ++ .../FloatBobberControllerProEditor.cs.meta | 3 + Assets/Scripts/FloatBobberController.cs | 439 +++++++++++++----- Assets/Scripts/FloatBobberController.cs.meta | 3 +- Assets/Scripts/FloatBobberControllerPro.cs | 169 +++++++ .../Scripts/FloatBobberControllerPro.cs.meta | 2 + Assets/Scripts/FloatBobberControllerProV4.cs | 206 ++++++++ .../FloatBobberControllerProV4.cs.meta | 3 + Fishing2.sln.DotSettings.user | 2 + 17 files changed, 1135 insertions(+), 139 deletions(-) create mode 100644 Assets/Resources/gfx/test.meta create mode 100644 Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat create mode 100644 Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat.meta create mode 100644 Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat create mode 100644 Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat.meta create mode 100644 Assets/Scripts/Editor/FloatBobberControllerEditor.cs create mode 100644 Assets/Scripts/Editor/FloatBobberControllerEditor.cs.meta create mode 100644 Assets/Scripts/Editor/FloatBobberControllerProEditor.cs create mode 100644 Assets/Scripts/Editor/FloatBobberControllerProEditor.cs.meta create mode 100644 Assets/Scripts/FloatBobberControllerPro.cs create mode 100644 Assets/Scripts/FloatBobberControllerPro.cs.meta create mode 100644 Assets/Scripts/FloatBobberControllerProV4.cs create mode 100644 Assets/Scripts/FloatBobberControllerProV4.cs.meta diff --git a/Assets/Resources/gfx/test.meta b/Assets/Resources/gfx/test.meta new file mode 100644 index 000000000..13f6fc572 --- /dev/null +++ b/Assets/Resources/gfx/test.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b082403ccfaf6a4e97e2f5ef9ec10e0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat b/Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat new file mode 100644 index 000000000..d6893dae3 --- /dev/null +++ b/Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat @@ -0,0 +1,140 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-3102228912620000641 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: bob_25002-bob_25002_emissive + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _SPECULAR_SETUP + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + 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} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 2800000, guid: ba7837965ad0fcc448dbdf2a1ada9942, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _UVSec: 0 + - _WorkflowMode: 0 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 0, g: 0, b: 0, a: 1} + - _EmissionColor: {r: 0.6985294, g: 0.48542836, b: 0.21572232, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat.meta b/Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat.meta new file mode 100644 index 000000000..46653e713 --- /dev/null +++ b/Assets/Resources/gfx/test/bob_25002-bob_25002_emissive.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f221df6c6ebdb0499361f1418f55f7a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat b/Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat new file mode 100644 index 000000000..adccc0519 --- /dev/null +++ b/Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat @@ -0,0 +1,144 @@ +%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: bob_25002-bob_25002_mat + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _SPECGLOSSMAP + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + 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} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AddPrecomputedVelocity: 0 + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BumpMapScale: 1 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _Fresnel: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.7 + - _GlossyReflections: 1 + - _Metallic: 0.15 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _Shininess: 6 + - _Smoothness: 0.271 + - _SmoothnessTextureChannel: 0 + - _SpecInt: 1 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _UVSec: 0 + - _WorkflowMode: 1 + - _XRMotionVectorsPass: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 0, g: 0, b: 0, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecColor: {r: 1, g: 1, b: 1, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &7261695233209220307 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 diff --git a/Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat.meta b/Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat.meta new file mode 100644 index 000000000..6c5108f66 --- /dev/null +++ b/Assets/Resources/gfx/test/bob_25002-bob_25002_mat.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: be41c511450533646b6a0485f18d26db +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/BobberTest.unity b/Assets/Scenes/BobberTest.unity index 3791f1cd8..4ee5230a0 100644 --- a/Assets/Scenes/BobberTest.unity +++ b/Assets/Scenes/BobberTest.unity @@ -514,7 +514,7 @@ BoxCollider: m_Enabled: 1 serializedVersion: 3 m_Size: {x: 0.005, y: 0.005, z: 0.005} - m_Center: {x: 0, y: -0.01, z: 0} + m_Center: {x: 0, y: 0, z: 0} --- !u!1 &3062767698477047043 GameObject: m_ObjectHideFlags: 0 @@ -627,6 +627,7 @@ GameObject: - component: {fileID: 3372919389234347908} - component: {fileID: 2709071706889968141} - component: {fileID: 3372919389234347909} + - component: {fileID: 3372919389234347910} m_Layer: 0 m_Name: bob_25002 m_TagString: Untagged @@ -770,8 +771,8 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 7881e4598f2626c4a8ffb3e956070a4b, type: 2} - - {fileID: 2100000, guid: 940b6068f71807340a836245c4bbcb7e, type: 2} + - {fileID: 2100000, guid: be41c511450533646b6a0485f18d26db, type: 2} + - {fileID: 2100000, guid: 6f221df6c6ebdb0499361f1418f55f7a, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -872,21 +873,48 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3063281911495263383} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 59f0b74408dbbfe44aee75e1ddf784d3, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::FloatBobberController - useKWS: 0 - waterLayer: - serializedVersion: 2 - m_Bits: 0 - waterRaycastHeight: 10 - stiffness: 0.35 - damping: 0.82 - noiseStrength: 0.02 - lineAttachPoint: {fileID: 2113762193} - tiltStrength: 0 + waterLevel: 0 + bobberVolume: 30 + bobberMass: 1 + bobberHeight: 0.25 + sinkerWeight: 2 + baitWeight: 0.5 + hookWeight: 0.2 + fallSpeed: 8 + riseSpeed: 3 + angleLaySpeed: 2 + uprightSpeed: 2 + bottomDrag: 1.2 + maxLayAngle: 85 + noiseAmp: 0.001 + noiseFreq: 1.5 +--- !u!114 &3372919389234347910 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3063281911495263383} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c0e5ba2adc224f279b89a0adf2bd97a9, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::FloatBobberController + waterLevel: 0 + bobberVolume: 4 + bobberMass: 1 + bobberHeight: 0.25 + sinkerWeight: 2 + baitWeight: 0.5 + hookWeight: 0.2 + fallSpeed: 8 + riseSpeed: 3 + smoothDamping: 8 --- !u!1660057539 &9223372036854775807 SceneRoots: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Editor/FloatBobberControllerEditor.cs b/Assets/Scripts/Editor/FloatBobberControllerEditor.cs new file mode 100644 index 000000000..87b998144 --- /dev/null +++ b/Assets/Scripts/Editor/FloatBobberControllerEditor.cs @@ -0,0 +1,40 @@ +using UnityEditor; +using UnityEngine; + +namespace NBF +{ + [CustomEditor(typeof(FloatBobberController))] + public class FloatBobberControllerEditor : Editor + { + private FloatBobberController _target; + void OnEnable() + { + _target = target as FloatBobberController; + // lookAtPoint = serializedObject.FindProperty("lookAtPoint"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + if (GUILayout.Button("TriggerDownPulse")) + { + _target.TriggerDownPulse(); + } + if (GUILayout.Button("TriggerUpPulse")) + { + _target.TriggerUpPulse(); + } + if (GUILayout.Button("AddFishPull")) + { + _target.AddFishPull(0.5f); + } + if (GUILayout.Button("AddFishPull")) + { + _target.ReleaseFishPull(0.5f); + } + // serializedObject.Update(); + // EditorGUILayout.PropertyField(lookAtPoint); + // serializedObject.ApplyModifiedProperties(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Editor/FloatBobberControllerEditor.cs.meta b/Assets/Scripts/Editor/FloatBobberControllerEditor.cs.meta new file mode 100644 index 000000000..fd51277cf --- /dev/null +++ b/Assets/Scripts/Editor/FloatBobberControllerEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d2e2de2e2fef459895d6c89eb7b66a34 +timeCreated: 1764169703 \ No newline at end of file diff --git a/Assets/Scripts/Editor/FloatBobberControllerProEditor.cs b/Assets/Scripts/Editor/FloatBobberControllerProEditor.cs new file mode 100644 index 000000000..725fce82b --- /dev/null +++ b/Assets/Scripts/Editor/FloatBobberControllerProEditor.cs @@ -0,0 +1,40 @@ +using UnityEditor; +using UnityEngine; + +namespace NBF +{ + [CustomEditor(typeof(FloatBobberControllerPro))] + public class FloatBobberControllerProEditor : Editor + { + private FloatBobberControllerPro _target; + void OnEnable() + { + _target = target as FloatBobberControllerPro; + // lookAtPoint = serializedObject.FindProperty("lookAtPoint"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + if (GUILayout.Button("TriggerDownPulse")) + { + _target.TriggerDownPulse(); + } + if (GUILayout.Button("TriggerUpPulse")) + { + _target.TriggerUpPulse(); + } + if (GUILayout.Button("AddFishPull")) + { + _target.AddFishPull(0.5f); + } + if (GUILayout.Button("AddFishPull")) + { + _target.ReleaseFishPull(0.5f); + } + // serializedObject.Update(); + // EditorGUILayout.PropertyField(lookAtPoint); + // serializedObject.ApplyModifiedProperties(); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Editor/FloatBobberControllerProEditor.cs.meta b/Assets/Scripts/Editor/FloatBobberControllerProEditor.cs.meta new file mode 100644 index 000000000..6125ebdea --- /dev/null +++ b/Assets/Scripts/Editor/FloatBobberControllerProEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a90396d330f942dea5b6ac1aff681614 +timeCreated: 1764167227 \ No newline at end of file diff --git a/Assets/Scripts/FloatBobberController.cs b/Assets/Scripts/FloatBobberController.cs index 507193656..6fd7f79e7 100644 --- a/Assets/Scripts/FloatBobberController.cs +++ b/Assets/Scripts/FloatBobberController.cs @@ -1,170 +1,361 @@ -using UnityEngine; +using UnityEngine; -public class FloatBobberControllerPro : MonoBehaviour +public class FloatBobberController : MonoBehaviour { - [Header("Water")] + [Header("水属性")] public float waterLevel = 0f; - public float waterDensity = 1f; - - [Header("Bobber Physical")] - public float bobberVolume = 30f; // 浮漂最大浮力 (cm³) - public float bobberMass = 1f; // 浮漂自重 (g) - public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度 - - [Header("Tackle Weight")] + + [Header("浮漂属性")] + public float bobberVolume = 30f; // 浮漂最大排水体积 (cm³) + public float bobberMass = 1f; // 浮漂自重 (g) + public float bobberHeight = 0.25f; // 浮漂总高度 + [Range(0, 1)] public float bobberFloatPartRatio = 0.7f; // 浮漂浮体部分占总高度的比例 + + [Header("配件重量")] public float sinkerWeight = 2f; public float baitWeight = 0.5f; public float hookWeight = 0.2f; - [Header("Behaviour")] + [Header("行为参数")] public float fallSpeed = 8f; public float riseSpeed = 3f; - public float angleLaySpeed = 2f; // 躺漂速度 - public float uprightSpeed = 2f; // 立漂速度 - public float bottomDrag = 1.2f; // 铅坠触底阻力(越大越难被浮漂拉起) + public float smoothDamping = 8f; + + // 私有变量 + private float totalDownwardWeight; + private float maxBuoyancyForce; + private float currentSubmergedLength; // 当前浸没长度 + private float bobberFloatPartHeight; // 浮体部分高度 + + // 浮漂状态 + private float currentBuoyancy; // 当前实际浮力 + private Vector3 targetPosition; + + // 冲击力相关 + private float impulseForce = 0f; + private float impulseDecay = 4f; - [Header("Angles")] - public float maxLayAngle = 75f; // 最大躺漂角度 - float currentAngle = 0f; + void Start() + { + InitializeBobber(); + } - [Header("Noise")] - public float noiseAmp = 0.015f; - public float noiseFreq = 1.5f; + void InitializeBobber() + { + // 计算浮体部分高度(能够产生浮力的部分) + bobberFloatPartHeight = bobberHeight * bobberFloatPartRatio; + + // 最大浮力 = 浮体部分完全浸没时的排水量 + maxBuoyancyForce = bobberFloatPartHeight * 100f; // 简化计算,可根据需要调整系数 + + // 初始位置调整:让浮漂底部刚好在水面 + Vector3 pos = transform.position; + pos.y = waterLevel - (bobberHeight * 0.5f); // 假设原点在中心,调整到浮漂底部在水面 + transform.position = pos; + + RecalculateWeights(); + } - float impulseForce = 0f; - float impulseDecay = 4f; - - void Update() + void FixedUpdate() { SimulateBobber(); } + void RecalculateWeights() + { + totalDownwardWeight = bobberMass + sinkerWeight + baitWeight + hookWeight; + } + void SimulateBobber() { - float totalWeight = bobberMass + sinkerWeight + baitWeight + hookWeight; - float netBuoyancy = bobberVolume - totalWeight; // 正 → 上浮;负 → 下拉 - - // ----------------------------- - // ① 计算浮漂底部 Y 的高度 - // ----------------------------- - float bobberBottomY = transform.position.y - bobberHeight * 0.5f; - float bottomY = waterLevel - 0.02f; // 水底高度(可替换真实地形) - - bool sinkerOnBottom = (bobberBottomY <= bottomY); - - // ----------------------------- - // ② 计算 targetY - // ----------------------------- - float targetY; - - if (!sinkerOnBottom) + RecalculateWeights(); + + // ------------------------- + // 1. 计算当前浸没长度和浮力 + // ------------------------- + // 浮漂的基准位置(底部位置) + float bobberBottomY = transform.position.y; + float bobberTopY = bobberBottomY + bobberHeight; + + // 计算浸没长度:浮漂底部到水面的距离,限制在0到浮体高度之间 + float submergedLength = Mathf.Clamp(waterLevel - bobberBottomY, 0f, bobberFloatPartHeight); + currentSubmergedLength = submergedLength; + + // 当前浮力 = (浸没长度 / 浮体高度) * 最大浮力 + float submergedRatio = submergedLength / bobberFloatPartHeight; + currentBuoyancy = submergedRatio * maxBuoyancyForce; + + // ------------------------- + // 2. 计算净力并决定运动 + // ------------------------- + float netForce = currentBuoyancy - totalDownwardWeight; + + // 目标Y位置基于净力计算 + float targetY = transform.position.y; + + if (Mathf.Abs(netForce) < 0.01f) // 基本平衡 { - // 铅坠悬浮 → 浮漂直立 - if (netBuoyancy > 0) + // 保持当前位置,微小波动可以在这里添加 + targetY = transform.position.y; + } + else if (netForce > 0) // 浮力大于重力,上浮 + { + float riseAmount = netForce * 0.001f * riseSpeed; + targetY += riseAmount * Time.deltaTime; + + // 限制不能浮出太多(露出部分不能超过非浮体部分) + float maxBobberTopY = waterLevel + (bobberHeight - bobberFloatPartHeight); + if (bobberTopY + riseAmount > maxBobberTopY) { - float rise = Mathf.Clamp01(netBuoyancy / bobberVolume) * 0.1f; - targetY = waterLevel + rise; - } - else - { - float sink = Mathf.Abs(netBuoyancy) * 0.02f; - targetY = waterLevel - sink; + targetY = maxBobberTopY - bobberHeight; } } - else + else // 重力大于浮力,下沉 { - // 铅坠触底 → 浮漂无法再被向下拉 - if (netBuoyancy > bottomDrag) + float sinkAmount = Mathf.Abs(netForce) * 0.001f * fallSpeed; + targetY -= sinkAmount * Time.deltaTime; + + // 限制不能沉没太多(浮体部分完全浸没后浮力达到最大) + float minBobberBottomY = waterLevel - bobberFloatPartHeight; + if (bobberBottomY - sinkAmount < minBobberBottomY) { - // 浮漂浮力足够将其立起来 - float rise = Mathf.Clamp01((netBuoyancy - bottomDrag) / bobberVolume) * 0.1f; - targetY = waterLevel + rise; // 轻轻立起 - } - else - { - // 浮漂浮力不足 → 躺漂 - targetY = waterLevel + 0.01f; // 漂身贴水 + targetY = minBobberBottomY; } } - - // 水波噪声 - targetY += Mathf.Sin(Time.time * noiseFreq) * noiseAmp; - - // 顿口/顶漂力 - if (impulseForce != 0f) + + // ------------------------- + // 3. 应用冲击力 + // ------------------------- + if (Mathf.Abs(impulseForce) > 0.01f) { targetY += impulseForce * Time.deltaTime; impulseForce = Mathf.Lerp(impulseForce, 0, Time.deltaTime * impulseDecay); } - - // ----------------------------- - // ③ 上浮 / 下沉差速 - // ----------------------------- - float y = transform.position.y; - float diff = targetY - y; - - if (diff > 0) // 上浮 - y += diff * Time.deltaTime * riseSpeed; - else - y += diff * Time.deltaTime * fallSpeed; - - transform.position = new Vector3(transform.position.x, y, transform.position.z); - - // ----------------------------- - // ④ 浮漂角度控制 - // ----------------------------- - float targetAngle = 0f; - - if (sinkerOnBottom) - { - // 触底 → 判断是否能立漂 - if (netBuoyancy > bottomDrag) - { - targetAngle = 0f; // 立漂 - } - else - { - // 躺漂 - targetAngle = maxLayAngle; - } - } - else - { - // 铅坠在水中 → 漂直立 - targetAngle = 0f; - } - - // 平滑角度 - currentAngle = Mathf.Lerp( - currentAngle, - targetAngle, - Time.deltaTime * (targetAngle == 0 ? uprightSpeed : angleLaySpeed) - ); - - transform.rotation = Quaternion.Euler(currentAngle, 0, 0); + + // ------------------------- + // 4. 平滑移动 + // ------------------------- + targetPosition = new Vector3(transform.position.x, targetY, transform.position.z); + transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smoothDamping); + + // 调试信息 + DebugDisplay(); + } + + void DebugDisplay() + { + Debug.Log($"浸没比例: {(currentSubmergedLength / bobberFloatPartHeight):P1} " + + $"当前浮力: {currentBuoyancy:F2} " + + $"总重力: {totalDownwardWeight:F2} " + + $"净力: {currentBuoyancy - totalDownwardWeight:F2}"); + } + + // ---------------------------------------- + // 公共方法 - 用于调漂和鱼咬钩 + // ---------------------------------------- + + /// + /// 调整配重(用于调漂) + /// + public void AdjustSinkerWeight(float newWeight) + { + sinkerWeight = newWeight; + RecalculateWeights(); + } + + /// + /// 获取当前调目(浮漂露出水面的格数) + /// + public float GetCurrentVisibleMarks() + { + float bobberBottomY = transform.position.y; + float visibleHeight = (bobberBottomY + bobberHeight) - waterLevel; + float markHeight = bobberHeight / 10f; // 假设浮漂有10格 + return Mathf.Max(0, visibleHeight / markHeight); + } + + /// + /// 设置目标调目(自动计算需要的配重) + /// + public void SetTargetMarks(float targetMarks) + { + float markHeight = bobberHeight / 10f; + float targetVisibleHeight = targetMarks * markHeight; + float targetSubmergedLength = bobberFloatPartHeight - targetVisibleHeight; + + // 需要的浮力 = (浸没长度 / 浮体高度) * 最大浮力 + float requiredBuoyancy = (targetSubmergedLength / bobberFloatPartHeight) * maxBuoyancyForce; + + // 配重 = 浮漂自重 + 钩饵重 - 需要的浮力 + float requiredSinkerWeight = bobberMass + hookWeight + baitWeight - requiredBuoyancy; + + sinkerWeight = Mathf.Max(0, requiredSinkerWeight); + RecalculateWeights(); } // ---------------------------------------- - // 外部控制接口 + // 鱼咬钩相关方法 // ---------------------------------------- - - public void TriggerDownPulse(float s = 0.8f) + + public void TriggerDownPulse(float strength = 0.8f) { - impulseForce -= Mathf.Abs(s); + impulseForce -= Mathf.Abs(strength); } - public void TriggerUpPulse(float s = 0.8f) + public void TriggerUpPulse(float strength = 0.8f) { - impulseForce += Mathf.Abs(s); + impulseForce += Mathf.Abs(strength); } - public void AddFishPull(float v) + public void AddFishPull(float pullForce) { - sinkerWeight += v; + // 鱼的拉力相当于增加向下的力 + sinkerWeight += pullForce; } - public void ReleaseFishPull(float v) + public void ReleaseFishPull(float pullForce) { - sinkerWeight -= v; + sinkerWeight -= pullForce; + } + + // ---------------------------------------- + // 可视化调试 + // ---------------------------------------- + + void OnDrawGizmos() + { + // 绘制水面 + Gizmos.color = Color.blue; + Gizmos.DrawLine(new Vector3(-1, waterLevel, 0), new Vector3(1, waterLevel, 0)); + + // 绘制浮漂 + if (Application.isPlaying) + { + // 浸没部分用蓝色 + Gizmos.color = Color.cyan; + float submergedBottom = transform.position.y; + float submergedTop = submergedBottom + currentSubmergedLength; + Gizmos.DrawWireCube( + new Vector3(transform.position.x, (submergedBottom + submergedTop) * 0.5f, transform.position.z), + new Vector3(0.1f, currentSubmergedLength, 0.1f) + ); + + // 露出部分用红色 + Gizmos.color = Color.red; + float visibleBottom = submergedTop; + float visibleTop = transform.position.y + bobberHeight; + float visibleHeight = visibleTop - visibleBottom; + if (visibleHeight > 0) + { + Gizmos.DrawWireCube( + new Vector3(transform.position.x, (visibleBottom + visibleTop) * 0.5f, transform.position.z), + new Vector3(0.1f, visibleHeight, 0.1f) + ); + } + } } } + + +// using UnityEngine; +// +// public class FloatBobberController : MonoBehaviour +// { +// [Header("水属性")] public float waterLevel = 0f; +// [Header("浮漂最大浮力")] public float bobberVolume = 30f; // 浮漂最大浮力 (cm³) +// [Header("浮漂自重")] public float bobberMass = 1f; // 浮漂自重 (g) +// public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度 +// +// [Header("配件重量")] public float sinkerWeight = 2f; +// public float baitWeight = 0.5f; +// public float hookWeight = 0.2f; +// +// [Header("Behaviour")] public float fallSpeed = 8f; +// public float riseSpeed = 3f; +// public float smoothDamping = 8f; // 插值平滑 +// +// // [Header("Noise")] public float noiseAmp = 0.015f; +// // public float noiseFreq = 1.5f; +// +// float impulseForce = 0f; +// float impulseDecay = 4f; +// +// void FixedUpdate() +// { +// SimulateBobber(); +// } +// +// void SimulateBobber() +// { +// float totalDownwardWeight = bobberMass + sinkerWeight + baitWeight + hookWeight; +// +// float maxBuoyancy = bobberVolume; // 最大浮力 = 体积 +// float netBuoyancy = maxBuoyancy - totalDownwardWeight; +// +// float targetY; +// +// // ------------------------- +// // 1. 判断浮漂应该沉多少(吃水深度) +// // ------------------------- +// if (netBuoyancy > 0) +// { +// float buoyPercent = Mathf.Clamp01(netBuoyancy / maxBuoyancy); +// float rise = buoyPercent * 0.1f; // 浮漂露出水面的高度 +// +// targetY = waterLevel + rise; +// +// // targetY += Mathf.Sin(Time.time * noiseFreq) * noiseAmp; // 微扰模拟波浪 +// } +// else +// { +// // 净浮力为负 → 说明浮漂整体被拉下,沉入水中 +// float sinkDistance = Mathf.Abs(netBuoyancy) * 0.03f; +// targetY = waterLevel - sinkDistance; +// } +// +// // 顿口/顶漂力 +// if (impulseForce != 0f) +// { +// targetY += impulseForce * Time.deltaTime; +// impulseForce = Mathf.Lerp(impulseForce, 0, Time.deltaTime * impulseDecay); +// } +// +// // ----------------------------- +// // ③ 上浮 / 下沉差速 +// // ----------------------------- +// float y = transform.position.y; +// float diff = targetY - y; +// +// if (diff > 0) // 上浮 +// y += diff * Time.deltaTime * riseSpeed; +// else +// y += diff * Time.deltaTime * fallSpeed; +// +// transform.position = new Vector3(transform.position.x, y, transform.position.z); +// } +// +// +// // ---------------------------------------- +// // 外部控制接口 +// // ---------------------------------------- +// +// public void TriggerDownPulse(float s = 0.8f) +// { +// impulseForce -= Mathf.Abs(s); +// } +// +// public void TriggerUpPulse(float s = 0.8f) +// { +// impulseForce += Mathf.Abs(s); +// } +// +// public void AddFishPull(float v) +// { +// sinkerWeight += v; +// } +// +// public void ReleaseFishPull(float v) +// { +// sinkerWeight -= v; +// } +// } \ No newline at end of file diff --git a/Assets/Scripts/FloatBobberController.cs.meta b/Assets/Scripts/FloatBobberController.cs.meta index 8f5b04fc7..cf5cda6d5 100644 --- a/Assets/Scripts/FloatBobberController.cs.meta +++ b/Assets/Scripts/FloatBobberController.cs.meta @@ -1,2 +1,3 @@ fileFormatVersion: 2 -guid: 59f0b74408dbbfe44aee75e1ddf784d3 \ No newline at end of file +guid: c0e5ba2adc224f279b89a0adf2bd97a9 +timeCreated: 1764168783 \ No newline at end of file diff --git a/Assets/Scripts/FloatBobberControllerPro.cs b/Assets/Scripts/FloatBobberControllerPro.cs new file mode 100644 index 000000000..cf7d68c6f --- /dev/null +++ b/Assets/Scripts/FloatBobberControllerPro.cs @@ -0,0 +1,169 @@ +using UnityEngine; + +public class FloatBobberControllerPro : MonoBehaviour +{ + [Header("Water")] + public float waterLevel = 0f; + + [Header("Bobber Physical")] + public float bobberVolume = 30f; // 浮漂最大浮力 (cm³) + public float bobberMass = 1f; // 浮漂自重 (g) + public float bobberHeight = 0.25f; // 浮漂长度,用来决定躺漂角度 + + [Header("Tackle Weight")] + public float sinkerWeight = 2f; + public float baitWeight = 0.5f; + public float hookWeight = 0.2f; + + [Header("Behaviour")] + public float fallSpeed = 8f; + public float riseSpeed = 3f; + public float angleLaySpeed = 2f; // 躺漂速度 + public float uprightSpeed = 2f; // 立漂速度 + public float bottomDrag = 1.2f; // 铅坠触底阻力(越大越难被浮漂拉起) + + [Header("Angles")] + public float maxLayAngle = 75f; // 最大躺漂角度 + float currentAngle = 0f; + + [Header("Noise")] + public float noiseAmp = 0.015f; + public float noiseFreq = 1.5f; + + float impulseForce = 0f; + float impulseDecay = 4f; + + void Update() + { + SimulateBobber(); + } + + void SimulateBobber() + { + float totalWeight = bobberMass + sinkerWeight + baitWeight + hookWeight; + float netBuoyancy = bobberVolume - totalWeight; // 正 → 上浮;负 → 下拉 + + // ----------------------------- + // ① 计算浮漂底部 Y 的高度 + // ----------------------------- + float bobberBottomY = transform.position.y - bobberHeight * 0.5f; + float bottomY = waterLevel - 0.02f; // 水底高度(可替换真实地形) + + bool sinkerOnBottom = (bobberBottomY <= bottomY); + + // ----------------------------- + // ② 计算 targetY + // ----------------------------- + float targetY; + + if (!sinkerOnBottom) + { + // 铅坠悬浮 → 浮漂直立 + if (netBuoyancy > 0) + { + float rise = Mathf.Clamp01(netBuoyancy / bobberVolume) * 0.1f; + targetY = waterLevel + rise; + } + else + { + float sink = Mathf.Abs(netBuoyancy) * 0.02f; + targetY = waterLevel - sink; + } + } + else + { + // 铅坠触底 → 浮漂无法再被向下拉 + if (netBuoyancy > bottomDrag) + { + // 浮漂浮力足够将其立起来 + float rise = Mathf.Clamp01((netBuoyancy - bottomDrag) / bobberVolume) * 0.1f; + targetY = waterLevel + rise; // 轻轻立起 + } + else + { + // 浮漂浮力不足 → 躺漂 + targetY = waterLevel + 0.01f; // 漂身贴水 + } + } + + // 水波噪声 + targetY += Mathf.Sin(Time.time * noiseFreq) * noiseAmp; + + // 顿口/顶漂力 + if (impulseForce != 0f) + { + targetY += impulseForce * Time.deltaTime; + impulseForce = Mathf.Lerp(impulseForce, 0, Time.deltaTime * impulseDecay); + } + + // ----------------------------- + // ③ 上浮 / 下沉差速 + // ----------------------------- + float y = transform.position.y; + float diff = targetY - y; + + if (diff > 0) // 上浮 + y += diff * Time.deltaTime * riseSpeed; + else + y += diff * Time.deltaTime * fallSpeed; + + transform.position = new Vector3(transform.position.x, y, transform.position.z); + + // ----------------------------- + // ④ 浮漂角度控制 + // ----------------------------- + float targetAngle = 0f; + + if (sinkerOnBottom) + { + // 触底 → 判断是否能立漂 + if (netBuoyancy > bottomDrag) + { + targetAngle = 0f; // 立漂 + } + else + { + // 躺漂 + targetAngle = maxLayAngle; + } + } + else + { + // 铅坠在水中 → 漂直立 + targetAngle = 0f; + } + + // 平滑角度 + currentAngle = Mathf.Lerp( + currentAngle, + targetAngle, + Time.deltaTime * (targetAngle == 0 ? uprightSpeed : angleLaySpeed) + ); + + transform.rotation = Quaternion.Euler(currentAngle, 0, 0); + } + + // ---------------------------------------- + // 外部控制接口 + // ---------------------------------------- + + public void TriggerDownPulse(float s = 0.8f) + { + impulseForce -= Mathf.Abs(s); + } + + public void TriggerUpPulse(float s = 0.8f) + { + impulseForce += Mathf.Abs(s); + } + + public void AddFishPull(float v) + { + sinkerWeight += v; + } + + public void ReleaseFishPull(float v) + { + sinkerWeight -= v; + } +} diff --git a/Assets/Scripts/FloatBobberControllerPro.cs.meta b/Assets/Scripts/FloatBobberControllerPro.cs.meta new file mode 100644 index 000000000..8f5b04fc7 --- /dev/null +++ b/Assets/Scripts/FloatBobberControllerPro.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 59f0b74408dbbfe44aee75e1ddf784d3 \ No newline at end of file diff --git a/Assets/Scripts/FloatBobberControllerProV4.cs b/Assets/Scripts/FloatBobberControllerProV4.cs new file mode 100644 index 000000000..e895c033c --- /dev/null +++ b/Assets/Scripts/FloatBobberControllerProV4.cs @@ -0,0 +1,206 @@ +using UnityEngine; + +public enum BobberState +{ + LyingDown, // 躺漂 + RisingUp, // 起漂 + Standing, // 正常站立 + Bottom, // 挂底 + TopLift, // 顶漂 + DownPull, // 黑漂 + Nibble // 小顿口 +} + +public class FloatBobberControllerProV4 : MonoBehaviour +{ + [Header("Environment")] + public float waterLevel = 0f; + + [Header("Float Settings")] + public float floatLength = 0.20f; // 漂总长度 + public float buoyancyForce = 0.35f; // 浮力强度 + public float mass = 0.015f; // 重量 + public float tiltRecoverySpeed = 3f; // 漂恢复垂直速度 + public float maxTiltAngle = 60f; // 躺漂最大角度 + + [Header("Line Settings")] + public float lineTension = 0f; // 动态线张力(由鱼影响) + public float bottomDrag = 1.5f; // 铅坠触底时的阻力 + + [Header("State Machine")] + public BobberState state = BobberState.LyingDown; + + // internal vars + private float verticalSpeed = 0f; + private float angle = 60f; // 初始躺漂角度 + private float lastHeight; + private float deltaY; + + void Start() + { + lastHeight = transform.position.y; + state = BobberState.LyingDown; + } + + void Update() + { + deltaY = transform.position.y - lastHeight; + lastHeight = transform.position.y; + + ApplyPhysics(); + ProcessStateMachine(); + ApplyRotation(); + } + + // --------------------------------------------------------------------- + // 一切物理都由状态机控制 + // --------------------------------------------------------------------- + void ProcessStateMachine() + { + switch (state) + { + case BobberState.LyingDown: + LyingDownBehaviour(); + break; + + case BobberState.RisingUp: + RisingUpBehaviour(); + break; + + case BobberState.Standing: + StandingBehaviour(); + break; + + case BobberState.Bottom: + BottomBehaviour(); + break; + + case BobberState.TopLift: + TopLiftBehaviour(); + break; + + case BobberState.DownPull: + DownPullBehaviour(); + break; + + case BobberState.Nibble: + NibbleBehaviour(); + break; + } + + AutoTransition(); + } + + // --------------------------------------------------------------------- + // 【状态 → 行为】 + // --------------------------------------------------------------------- + + void LyingDownBehaviour() + { + // 浮漂处于平躺,几乎无浮力 + angle = Mathf.Lerp(angle, maxTiltAngle, Time.deltaTime * 1.5f); + + // 水面浮力很小 + verticalSpeed += (buoyancyForce * 0.1f - mass * 9.8f) * Time.deltaTime; + } + + void RisingUpBehaviour() + { + // 浮漂正在被浮力慢慢扶正 + angle = Mathf.Lerp(angle, 0, Time.deltaTime * (tiltRecoverySpeed * 0.7f)); + + // 浮力略加强 + verticalSpeed += (buoyancyForce * 0.5f) * Time.deltaTime; + } + + void StandingBehaviour() + { + // 完全立稳 + angle = Mathf.Lerp(angle, 0, Time.deltaTime * tiltRecoverySpeed); + + // 浮力与重力平衡,小幅波动 + verticalSpeed += Mathf.Sin(Time.time * 4f) * 0.001f; + } + + void BottomBehaviour() + { + // 铅坠或饵触底 → 浮漂立不起来 + angle = Mathf.Lerp(angle, 20f, Time.deltaTime * 2f); + + // 上浮被底部拖住 + verticalSpeed *= 0.6f; + } + + void TopLiftBehaviour() + { + // 顶漂 → 漂被往上托一点 + verticalSpeed += 0.02f; + } + + void DownPullBehaviour() + { + // 黑漂 → 往下猛拉 + verticalSpeed -= 0.05f; + } + + void NibbleBehaviour() + { + // 小顿口 → 轻微波动 + verticalSpeed += Mathf.Sin(Time.time * 20f) * 0.0015f; + } + + // --------------------------------------------------------------------- + // 状态自动切换 + // --------------------------------------------------------------------- + void AutoTransition() + { + // 1. 浮漂露出 40% 以上 → 起漂或站漂 + float headHeight = transform.position.y + floatLength; + + if (state == BobberState.LyingDown && headHeight > waterLevel - 0.02f) + state = BobberState.RisingUp; + + if (state == BobberState.RisingUp && angle < 12f) + state = BobberState.Standing; + + // 2. 挂底判定 + float tailHeight = transform.position.y - floatLength; + if (tailHeight < waterLevel - 0.03f) + state = BobberState.Bottom; + + // 3. 顶漂 + if (deltaY > 0.015f) + state = BobberState.TopLift; + + // 4. 黑漂 + if (deltaY < -0.02f) + state = BobberState.DownPull; + + // 5. 小顿口 + if (Mathf.Abs(deltaY) > 0.003f && Mathf.Abs(deltaY) < 0.015f) + state = BobberState.Nibble; + } + + // --------------------------------------------------------------------- + // 垂直物理 + // --------------------------------------------------------------------- + void ApplyPhysics() + { + float submerged = Mathf.Clamp01((waterLevel - transform.position.y) * 8f); + float upForce = buoyancyForce * submerged - mass * 9.8f; + + verticalSpeed += upForce * Time.deltaTime; + verticalSpeed = Mathf.Clamp(verticalSpeed, -0.2f, 0.2f); + + transform.position += new Vector3(0, verticalSpeed, 0); + } + + // --------------------------------------------------------------------- + // 倾斜角控制 + // --------------------------------------------------------------------- + void ApplyRotation() + { + Quaternion q = Quaternion.Euler(angle, 0, 0); + transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * 8f); + } +} diff --git a/Assets/Scripts/FloatBobberControllerProV4.cs.meta b/Assets/Scripts/FloatBobberControllerProV4.cs.meta new file mode 100644 index 000000000..66be78d20 --- /dev/null +++ b/Assets/Scripts/FloatBobberControllerProV4.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 725d1d7ecc254c8a980d997ac7a9d5d3 +timeCreated: 1764166393 \ No newline at end of file diff --git a/Fishing2.sln.DotSettings.user b/Fishing2.sln.DotSettings.user index ff05a6ef8..48db78f80 100644 --- a/Fishing2.sln.DotSettings.user +++ b/Fishing2.sln.DotSettings.user @@ -15,6 +15,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -23,6 +24,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded