提交修改
This commit is contained in:
@@ -1,36 +0,0 @@
|
|||||||
%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: 9d66919bfa33a7445b32a45410e0ccfe, type: 3}
|
|
||||||
m_Name: FishingRigDefinition
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::FishingRigDefinition
|
|
||||||
logicalNodes:
|
|
||||||
- id:
|
|
||||||
nodeType: 0
|
|
||||||
distanceFromPrevious: 0
|
|
||||||
virtualNodeCount: 0
|
|
||||||
gravityScale: 0
|
|
||||||
damping: 0
|
|
||||||
debugColor: {r: 0.17723638, g: 1, b: 0, a: 1}
|
|
||||||
- id:
|
|
||||||
nodeType: 2
|
|
||||||
distanceFromPrevious: 0
|
|
||||||
virtualNodeCount: 0
|
|
||||||
gravityScale: 0
|
|
||||||
damping: 0
|
|
||||||
debugColor: {r: 0, g: 0.61897755, b: 1, a: 1}
|
|
||||||
- id:
|
|
||||||
nodeType: 3
|
|
||||||
distanceFromPrevious: 0
|
|
||||||
virtualNodeCount: 0
|
|
||||||
gravityScale: 0
|
|
||||||
damping: 0
|
|
||||||
debugColor: {r: 1, g: 0, b: 0, a: 1}
|
|
||||||
BIN
Assets/New Terrain.asset
Normal file
BIN
Assets/New Terrain.asset
Normal file
Binary file not shown.
@@ -1,8 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a48cb68bf14ac8c429abc96a2cdb7821
|
guid: 353d79ea0bc081b4c8f234204cbdcf46
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
mainObjectFileID: 15600000
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
@@ -392,33 +392,17 @@ GameObject:
|
|||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 445360722}
|
- component: {fileID: 445360722}
|
||||||
- component: {fileID: 445360721}
|
- component: {fileID: 445360726}
|
||||||
- component: {fileID: 445360723}
|
|
||||||
- component: {fileID: 445360725}
|
- component: {fileID: 445360725}
|
||||||
- component: {fileID: 445360724}
|
- component: {fileID: 445360724}
|
||||||
|
- component: {fileID: 445360723}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: FishingLineRoot
|
m_Name: LineRoot
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 1
|
||||||
--- !u!114 &445360721
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 445360720}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 5194be581ec15764eab72311e62182eb, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::FishingGameplayController
|
|
||||||
solver: {fileID: 445360723}
|
|
||||||
reelSpeed: 0.5
|
|
||||||
reelInKey: 101
|
|
||||||
reelOutKey: 113
|
|
||||||
--- !u!4 &445360722
|
--- !u!4 &445360722
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -428,69 +412,17 @@ Transform:
|
|||||||
m_GameObject: {fileID: 445360720}
|
m_GameObject: {fileID: 445360720}
|
||||||
serializedVersion: 2
|
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_LocalPosition: {x: -0, y: 1, z: -0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children:
|
||||||
|
- {fileID: 1930940348}
|
||||||
|
- {fileID: 1230107384}
|
||||||
|
- {fileID: 1508371650}
|
||||||
|
- {fileID: 663592153}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &445360723
|
--- !u!114 &445360723
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 445360720}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: b8bc695f40e430b4588f7fb29f79a3e3, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::FishingLineSolver
|
|
||||||
rigDefinition: {fileID: 11400000, guid: a48cb68bf14ac8c429abc96a2cdb7821, type: 2}
|
|
||||||
inlineLogicalNodes:
|
|
||||||
- id: Start
|
|
||||||
nodeType: 0
|
|
||||||
distanceFromPrevious: 0
|
|
||||||
virtualNodeCount: 0
|
|
||||||
gravityScale: 0
|
|
||||||
damping: 0
|
|
||||||
debugColor: {r: 0.4, g: 1, b: 0.6, a: 1}
|
|
||||||
- id: Float
|
|
||||||
nodeType: 1
|
|
||||||
distanceFromPrevious: 1.2
|
|
||||||
virtualNodeCount: 10
|
|
||||||
gravityScale: 0.15
|
|
||||||
damping: 0.08
|
|
||||||
debugColor: {r: 1, g: 0.75, b: 0.2, a: 1}
|
|
||||||
- id: Sinker
|
|
||||||
nodeType: 2
|
|
||||||
distanceFromPrevious: 1.4
|
|
||||||
virtualNodeCount: 10
|
|
||||||
gravityScale: 1.6
|
|
||||||
damping: 0.02
|
|
||||||
debugColor: {r: 0.7, g: 0.85, b: 1, a: 1}
|
|
||||||
- id: Hook
|
|
||||||
nodeType: 3
|
|
||||||
distanceFromPrevious: 0.8
|
|
||||||
virtualNodeCount: 10
|
|
||||||
gravityScale: 1.2
|
|
||||||
damping: 0.03
|
|
||||||
debugColor: {r: 1, g: 0.35, b: 0.35, a: 1}
|
|
||||||
startAnchor: {fileID: 1538371803}
|
|
||||||
initialDirection: {x: 0, y: -1, z: 0}
|
|
||||||
solverIterations: 8
|
|
||||||
gravity: 9.81
|
|
||||||
globalDamping: 0.01
|
|
||||||
tensionSmoothing: 0.18
|
|
||||||
simulateInFixedUpdate: 0
|
|
||||||
currentLineLength: 3.4
|
|
||||||
minLineLength: 1.2
|
|
||||||
maxLineLength: 8.5
|
|
||||||
drawDebug: 1
|
|
||||||
debugNodeRadius: 0.03
|
|
||||||
virtualNodeColor: {r: 0.4, g: 0.75, b: 1, a: 1}
|
|
||||||
segmentColor: {r: 0.85, g: 0.9, b: 1, a: 1}
|
|
||||||
--- !u!114 &445360724
|
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
@@ -502,10 +434,9 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 0af449a2493cf8c4281c9d5ae01c2a92, type: 3}
|
m_Script: {fileID: 11500000, guid: 0af449a2493cf8c4281c9d5ae01c2a92, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::FishingLineRendererBinder
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineRendererBinder
|
||||||
solver: {fileID: 445360723}
|
solver: {fileID: 445360725}
|
||||||
lineRenderer: {fileID: 445360725}
|
lineRenderer: {fileID: 445360724}
|
||||||
attachmentBindings: []
|
--- !u!120 &445360724
|
||||||
--- !u!120 &445360725
|
|
||||||
LineRenderer:
|
LineRenderer:
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -556,7 +487,7 @@ LineRenderer:
|
|||||||
m_MaskInteraction: 0
|
m_MaskInteraction: 0
|
||||||
m_Positions:
|
m_Positions:
|
||||||
- {x: 0, y: 0, z: 0}
|
- {x: 0, y: 0, z: 0}
|
||||||
- {x: 0, y: -0.01, z: 1}
|
- {x: 0, y: 0, z: 1}
|
||||||
m_Parameters:
|
m_Parameters:
|
||||||
serializedVersion: 3
|
serializedVersion: 3
|
||||||
widthMultiplier: 1
|
widthMultiplier: 1
|
||||||
@@ -615,6 +546,334 @@ LineRenderer:
|
|||||||
m_UseWorldSpace: 1
|
m_UseWorldSpace: 1
|
||||||
m_Loop: 0
|
m_Loop: 0
|
||||||
m_ApplyActiveColorSpace: 1
|
m_ApplyActiveColorSpace: 1
|
||||||
|
--- !u!114 &445360725
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 445360720}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b8bc695f40e430b4588f7fb29f79a3e3, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineSolver
|
||||||
|
lineRoot: {fileID: 445360722}
|
||||||
|
startAnchor: {fileID: 1538371803}
|
||||||
|
solverIterations: 8
|
||||||
|
gravity: 9.81
|
||||||
|
globalDamping: 0.01
|
||||||
|
initialDirection: {x: 0, y: -1, z: 0}
|
||||||
|
autoUseNodeDistances: 1
|
||||||
|
manualTotalLength: 3
|
||||||
|
minManualLength: 0.5
|
||||||
|
maxManualLength: 15
|
||||||
|
drawDebug: 1
|
||||||
|
debugPointRadius: 0.03
|
||||||
|
virtualPointColor: {r: 0.45, g: 0.75, b: 1, a: 1}
|
||||||
|
segmentColor: {r: 0.9, g: 0.95, b: 1, a: 1}
|
||||||
|
--- !u!114 &445360726
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 445360720}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 465a2f7c62ee04948b577ee52382c43e, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineTestController
|
||||||
|
solver: {fileID: 445360725}
|
||||||
|
reelSpeed: 1.5
|
||||||
|
reelInKey: 101
|
||||||
|
reelOutKey: 113
|
||||||
|
--- !u!1 &528985859
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 528985860}
|
||||||
|
- component: {fileID: 528985863}
|
||||||
|
- component: {fileID: 528985862}
|
||||||
|
- component: {fileID: 528985861}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Cube
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &528985860
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 528985859}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 1230107384}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!65 &528985861
|
||||||
|
BoxCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 528985859}
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_IncludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_ExcludeLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 0
|
||||||
|
m_LayerOverridePriority: 0
|
||||||
|
m_IsTrigger: 0
|
||||||
|
m_ProvidesContacts: 0
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 3
|
||||||
|
m_Size: {x: 1, y: 1, z: 1}
|
||||||
|
m_Center: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!23 &528985862
|
||||||
|
MeshRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 528985859}
|
||||||
|
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 &528985863
|
||||||
|
MeshFilter:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 528985859}
|
||||||
|
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
--- !u!1 &663592152
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 663592153}
|
||||||
|
- component: {fileID: 663592154}
|
||||||
|
- component: {fileID: 663592155}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: TerminalNode
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &663592153
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 663592152}
|
||||||
|
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: 733128128}
|
||||||
|
m_Father: {fileID: 445360722}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &663592154
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 663592152}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 6e0f6939c01292c4bb2adc26e7d6f24f, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineNode
|
||||||
|
nodeId: Terminal
|
||||||
|
nodeType: 3
|
||||||
|
distanceFromPrevious: 0
|
||||||
|
virtualNodeCount: 3
|
||||||
|
gravityScale: 1
|
||||||
|
damping: 0.04
|
||||||
|
alignToLine: 1
|
||||||
|
localForwardAxis: {x: 0, y: 0, z: 1}
|
||||||
|
upAxis: {x: 0, y: 1, z: 0}
|
||||||
|
debugColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
--- !u!114 &663592155
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 663592152}
|
||||||
|
m_Enabled: 0
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 953e78672cb7e2a4ebacb573fa9a7627, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingGroundProbeNodeBehaviour
|
||||||
|
behaviourEnabled: 1
|
||||||
|
probeShape: 2
|
||||||
|
collisionLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 64
|
||||||
|
probeRadius: 0.08
|
||||||
|
capsuleHeight: 0.3
|
||||||
|
boxHalfExtents: {x: 0.08, y: 0.08, z: 0.08}
|
||||||
|
castDistance: 0.5
|
||||||
|
collisionPadding: 0.01
|
||||||
|
contactDamping: 0.2
|
||||||
|
contactFriction: 0.85
|
||||||
|
contactSnapDistance: 0.03
|
||||||
|
drawDebug: 1
|
||||||
|
castColor: {r: 1, g: 0.85, b: 0.2, a: 0.9}
|
||||||
|
hitColor: {r: 0.25, g: 1, b: 0.4, a: 1}
|
||||||
|
--- !u!1 &733128127
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 733128128}
|
||||||
|
- component: {fileID: 733128131}
|
||||||
|
- component: {fileID: 733128130}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Cube
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &733128128
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 733128127}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 663592153}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!23 &733128130
|
||||||
|
MeshRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 733128127}
|
||||||
|
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 &733128131
|
||||||
|
MeshFilter:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 733128127}
|
||||||
|
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
--- !u!1 &832575517
|
--- !u!1 &832575517
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -664,6 +923,144 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &1230107383
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1230107384}
|
||||||
|
- component: {fileID: 1230107385}
|
||||||
|
- component: {fileID: 1230107386}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: FloatNode
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1230107384
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1230107383}
|
||||||
|
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: 528985860}
|
||||||
|
m_Father: {fileID: 445360722}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1230107385
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1230107383}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 6e0f6939c01292c4bb2adc26e7d6f24f, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineNode
|
||||||
|
nodeId: Float
|
||||||
|
nodeType: 1
|
||||||
|
distanceFromPrevious: 0
|
||||||
|
virtualNodeCount: 3
|
||||||
|
gravityScale: 1
|
||||||
|
damping: 0.04
|
||||||
|
alignToLine: 1
|
||||||
|
localForwardAxis: {x: 0, y: 0, z: 1}
|
||||||
|
upAxis: {x: 0, y: 1, z: 0}
|
||||||
|
debugColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
--- !u!114 &1230107386
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1230107383}
|
||||||
|
m_Enabled: 0
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 953e78672cb7e2a4ebacb573fa9a7627, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingGroundProbeNodeBehaviour
|
||||||
|
behaviourEnabled: 1
|
||||||
|
probeShape: 1
|
||||||
|
collisionLayers:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 64
|
||||||
|
probeRadius: 0.08
|
||||||
|
capsuleHeight: 0.3
|
||||||
|
boxHalfExtents: {x: 0.08, y: 0.08, z: 0.08}
|
||||||
|
castDistance: 0.5
|
||||||
|
collisionPadding: 0.01
|
||||||
|
contactDamping: 0.2
|
||||||
|
contactFriction: 0.85
|
||||||
|
contactSnapDistance: 0.03
|
||||||
|
drawDebug: 1
|
||||||
|
castColor: {r: 1, g: 0.85, b: 0.2, a: 0.9}
|
||||||
|
hitColor: {r: 0.25, g: 1, b: 0.4, a: 1}
|
||||||
|
--- !u!1 &1508371649
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1508371650}
|
||||||
|
- component: {fileID: 1508371651}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: WeightNode
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1508371650
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1508371649}
|
||||||
|
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: 445360722}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1508371651
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1508371649}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 6e0f6939c01292c4bb2adc26e7d6f24f, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineNode
|
||||||
|
nodeId: Weight
|
||||||
|
nodeType: 2
|
||||||
|
distanceFromPrevious: 0
|
||||||
|
virtualNodeCount: 3
|
||||||
|
gravityScale: 1
|
||||||
|
damping: 0.04
|
||||||
|
alignToLine: 1
|
||||||
|
localForwardAxis: {x: 0, y: 0, z: 1}
|
||||||
|
upAxis: {x: 0, y: 1, z: 0}
|
||||||
|
debugColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
--- !u!1 &1538371799
|
--- !u!1 &1538371799
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -770,12 +1167,159 @@ Transform:
|
|||||||
m_GameObject: {fileID: 1538371799}
|
m_GameObject: {fileID: 1538371799}
|
||||||
serializedVersion: 2
|
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_LocalPosition: {x: 0, y: 1, z: 0}
|
||||||
m_LocalScale: {x: 0.02, y: 0.02, z: 0.02}
|
m_LocalScale: {x: 0.02, y: 0.02, z: 0.02}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &1603549249
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1603549252}
|
||||||
|
- component: {fileID: 1603549251}
|
||||||
|
- component: {fileID: 1603549250}
|
||||||
|
m_Layer: 6
|
||||||
|
m_Name: Terrain
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 2147483647
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!154 &1603549250
|
||||||
|
TerrainCollider:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1603549249}
|
||||||
|
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: 353d79ea0bc081b4c8f234204cbdcf46, type: 2}
|
||||||
|
m_EnableTreeColliders: 1
|
||||||
|
--- !u!218 &1603549251
|
||||||
|
Terrain:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1603549249}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 6
|
||||||
|
m_TerrainData: {fileID: 15600000, guid: 353d79ea0bc081b4c8f234204cbdcf46, 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: 594ea882c5a793440b60ff72d896021e, 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 &1603549252
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1603549249}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: -2.46, y: 0, z: -4.86}
|
||||||
|
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 &1930940347
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1930940348}
|
||||||
|
- component: {fileID: 1930940349}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: StartNode
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1930940348
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1930940347}
|
||||||
|
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: 445360722}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1930940349
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1930940347}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 6e0f6939c01292c4bb2adc26e7d6f24f, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::FishingLineNode
|
||||||
|
nodeId: Start
|
||||||
|
nodeType: 0
|
||||||
|
distanceFromPrevious: 0
|
||||||
|
virtualNodeCount: 3
|
||||||
|
gravityScale: 1
|
||||||
|
damping: 0.04
|
||||||
|
alignToLine: 1
|
||||||
|
localForwardAxis: {x: 0, y: 0, z: 1}
|
||||||
|
upAxis: {x: 0, y: 1, z: 0}
|
||||||
|
debugColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
--- !u!1660057539 &9223372036854775807
|
--- !u!1660057539 &9223372036854775807
|
||||||
SceneRoots:
|
SceneRoots:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -785,3 +1329,4 @@ SceneRoots:
|
|||||||
- {fileID: 832575519}
|
- {fileID: 832575519}
|
||||||
- {fileID: 1538371803}
|
- {fileID: 1538371803}
|
||||||
- {fileID: 445360722}
|
- {fileID: 445360722}
|
||||||
|
- {fileID: 1603549252}
|
||||||
|
|||||||
32
Assets/Scripts/FishingFloatNodeBehaviour.cs
Normal file
32
Assets/Scripts/FishingFloatNodeBehaviour.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class FishingFloatNodeBehaviour : FishingLineNodeBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Transform waterSurface;
|
||||||
|
[SerializeField] private float fallbackWaterHeight = 0f;
|
||||||
|
[SerializeField] private float surfaceOffset = 0f;
|
||||||
|
[SerializeField] [Min(0f)] private float buoyancy = 16f;
|
||||||
|
[SerializeField] [Range(0f, 1f)] private float waterDrag = 0.22f;
|
||||||
|
[SerializeField] [Min(0.01f)] private float fullBuoyancyDepth = 0.35f;
|
||||||
|
|
||||||
|
public override void Evaluate(ref FishingLineNodeInfluence influence, in FishingLineNodeContext context)
|
||||||
|
{
|
||||||
|
if (!BehaviourEnabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float surfaceY = waterSurface != null ? waterSurface.position.y : fallbackWaterHeight;
|
||||||
|
surfaceY += surfaceOffset;
|
||||||
|
|
||||||
|
float depth = surfaceY - context.Position.y;
|
||||||
|
if (depth <= 0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float normalizedDepth = Mathf.Clamp01(depth / fullBuoyancyDepth);
|
||||||
|
influence.AdditionalAcceleration += Vector3.up * (buoyancy * normalizedDepth);
|
||||||
|
influence.ExtraDamping = Mathf.Max(influence.ExtraDamping, waterDrag);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/FishingFloatNodeBehaviour.cs.meta
Normal file
2
Assets/Scripts/FishingFloatNodeBehaviour.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d619081562aa3d546b20322841df5e50
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5194be581ec15764eab72311e62182eb
|
|
||||||
152
Assets/Scripts/FishingGroundProbeNodeBehaviour.cs
Normal file
152
Assets/Scripts/FishingGroundProbeNodeBehaviour.cs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public enum FishingGroundProbeShape
|
||||||
|
{
|
||||||
|
Sphere,
|
||||||
|
Capsule,
|
||||||
|
Box
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FishingGroundProbeNodeBehaviour : FishingLineNodeBehaviour
|
||||||
|
{
|
||||||
|
[Header("Probe")]
|
||||||
|
[SerializeField] private FishingGroundProbeShape probeShape = FishingGroundProbeShape.Sphere;
|
||||||
|
[SerializeField] private LayerMask collisionLayers = ~0;
|
||||||
|
[SerializeField] [Min(0.01f)] private float probeRadius = 0.08f;
|
||||||
|
[SerializeField] [Min(0.01f)] private float capsuleHeight = 0.3f;
|
||||||
|
[SerializeField] private Vector3 boxHalfExtents = new Vector3(0.08f, 0.08f, 0.08f);
|
||||||
|
[SerializeField] [Min(0.05f)] private float castDistance = 0.5f;
|
||||||
|
[SerializeField] [Min(0f)] private float collisionPadding = 0.01f;
|
||||||
|
[SerializeField] [Range(0f, 1f)] private float contactDamping = 0.2f;
|
||||||
|
[SerializeField] [Range(0f, 1f)] private float contactFriction = 0.85f;
|
||||||
|
[SerializeField] [Min(0f)] private float contactSnapDistance = 0.03f;
|
||||||
|
|
||||||
|
[Header("Debug")]
|
||||||
|
[SerializeField] private bool drawDebug = true;
|
||||||
|
[SerializeField] private Color castColor = new Color(1f, 0.85f, 0.2f, 0.9f);
|
||||||
|
[SerializeField] private Color hitColor = new Color(0.25f, 1f, 0.4f, 1f);
|
||||||
|
|
||||||
|
private bool hadHitLastFrame;
|
||||||
|
private RaycastHit lastHit;
|
||||||
|
|
||||||
|
public override void Evaluate(ref FishingLineNodeInfluence influence, in FishingLineNodeContext context)
|
||||||
|
{
|
||||||
|
if (!BehaviourEnabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryProbe(context.Position, out RaycastHit hit, out float supportOffset))
|
||||||
|
{
|
||||||
|
hadHitLastFrame = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hadHitLastFrame = true;
|
||||||
|
lastHit = hit;
|
||||||
|
|
||||||
|
float minimumY = hit.point.y + supportOffset + collisionPadding;
|
||||||
|
bool needsSnap = context.Position.y < minimumY || minimumY - context.Position.y <= contactSnapDistance;
|
||||||
|
if (needsSnap)
|
||||||
|
{
|
||||||
|
influence.PositionOffset += Vector3.up * (minimumY - context.Position.y);
|
||||||
|
Vector3 groundVelocity = Vector3.ProjectOnPlane(context.Velocity, hit.normal) * (1f - contactFriction);
|
||||||
|
influence.VelocityOffset += groundVelocity - context.Velocity;
|
||||||
|
influence.ExtraDamping = Mathf.Max(influence.ExtraDamping, contactDamping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryProbe(Vector3 position, out RaycastHit hit, out float supportOffset)
|
||||||
|
{
|
||||||
|
Vector3 direction = Vector3.down;
|
||||||
|
float distance = castDistance * 2f;
|
||||||
|
|
||||||
|
switch (probeShape)
|
||||||
|
{
|
||||||
|
case FishingGroundProbeShape.Capsule:
|
||||||
|
{
|
||||||
|
float halfSegment = Mathf.Max(0f, capsuleHeight * 0.5f - probeRadius);
|
||||||
|
Vector3 center = position + Vector3.up * castDistance;
|
||||||
|
Vector3 top = center + Vector3.up * halfSegment;
|
||||||
|
Vector3 bottom = center - Vector3.up * halfSegment;
|
||||||
|
supportOffset = probeRadius;
|
||||||
|
return Physics.CapsuleCast(top, bottom, probeRadius, direction, out hit, distance, collisionLayers, QueryTriggerInteraction.Ignore);
|
||||||
|
}
|
||||||
|
case FishingGroundProbeShape.Box:
|
||||||
|
{
|
||||||
|
Vector3 center = position + Vector3.up * castDistance;
|
||||||
|
supportOffset = boxHalfExtents.y;
|
||||||
|
return Physics.BoxCast(center, boxHalfExtents, direction, out hit, transform.rotation, distance, collisionLayers, QueryTriggerInteraction.Ignore);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Vector3 origin = position + Vector3.up * castDistance;
|
||||||
|
supportOffset = probeRadius;
|
||||||
|
return Physics.SphereCast(origin, probeRadius, direction, out hit, distance, collisionLayers, QueryTriggerInteraction.Ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDrawGizmos()
|
||||||
|
{
|
||||||
|
if (!drawDebug)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 start = transform.position + Vector3.up * castDistance;
|
||||||
|
Vector3 end = start + Vector3.down * (castDistance * 2f);
|
||||||
|
|
||||||
|
Gizmos.color = castColor;
|
||||||
|
switch (probeShape)
|
||||||
|
{
|
||||||
|
case FishingGroundProbeShape.Capsule:
|
||||||
|
DrawCapsuleCastGizmo(start, end);
|
||||||
|
break;
|
||||||
|
case FishingGroundProbeShape.Box:
|
||||||
|
DrawBoxCastGizmo(start, end);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Gizmos.DrawWireSphere(start, probeRadius);
|
||||||
|
Gizmos.DrawWireSphere(end, probeRadius);
|
||||||
|
Gizmos.DrawLine(start, end);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hadHitLastFrame)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gizmos.color = hitColor;
|
||||||
|
Gizmos.DrawSphere(lastHit.point, 0.03f);
|
||||||
|
Gizmos.DrawLine(lastHit.point, lastHit.point + lastHit.normal * 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawCapsuleCastGizmo(Vector3 start, Vector3 end)
|
||||||
|
{
|
||||||
|
float halfSegment = Mathf.Max(0f, capsuleHeight * 0.5f - probeRadius);
|
||||||
|
Vector3 startTop = start + Vector3.up * halfSegment;
|
||||||
|
Vector3 startBottom = start - Vector3.up * halfSegment;
|
||||||
|
Vector3 endTop = end + Vector3.up * halfSegment;
|
||||||
|
Vector3 endBottom = end - Vector3.up * halfSegment;
|
||||||
|
|
||||||
|
Gizmos.DrawWireSphere(startTop, probeRadius);
|
||||||
|
Gizmos.DrawWireSphere(startBottom, probeRadius);
|
||||||
|
Gizmos.DrawWireSphere(endTop, probeRadius);
|
||||||
|
Gizmos.DrawWireSphere(endBottom, probeRadius);
|
||||||
|
Gizmos.DrawLine(startTop, endTop);
|
||||||
|
Gizmos.DrawLine(startBottom, endBottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawBoxCastGizmo(Vector3 start, Vector3 end)
|
||||||
|
{
|
||||||
|
Matrix4x4 previous = Gizmos.matrix;
|
||||||
|
Gizmos.matrix = Matrix4x4.TRS(start, transform.rotation, Vector3.one);
|
||||||
|
Gizmos.DrawWireCube(Vector3.zero, boxHalfExtents * 2f);
|
||||||
|
Gizmos.matrix = Matrix4x4.TRS(end, transform.rotation, Vector3.one);
|
||||||
|
Gizmos.DrawWireCube(Vector3.zero, boxHalfExtents * 2f);
|
||||||
|
Gizmos.matrix = previous;
|
||||||
|
Gizmos.DrawLine(start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/FishingGroundProbeNodeBehaviour.cs.meta
Normal file
2
Assets/Scripts/FishingGroundProbeNodeBehaviour.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 953e78672cb7e2a4ebacb573fa9a7627
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -11,56 +10,79 @@ public enum FishingLineNodeType
|
|||||||
Normal
|
Normal
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
public class FishingLineNode : MonoBehaviour
|
||||||
public class FishingLineLogicalNodeDefinition
|
|
||||||
{
|
{
|
||||||
[SerializeField] private string id = "Node";
|
[SerializeField] private string nodeId = "Node";
|
||||||
[SerializeField] private FishingLineNodeType nodeType = FishingLineNodeType.Normal;
|
[SerializeField] private FishingLineNodeType nodeType = FishingLineNodeType.Normal;
|
||||||
[SerializeField] [Min(0f)] private float distanceFromPrevious = 1f;
|
[SerializeField] [Min(0f)] private float distanceFromPrevious = 0f;
|
||||||
[SerializeField] [Min(0)] private int virtualNodeCount = 3;
|
[SerializeField] [Min(0)] private int virtualNodeCount = 3;
|
||||||
[SerializeField] [Min(0f)] private float gravityScale = 1f;
|
[SerializeField] [Min(0f)] private float gravityScale = 1f;
|
||||||
[SerializeField] [Range(0f, 1f)] private float damping = 0.04f;
|
[SerializeField] [Range(0f, 1f)] private float damping = 0.04f;
|
||||||
[SerializeField] private Color debugColor = Color.white;
|
|
||||||
|
|
||||||
public string Id => id;
|
|
||||||
public FishingLineNodeType NodeType => nodeType;
|
|
||||||
public float DistanceFromPrevious => distanceFromPrevious;
|
|
||||||
public int VirtualNodeCount => virtualNodeCount;
|
|
||||||
public float GravityScale => gravityScale;
|
|
||||||
public float Damping => damping;
|
|
||||||
public Color DebugColor => debugColor;
|
|
||||||
|
|
||||||
public void ConfigurePrototype(
|
|
||||||
string newId,
|
|
||||||
FishingLineNodeType newNodeType,
|
|
||||||
float newDistanceFromPrevious,
|
|
||||||
int newVirtualNodeCount,
|
|
||||||
float newGravityScale,
|
|
||||||
float newDamping,
|
|
||||||
Color newDebugColor)
|
|
||||||
{
|
|
||||||
id = newId;
|
|
||||||
nodeType = newNodeType;
|
|
||||||
distanceFromPrevious = Mathf.Max(0f, newDistanceFromPrevious);
|
|
||||||
virtualNodeCount = Mathf.Max(0, newVirtualNodeCount);
|
|
||||||
gravityScale = Mathf.Max(0f, newGravityScale);
|
|
||||||
damping = Mathf.Clamp01(newDamping);
|
|
||||||
debugColor = newDebugColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class FishingLineAttachmentBinding
|
|
||||||
{
|
|
||||||
[SerializeField] [Min(0)] private int logicalNodeIndex;
|
|
||||||
[SerializeField] private List<Transform> targets = new List<Transform>();
|
|
||||||
[SerializeField] private bool alignToLine = true;
|
[SerializeField] private bool alignToLine = true;
|
||||||
[SerializeField] private Vector3 localForwardAxis = Vector3.forward;
|
[SerializeField] private Vector3 localForwardAxis = Vector3.forward;
|
||||||
[SerializeField] private Vector3 upAxis = Vector3.up;
|
[SerializeField] private Vector3 upAxis = Vector3.up;
|
||||||
|
[SerializeField] private Color debugColor = Color.white;
|
||||||
|
|
||||||
public int LogicalNodeIndex => logicalNodeIndex;
|
private readonly List<FishingLineNodeBehaviour> behaviours = new List<FishingLineNodeBehaviour>();
|
||||||
public IReadOnlyList<Transform> Targets => targets;
|
|
||||||
|
public string NodeId => nodeId;
|
||||||
|
public FishingLineNodeType NodeType => nodeType;
|
||||||
|
public int VirtualNodeCount => virtualNodeCount;
|
||||||
|
public float GravityScale => gravityScale;
|
||||||
|
public float Damping => damping;
|
||||||
public bool AlignToLine => alignToLine;
|
public bool AlignToLine => alignToLine;
|
||||||
public Vector3 LocalForwardAxis => localForwardAxis;
|
public Vector3 LocalForwardAxis => localForwardAxis;
|
||||||
public Vector3 UpAxis => upAxis;
|
public Vector3 UpAxis => upAxis;
|
||||||
|
public Color DebugColor => debugColor;
|
||||||
|
public IReadOnlyList<FishingLineNodeBehaviour> Behaviours => behaviours;
|
||||||
|
|
||||||
|
private void Reset()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(nodeId))
|
||||||
|
{
|
||||||
|
nodeId = gameObject.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshBehaviours();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(nodeId))
|
||||||
|
{
|
||||||
|
nodeId = gameObject.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ContextMenu("Refresh Node Behaviours")]
|
||||||
|
public void RefreshBehaviours()
|
||||||
|
{
|
||||||
|
behaviours.Clear();
|
||||||
|
FishingLineNodeBehaviour[] found = GetComponents<FishingLineNodeBehaviour>();
|
||||||
|
for (int index = 0; index < found.Length; index++)
|
||||||
|
{
|
||||||
|
FishingLineNodeBehaviour behaviour = found[index];
|
||||||
|
if (behaviour == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
behaviours.Add(behaviour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ResolveDistanceFromPrevious(FishingLineNode previousNode)
|
||||||
|
{
|
||||||
|
if (distanceFromPrevious > 0f)
|
||||||
|
{
|
||||||
|
return distanceFromPrevious;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousNode == null)
|
||||||
|
{
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Vector3.Distance(previousNode.transform.position, transform.position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
Assets/Scripts/FishingLineNodeBehaviour.cs
Normal file
30
Assets/Scripts/FishingLineNodeBehaviour.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public struct FishingLineNodeContext
|
||||||
|
{
|
||||||
|
public FishingLineSolver Solver;
|
||||||
|
public FishingLineNode Node;
|
||||||
|
public Vector3 Position;
|
||||||
|
public Vector3 PreviousPosition;
|
||||||
|
public Vector3 Velocity;
|
||||||
|
public Vector3 Tangent;
|
||||||
|
public float DeltaTime;
|
||||||
|
public float Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FishingLineNodeInfluence
|
||||||
|
{
|
||||||
|
public Vector3 PositionOffset;
|
||||||
|
public Vector3 VelocityOffset;
|
||||||
|
public Vector3 AdditionalAcceleration;
|
||||||
|
public float ExtraDamping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class FishingLineNodeBehaviour : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private bool behaviourEnabled = true;
|
||||||
|
|
||||||
|
public bool BehaviourEnabled => behaviourEnabled;
|
||||||
|
|
||||||
|
public abstract void Evaluate(ref FishingLineNodeInfluence influence, in FishingLineNodeContext context);
|
||||||
|
}
|
||||||
2
Assets/Scripts/FishingLineNodeBehaviour.cs.meta
Normal file
2
Assets/Scripts/FishingLineNodeBehaviour.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 17d8d651410bae146843019f74bc987b
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
[RequireComponent(typeof(LineRenderer))]
|
[RequireComponent(typeof(LineRenderer))]
|
||||||
@@ -6,74 +5,26 @@ public class FishingLineRendererBinder : MonoBehaviour
|
|||||||
{
|
{
|
||||||
[SerializeField] private FishingLineSolver solver;
|
[SerializeField] private FishingLineSolver solver;
|
||||||
[SerializeField] private LineRenderer lineRenderer;
|
[SerializeField] private LineRenderer lineRenderer;
|
||||||
[SerializeField] private List<FishingLineAttachmentBinding> attachmentBindings = new List<FishingLineAttachmentBinding>();
|
|
||||||
|
|
||||||
private void Reset()
|
private void Reset()
|
||||||
{
|
{
|
||||||
lineRenderer = GetComponent<LineRenderer>();
|
|
||||||
solver = GetComponent<FishingLineSolver>();
|
solver = GetComponent<FishingLineSolver>();
|
||||||
|
lineRenderer = GetComponent<LineRenderer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LateUpdate()
|
private void LateUpdate()
|
||||||
{
|
{
|
||||||
if (solver == null)
|
if (solver == null || lineRenderer == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateLineRenderer();
|
var positions = solver.LinePositions;
|
||||||
UpdateAttachments();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateLineRenderer()
|
|
||||||
{
|
|
||||||
if (lineRenderer == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IReadOnlyList<Vector3> positions = solver.LinePositions;
|
|
||||||
lineRenderer.useWorldSpace = true;
|
lineRenderer.useWorldSpace = true;
|
||||||
lineRenderer.positionCount = positions.Count;
|
lineRenderer.positionCount = positions.Count;
|
||||||
|
|
||||||
for (int index = 0; index < positions.Count; index++)
|
for (int index = 0; index < positions.Count; index++)
|
||||||
{
|
{
|
||||||
lineRenderer.SetPosition(index, positions[index]);
|
lineRenderer.SetPosition(index, positions[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAttachments()
|
|
||||||
{
|
|
||||||
for (int bindingIndex = 0; bindingIndex < attachmentBindings.Count; bindingIndex++)
|
|
||||||
{
|
|
||||||
FishingLineAttachmentBinding binding = attachmentBindings[bindingIndex];
|
|
||||||
if (!solver.TryGetLogicalNodePosition(binding.LogicalNodeIndex, out Vector3 position))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion rotation = Quaternion.identity;
|
|
||||||
if (binding.AlignToLine && solver.TryGetLogicalNodeTangent(binding.LogicalNodeIndex, out Vector3 tangent))
|
|
||||||
{
|
|
||||||
rotation = Quaternion.LookRotation(tangent, binding.UpAxis.sqrMagnitude > 0f ? binding.UpAxis.normalized : Vector3.up);
|
|
||||||
}
|
|
||||||
|
|
||||||
IReadOnlyList<Transform> targets = binding.Targets;
|
|
||||||
for (int targetIndex = 0; targetIndex < targets.Count; targetIndex++)
|
|
||||||
{
|
|
||||||
Transform target = targets[targetIndex];
|
|
||||||
if (target == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
target.position = position;
|
|
||||||
if (binding.AlignToLine)
|
|
||||||
{
|
|
||||||
Quaternion axisOffset = Quaternion.FromToRotation(binding.LocalForwardAxis.normalized, Vector3.forward);
|
|
||||||
target.rotation = rotation * Quaternion.Inverse(axisOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -6,139 +5,106 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
{
|
{
|
||||||
private const float MinSegmentLength = 0.01f;
|
private const float MinSegmentLength = 0.01f;
|
||||||
|
|
||||||
[Header("Rig")]
|
[Header("Scene Nodes")]
|
||||||
[SerializeField] private FishingRigDefinition rigDefinition;
|
[SerializeField] private Transform lineRoot;
|
||||||
[SerializeField] private List<FishingLineLogicalNodeDefinition> inlineLogicalNodes = new List<FishingLineLogicalNodeDefinition>();
|
|
||||||
[SerializeField] private Transform startAnchor;
|
[SerializeField] private Transform startAnchor;
|
||||||
[SerializeField] private Vector3 initialDirection = Vector3.down;
|
|
||||||
|
|
||||||
[Header("Simulation")]
|
[Header("Simulation")]
|
||||||
[SerializeField] [Min(1)] private int solverIterations = 8;
|
[SerializeField] [Min(1)] private int solverIterations = 8;
|
||||||
[SerializeField] [Min(0f)] private float gravity = 9.81f;
|
[SerializeField] [Min(0f)] private float gravity = 9.81f;
|
||||||
[SerializeField] [Range(0f, 1f)] private float globalDamping = 0.01f;
|
[SerializeField] [Range(0f, 1f)] private float globalDamping = 0.01f;
|
||||||
[SerializeField] [Range(0f, 1f)] private float tensionSmoothing = 0.18f;
|
[SerializeField] private Vector3 initialDirection = Vector3.down;
|
||||||
[SerializeField] private bool simulateInFixedUpdate = false;
|
[SerializeField] [Min(0.05f)] private float maxSolverSegmentLength = 0.25f;
|
||||||
|
|
||||||
[Header("Line Length")]
|
[Header("Start Segment")]
|
||||||
[SerializeField] [Min(0.01f)] private float currentLineLength = 3.4f;
|
[SerializeField] private bool useSceneDistanceForStartSegment = true;
|
||||||
[SerializeField] [Min(0.01f)] private float minLineLength = 1.2f;
|
[SerializeField] [Min(0.1f)] private float startSegmentLength = 3f;
|
||||||
[SerializeField] [Min(0.01f)] private float maxLineLength = 8.5f;
|
[SerializeField] [Min(0.1f)] private float minStartSegmentLength = 0.5f;
|
||||||
|
[SerializeField] [Min(0.1f)] private float maxStartSegmentLength = 15f;
|
||||||
|
|
||||||
[Header("Debug")]
|
[Header("Debug")]
|
||||||
[SerializeField] private bool drawDebug = true;
|
[SerializeField] private bool drawDebug = true;
|
||||||
[SerializeField] [Min(0.005f)] private float debugNodeRadius = 0.03f;
|
[SerializeField] [Min(0.005f)] private float debugPointRadius = 0.03f;
|
||||||
[SerializeField] private Color virtualNodeColor = new Color(0.4f, 0.75f, 1f, 1f);
|
[SerializeField] private Color virtualPointColor = new Color(0.45f, 0.75f, 1f, 1f);
|
||||||
[SerializeField] private Color segmentColor = new Color(0.85f, 0.9f, 1f, 1f);
|
[SerializeField] private Color segmentColor = new Color(0.9f, 0.95f, 1f, 1f);
|
||||||
|
|
||||||
|
private readonly List<FishingLineNode> logicalNodes = new List<FishingLineNode>();
|
||||||
private readonly List<RuntimePoint> points = new List<RuntimePoint>();
|
private readonly List<RuntimePoint> points = new List<RuntimePoint>();
|
||||||
private readonly List<RuntimeLogicalNode> logicalNodes = new List<RuntimeLogicalNode>();
|
|
||||||
private readonly List<float> baseSegmentLengths = new List<float>();
|
private readonly List<float> baseSegmentLengths = new List<float>();
|
||||||
private readonly List<Vector3> linePositions = new List<Vector3>();
|
private readonly List<Vector3> linePositions = new List<Vector3>();
|
||||||
private readonly List<FishingLineLogicalNodeDefinition> fallbackLogicalNodes = new List<FishingLineLogicalNodeDefinition>();
|
private readonly List<int> logicalPointIndices = new List<int>();
|
||||||
|
|
||||||
private bool runtimeBuilt;
|
private bool runtimeBuilt;
|
||||||
private float currentTensionNormalized;
|
private float fixedRigLength;
|
||||||
private float previousLineLength;
|
private int startSegmentSubsegments;
|
||||||
private float baseTotalLength;
|
|
||||||
|
|
||||||
public IReadOnlyList<Vector3> LinePositions => linePositions;
|
public IReadOnlyList<Vector3> LinePositions => linePositions;
|
||||||
public int PointCount => points.Count;
|
public IReadOnlyList<FishingLineNode> LogicalNodes => logicalNodes;
|
||||||
public int LogicalNodeCount => logicalNodes.Count;
|
public float FixedRigLength => fixedRigLength;
|
||||||
public float CurrentTensionNormalized => currentTensionNormalized;
|
public float StartSegmentLength => startSegmentLength;
|
||||||
public float CurrentLineLength => currentLineLength;
|
public float TotalLineLength => fixedRigLength + startSegmentLength;
|
||||||
public float BaseTotalLength => baseTotalLength;
|
|
||||||
|
|
||||||
public IReadOnlyList<FishingLineLogicalNodeDefinition> LogicalNodeDefinitions => GetActiveDefinitions();
|
private void Reset()
|
||||||
|
{
|
||||||
|
lineRoot = transform;
|
||||||
|
startAnchor = transform;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
Rebuild();
|
Rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Reset()
|
|
||||||
{
|
|
||||||
EnsureInlinePrototypeIfNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
solverIterations = Mathf.Max(1, solverIterations);
|
solverIterations = Mathf.Max(1, solverIterations);
|
||||||
minLineLength = Mathf.Max(MinSegmentLength, minLineLength);
|
minStartSegmentLength = Mathf.Max(0.1f, minStartSegmentLength);
|
||||||
maxLineLength = Mathf.Max(minLineLength, maxLineLength);
|
maxStartSegmentLength = Mathf.Max(minStartSegmentLength, maxStartSegmentLength);
|
||||||
currentLineLength = Mathf.Clamp(currentLineLength, minLineLength, maxLineLength);
|
startSegmentLength = Mathf.Clamp(startSegmentLength, minStartSegmentLength, maxStartSegmentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (!simulateInFixedUpdate)
|
Simulate(Time.deltaTime);
|
||||||
{
|
|
||||||
Simulate(Time.deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FixedUpdate()
|
|
||||||
{
|
|
||||||
if (simulateInFixedUpdate)
|
|
||||||
{
|
|
||||||
Simulate(Time.fixedDeltaTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ContextMenu("Rebuild Solver")]
|
[ContextMenu("Rebuild Solver")]
|
||||||
public void Rebuild()
|
public void Rebuild()
|
||||||
{
|
{
|
||||||
EnsureInlinePrototypeIfNeeded();
|
CollectLogicalNodes();
|
||||||
BuildRuntime();
|
BuildRuntime();
|
||||||
SnapToAnchors();
|
SnapAnchors();
|
||||||
RefreshLinePositions();
|
RefreshLinePositions();
|
||||||
previousLineLength = currentLineLength;
|
SyncLogicalNodeTransforms();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetLineLength(float newLength)
|
public void SetStartSegmentLength(float newLength)
|
||||||
{
|
{
|
||||||
float clampedLength = Mathf.Clamp(newLength, minLineLength, maxLineLength);
|
useSceneDistanceForStartSegment = false;
|
||||||
bool expanded = clampedLength > currentLineLength + Mathf.Epsilon;
|
startSegmentLength = Mathf.Clamp(newLength, minStartSegmentLength, maxStartSegmentLength);
|
||||||
currentLineLength = clampedLength;
|
}
|
||||||
|
|
||||||
if (expanded)
|
public void AdjustStartSegmentLength(float delta)
|
||||||
|
{
|
||||||
|
SetStartSegmentLength(startSegmentLength + delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetLogicalNodePosition(string nodeId, out Vector3 position)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < logicalNodes.Count; index++)
|
||||||
{
|
{
|
||||||
ExpandLineToCurrentLength();
|
FishingLineNode node = logicalNodes[index];
|
||||||
RefreshLinePositions();
|
if (node == null || !string.Equals(node.NodeId, nodeId, System.StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
position = points[GetLogicalPointIndex(index)].Position;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
previousLineLength = currentLineLength;
|
position = default;
|
||||||
}
|
return false;
|
||||||
|
|
||||||
public void AdjustLineLength(float delta)
|
|
||||||
{
|
|
||||||
SetLineLength(currentLineLength + delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetLogicalNodePosition(int logicalNodeIndex, out Vector3 position)
|
|
||||||
{
|
|
||||||
if (logicalNodeIndex < 0 || logicalNodeIndex >= logicalNodes.Count)
|
|
||||||
{
|
|
||||||
position = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
position = logicalNodes[logicalNodeIndex].Point.Position;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetLogicalNodeTangent(int logicalNodeIndex, out Vector3 tangent)
|
|
||||||
{
|
|
||||||
if (logicalNodeIndex < 0 || logicalNodeIndex >= logicalNodes.Count)
|
|
||||||
{
|
|
||||||
tangent = Vector3.forward;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pointIndex = logicalNodes[logicalNodeIndex].PointIndex;
|
|
||||||
Vector3 previous = pointIndex > 0 ? points[pointIndex - 1].Position : points[pointIndex].Position;
|
|
||||||
Vector3 next = pointIndex < points.Count - 1 ? points[pointIndex + 1].Position : points[pointIndex].Position;
|
|
||||||
tangent = (next - previous).normalized;
|
|
||||||
return tangent.sqrMagnitude > 0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Simulate(float deltaTime)
|
private void Simulate(float deltaTime)
|
||||||
@@ -148,247 +114,166 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
Rebuild();
|
Rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (points.Count == 0 || deltaTime <= 0f)
|
if (!runtimeBuilt || deltaTime <= 0f)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncAnchors();
|
EnsureRuntimeTopologyMatchesLength();
|
||||||
if (currentLineLength > previousLineLength + Mathf.Epsilon)
|
SyncStartAnchor();
|
||||||
{
|
|
||||||
ExpandLineToCurrentLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
Integrate(deltaTime);
|
Integrate(deltaTime);
|
||||||
|
ApplyNodeBehaviours(deltaTime);
|
||||||
SolveConstraints();
|
SolveConstraints();
|
||||||
SyncAnchors();
|
ApplyNodeBehaviours(0f);
|
||||||
|
SolveConstraints();
|
||||||
|
SyncStartAnchor();
|
||||||
RefreshLinePositions();
|
RefreshLinePositions();
|
||||||
UpdateTension();
|
SyncLogicalNodeTransforms();
|
||||||
previousLineLength = currentLineLength;
|
}
|
||||||
|
|
||||||
|
private void CollectLogicalNodes()
|
||||||
|
{
|
||||||
|
logicalNodes.Clear();
|
||||||
|
|
||||||
|
Transform root = lineRoot != null ? lineRoot : transform;
|
||||||
|
for (int childIndex = 0; childIndex < root.childCount; childIndex++)
|
||||||
|
{
|
||||||
|
Transform child = root.GetChild(childIndex);
|
||||||
|
if (child == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FishingLineNode node = child.GetComponent<FishingLineNode>();
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.RefreshBehaviours();
|
||||||
|
logicalNodes.Add(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildRuntime()
|
private void BuildRuntime()
|
||||||
{
|
{
|
||||||
|
List<Vector3> previousPolyline = linePositions.Count > 1 ? new List<Vector3>(linePositions) : null;
|
||||||
|
|
||||||
points.Clear();
|
points.Clear();
|
||||||
logicalNodes.Clear();
|
|
||||||
baseSegmentLengths.Clear();
|
baseSegmentLengths.Clear();
|
||||||
linePositions.Clear();
|
linePositions.Clear();
|
||||||
baseTotalLength = 0f;
|
logicalPointIndices.Clear();
|
||||||
|
fixedRigLength = 0f;
|
||||||
|
startSegmentSubsegments = 0;
|
||||||
|
runtimeBuilt = false;
|
||||||
|
|
||||||
EnsureInlinePrototypeIfNeeded();
|
if (logicalNodes.Count < 1)
|
||||||
IReadOnlyList<FishingLineLogicalNodeDefinition> definitions = GetResolvedDefinitions();
|
|
||||||
if (definitions.Count == 0)
|
|
||||||
{
|
{
|
||||||
runtimeBuilt = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (definitions.Count < 2)
|
Vector3 anchor = GetStartAnchorPosition();
|
||||||
|
if (useSceneDistanceForStartSegment)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("FishingLineSolver needs at least 2 logical nodes to build a valid line.", this);
|
startSegmentLength = Mathf.Clamp(
|
||||||
runtimeBuilt = false;
|
Mathf.Max(MinSegmentLength, Vector3.Distance(anchor, logicalNodes[0].transform.position)),
|
||||||
return;
|
minStartSegmentLength,
|
||||||
|
maxStartSegmentLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startSegmentLength = Mathf.Clamp(startSegmentLength, minStartSegmentLength, maxStartSegmentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (definitions[0].NodeType != FishingLineNodeType.Start)
|
RuntimePoint anchorPoint = new RuntimePoint(anchor, true, -1, logicalNodes[0].GravityScale, logicalNodes[0].Damping);
|
||||||
|
points.Add(anchorPoint);
|
||||||
|
|
||||||
|
int currentPointIndex = 1;
|
||||||
|
FishingLineNode firstNode = logicalNodes[0];
|
||||||
|
startSegmentSubsegments = Mathf.Max(1, Mathf.Max(firstNode.VirtualNodeCount + 1, Mathf.CeilToInt(startSegmentLength / maxSolverSegmentLength)));
|
||||||
|
float startSubsegmentLength = startSegmentLength / startSegmentSubsegments;
|
||||||
|
for (int virtualIndex = 1; virtualIndex < startSegmentSubsegments; virtualIndex++)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("FishingLineSolver expects the first logical node to be Start. The first node is still treated as the anchor.", this);
|
RuntimePoint virtualPoint = new RuntimePoint(
|
||||||
|
anchor,
|
||||||
|
false,
|
||||||
|
-1,
|
||||||
|
Mathf.Lerp(0f, firstNode.GravityScale, virtualIndex / (float)startSegmentSubsegments),
|
||||||
|
Mathf.Lerp(0f, firstNode.Damping, virtualIndex / (float)startSegmentSubsegments));
|
||||||
|
|
||||||
|
points.Add(virtualPoint);
|
||||||
|
baseSegmentLengths.Add(startSubsegmentLength);
|
||||||
|
currentPointIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 cursor = startAnchor != null ? startAnchor.position : transform.position;
|
RuntimePoint firstLogicalPoint = new RuntimePoint(anchor, false, 0, firstNode.GravityScale, firstNode.Damping);
|
||||||
Vector3 direction = initialDirection.sqrMagnitude > 0f ? initialDirection.normalized : Vector3.down;
|
points.Add(firstLogicalPoint);
|
||||||
|
baseSegmentLengths.Add(startSubsegmentLength);
|
||||||
|
logicalPointIndices.Add(currentPointIndex);
|
||||||
|
currentPointIndex++;
|
||||||
|
|
||||||
for (int logicalIndex = 0; logicalIndex < definitions.Count; logicalIndex++)
|
for (int logicalIndex = 1; logicalIndex < logicalNodes.Count; logicalIndex++)
|
||||||
{
|
{
|
||||||
FishingLineLogicalNodeDefinition definition = definitions[logicalIndex];
|
FishingLineNode node = logicalNodes[logicalIndex];
|
||||||
bool anchored = logicalIndex == 0;
|
FishingLineNode previousNode = logicalNodes[logicalIndex - 1];
|
||||||
|
float baseDistance = Mathf.Max(MinSegmentLength, node.ResolveDistanceFromPrevious(previousNode));
|
||||||
|
fixedRigLength += baseDistance;
|
||||||
|
|
||||||
if (logicalIndex > 0)
|
int requiredSubsegments = Mathf.Max(1, node.VirtualNodeCount + 1);
|
||||||
|
float baseSubsegmentLength = baseDistance / requiredSubsegments;
|
||||||
|
for (int virtualIndex = 1; virtualIndex < requiredSubsegments; virtualIndex++)
|
||||||
{
|
{
|
||||||
FishingLineLogicalNodeDefinition previousDefinition = definitions[logicalIndex - 1];
|
RuntimePoint virtualPoint = new RuntimePoint(
|
||||||
float logicalDistance = Mathf.Max(MinSegmentLength, definition.DistanceFromPrevious);
|
anchor,
|
||||||
int virtualNodeCount = Mathf.Max(0, definition.VirtualNodeCount);
|
false,
|
||||||
float subSegmentLength = logicalDistance / (virtualNodeCount + 1);
|
-1,
|
||||||
|
Mathf.Lerp(previousNode.GravityScale, node.GravityScale, virtualIndex / (float)requiredSubsegments),
|
||||||
|
Mathf.Lerp(previousNode.Damping, node.Damping, virtualIndex / (float)requiredSubsegments));
|
||||||
|
|
||||||
for (int virtualIndex = 0; virtualIndex < virtualNodeCount; virtualIndex++)
|
points.Add(virtualPoint);
|
||||||
{
|
baseSegmentLengths.Add(baseSubsegmentLength);
|
||||||
cursor += direction * subSegmentLength;
|
currentPointIndex++;
|
||||||
RuntimePoint virtualPoint = new RuntimePoint(
|
|
||||||
cursor,
|
|
||||||
false,
|
|
||||||
-1,
|
|
||||||
Mathf.Lerp(previousDefinition.GravityScale, definition.GravityScale, (virtualIndex + 1f) / (virtualNodeCount + 1f)),
|
|
||||||
Mathf.Lerp(previousDefinition.Damping, definition.Damping, (virtualIndex + 1f) / (virtualNodeCount + 1f)));
|
|
||||||
|
|
||||||
points.Add(virtualPoint);
|
|
||||||
baseSegmentLengths.Add(subSegmentLength);
|
|
||||||
baseTotalLength += subSegmentLength;
|
|
||||||
linePositions.Add(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor += direction * subSegmentLength;
|
|
||||||
baseSegmentLengths.Add(subSegmentLength);
|
|
||||||
baseTotalLength += subSegmentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
RuntimePoint logicalPoint = new RuntimePoint(cursor, anchored, logicalIndex, definition.GravityScale, definition.Damping);
|
|
||||||
if (anchored)
|
|
||||||
{
|
|
||||||
logicalPoint.Anchor = startAnchor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RuntimePoint logicalPoint = new RuntimePoint(anchor, false, logicalIndex, node.GravityScale, node.Damping);
|
||||||
points.Add(logicalPoint);
|
points.Add(logicalPoint);
|
||||||
logicalNodes.Add(new RuntimeLogicalNode(logicalIndex, points.Count - 1, logicalPoint));
|
baseSegmentLengths.Add(baseSubsegmentLength);
|
||||||
linePositions.Add(cursor);
|
logicalPointIndices.Add(currentPointIndex);
|
||||||
|
currentPointIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeLineLengthDefaults();
|
InitializeRuntimePointPositions(previousPolyline);
|
||||||
runtimeBuilt = points.Count > 0;
|
runtimeBuilt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeLineLengthDefaults()
|
private void SnapAnchors()
|
||||||
{
|
{
|
||||||
if (baseTotalLength <= MinSegmentLength)
|
if (points.Count == 0)
|
||||||
{
|
|
||||||
minLineLength = Mathf.Max(MinSegmentLength, minLineLength);
|
|
||||||
maxLineLength = Mathf.Max(minLineLength, maxLineLength);
|
|
||||||
currentLineLength = Mathf.Clamp(Mathf.Max(currentLineLength, minLineLength), minLineLength, maxLineLength);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentLineLength <= MinSegmentLength)
|
|
||||||
{
|
|
||||||
currentLineLength = baseTotalLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minLineLength <= MinSegmentLength)
|
|
||||||
{
|
|
||||||
minLineLength = Mathf.Max(MinSegmentLength, baseTotalLength * 0.35f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxLineLength <= MinSegmentLength || maxLineLength < currentLineLength)
|
|
||||||
{
|
|
||||||
maxLineLength = Mathf.Max(currentLineLength, baseTotalLength * 2.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
minLineLength = Mathf.Min(minLineLength, maxLineLength);
|
|
||||||
currentLineLength = Mathf.Clamp(currentLineLength, minLineLength, maxLineLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnsureInlinePrototypeIfNeeded()
|
|
||||||
{
|
|
||||||
if (rigDefinition != null && IsDefinitionListUsable(rigDefinition.LogicalNodes))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDefinitionListUsable(inlineLogicalNodes))
|
RuntimePoint startPoint = points[0];
|
||||||
|
Vector3 anchorPosition = GetStartAnchorPosition();
|
||||||
|
startPoint.Position = anchorPosition;
|
||||||
|
startPoint.PreviousPosition = anchorPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncStartAnchor()
|
||||||
|
{
|
||||||
|
if (points.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
inlineLogicalNodes.Clear();
|
Vector3 anchorPosition = GetStartAnchorPosition();
|
||||||
PopulatePrototypeNodes(inlineLogicalNodes);
|
points[0].Position = anchorPosition;
|
||||||
}
|
points[0].PreviousPosition = anchorPosition;
|
||||||
|
|
||||||
private IReadOnlyList<FishingLineLogicalNodeDefinition> GetResolvedDefinitions()
|
|
||||||
{
|
|
||||||
if (rigDefinition != null && IsDefinitionListUsable(rigDefinition.LogicalNodes))
|
|
||||||
{
|
|
||||||
return rigDefinition.LogicalNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsDefinitionListUsable(inlineLogicalNodes))
|
|
||||||
{
|
|
||||||
return inlineLogicalNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
fallbackLogicalNodes.Clear();
|
|
||||||
PopulatePrototypeNodes(fallbackLogicalNodes);
|
|
||||||
return fallbackLogicalNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsDefinitionListUsable(IReadOnlyList<FishingLineLogicalNodeDefinition> definitions)
|
|
||||||
{
|
|
||||||
if (definitions == null || definitions.Count < 2)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definitions[0] == null || definitions[0].NodeType != FishingLineNodeType.Start)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
float totalDistance = 0f;
|
|
||||||
for (int index = 1; index < definitions.Count; index++)
|
|
||||||
{
|
|
||||||
FishingLineLogicalNodeDefinition definition = definitions[index];
|
|
||||||
if (definition == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
totalDistance += definition.DistanceFromPrevious;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalDistance > MinSegmentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PopulatePrototypeNodes(ICollection<FishingLineLogicalNodeDefinition> target)
|
|
||||||
{
|
|
||||||
FishingLineLogicalNodeDefinition startNode = new FishingLineLogicalNodeDefinition();
|
|
||||||
startNode.ConfigurePrototype("Start", FishingLineNodeType.Start, 0f, 0, 0f, 0f, new Color(0.4f, 1f, 0.6f, 1f));
|
|
||||||
|
|
||||||
FishingLineLogicalNodeDefinition floatNode = new FishingLineLogicalNodeDefinition();
|
|
||||||
floatNode.ConfigurePrototype("Float", FishingLineNodeType.Float, 1.2f, 5, 0.15f, 0.08f, new Color(1f, 0.75f, 0.2f, 1f));
|
|
||||||
|
|
||||||
FishingLineLogicalNodeDefinition weightNode = new FishingLineLogicalNodeDefinition();
|
|
||||||
weightNode.ConfigurePrototype("Weight", FishingLineNodeType.Weight, 1.4f, 4, 1.6f, 0.02f, new Color(0.7f, 0.85f, 1f, 1f));
|
|
||||||
|
|
||||||
FishingLineLogicalNodeDefinition terminalNode = new FishingLineLogicalNodeDefinition();
|
|
||||||
terminalNode.ConfigurePrototype("Terminal", FishingLineNodeType.Terminal, 0.8f, 2, 1.2f, 0.03f, new Color(1f, 0.35f, 0.35f, 1f));
|
|
||||||
|
|
||||||
target.Add(startNode);
|
|
||||||
target.Add(floatNode);
|
|
||||||
target.Add(weightNode);
|
|
||||||
target.Add(terminalNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SnapToAnchors()
|
|
||||||
{
|
|
||||||
for (int index = 0; index < points.Count; index++)
|
|
||||||
{
|
|
||||||
RuntimePoint point = points[index];
|
|
||||||
if (!point.IsAnchored)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 anchorPosition = point.Anchor != null ? point.Anchor.position : transform.position;
|
|
||||||
point.Position = anchorPosition;
|
|
||||||
point.PreviousPosition = anchorPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SyncAnchors()
|
|
||||||
{
|
|
||||||
for (int index = 0; index < points.Count; index++)
|
|
||||||
{
|
|
||||||
RuntimePoint point = points[index];
|
|
||||||
if (!point.IsAnchored)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 anchorPosition = point.Anchor != null ? point.Anchor.position : transform.position;
|
|
||||||
point.Position = anchorPosition;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Integrate(float deltaTime)
|
private void Integrate(float deltaTime)
|
||||||
{
|
{
|
||||||
float deltaTimeSqr = deltaTime * deltaTime;
|
float deltaTimeSquared = deltaTime * deltaTime;
|
||||||
|
|
||||||
for (int index = 0; index < points.Count; index++)
|
for (int index = 0; index < points.Count; index++)
|
||||||
{
|
{
|
||||||
@@ -401,13 +286,65 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
|
|
||||||
Vector3 velocity = point.Position - point.PreviousPosition;
|
Vector3 velocity = point.Position - point.PreviousPosition;
|
||||||
float dampingFactor = Mathf.Clamp01(1f - globalDamping - point.Damping);
|
float dampingFactor = Mathf.Clamp01(1f - globalDamping - point.Damping);
|
||||||
Vector3 nextPosition = point.Position + velocity * dampingFactor + Vector3.down * (gravity * point.GravityScale * deltaTimeSqr);
|
Vector3 nextPosition = point.Position + velocity * dampingFactor + Vector3.down * (gravity * point.GravityScale * deltaTimeSquared);
|
||||||
|
|
||||||
point.PreviousPosition = point.Position;
|
point.PreviousPosition = point.Position;
|
||||||
point.Position = nextPosition;
|
point.Position = nextPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyNodeBehaviours(float deltaTime)
|
||||||
|
{
|
||||||
|
for (int logicalIndex = 0; logicalIndex < logicalNodes.Count; logicalIndex++)
|
||||||
|
{
|
||||||
|
FishingLineNode node = logicalNodes[logicalIndex];
|
||||||
|
RuntimePoint point = points[GetLogicalPointIndex(logicalIndex)];
|
||||||
|
if (point.IsAnchored)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 tangent = GetLogicalNodeTangent(logicalIndex);
|
||||||
|
Vector3 velocity = point.Position - point.PreviousPosition;
|
||||||
|
|
||||||
|
FishingLineNodeContext context = new FishingLineNodeContext
|
||||||
|
{
|
||||||
|
Solver = this,
|
||||||
|
Node = node,
|
||||||
|
Position = point.Position,
|
||||||
|
PreviousPosition = point.PreviousPosition,
|
||||||
|
Velocity = velocity,
|
||||||
|
Tangent = tangent,
|
||||||
|
DeltaTime = deltaTime,
|
||||||
|
Time = Time.time
|
||||||
|
};
|
||||||
|
|
||||||
|
FishingLineNodeInfluence influence = default;
|
||||||
|
IReadOnlyList<FishingLineNodeBehaviour> behaviours = node.Behaviours;
|
||||||
|
for (int behaviourIndex = 0; behaviourIndex < behaviours.Count; behaviourIndex++)
|
||||||
|
{
|
||||||
|
FishingLineNodeBehaviour behaviour = behaviours[behaviourIndex];
|
||||||
|
if (behaviour == null || !behaviour.BehaviourEnabled)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
behaviour.Evaluate(ref influence, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyInfluence(point, influence, deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyInfluence(RuntimePoint point, FishingLineNodeInfluence influence, float deltaTime)
|
||||||
|
{
|
||||||
|
Vector3 velocity = point.Position - point.PreviousPosition + influence.VelocityOffset;
|
||||||
|
velocity *= Mathf.Clamp01(1f - influence.ExtraDamping);
|
||||||
|
|
||||||
|
point.PreviousPosition = point.Position - velocity;
|
||||||
|
point.Position += influence.PositionOffset + influence.AdditionalAcceleration * (deltaTime * deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
private void SolveConstraints()
|
private void SolveConstraints()
|
||||||
{
|
{
|
||||||
for (int iteration = 0; iteration < solverIterations; iteration++)
|
for (int iteration = 0; iteration < solverIterations; iteration++)
|
||||||
@@ -419,19 +356,13 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
|
|
||||||
Vector3 delta = pointB.Position - pointA.Position;
|
Vector3 delta = pointB.Position - pointA.Position;
|
||||||
float distance = delta.magnitude;
|
float distance = delta.magnitude;
|
||||||
float restLength = GetTargetSegmentLength(segmentIndex);
|
float restLength = GetSegmentTargetLength(segmentIndex);
|
||||||
if (distance <= restLength || distance <= Mathf.Epsilon)
|
if (distance <= restLength || distance <= Mathf.Epsilon)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 correction = delta * ((distance - restLength) / distance);
|
Vector3 correction = delta * ((distance - restLength) / distance);
|
||||||
|
|
||||||
if (pointA.IsAnchored && pointB.IsAnchored)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pointA.IsAnchored)
|
if (pointA.IsAnchored)
|
||||||
{
|
{
|
||||||
pointB.Position -= correction;
|
pointB.Position -= correction;
|
||||||
@@ -444,13 +375,28 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 halfCorrection = correction * 0.5f;
|
Vector3 half = correction * 0.5f;
|
||||||
pointA.Position += halfCorrection;
|
pointA.Position += half;
|
||||||
pointB.Position -= halfCorrection;
|
pointB.Position -= half;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float GetSegmentTargetLength(int segmentIndex)
|
||||||
|
{
|
||||||
|
if (segmentIndex < 0 || segmentIndex >= baseSegmentLengths.Count)
|
||||||
|
{
|
||||||
|
return MinSegmentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segmentIndex < startSegmentSubsegments)
|
||||||
|
{
|
||||||
|
return Mathf.Max(MinSegmentLength, startSegmentLength / Mathf.Max(1, startSegmentSubsegments));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mathf.Max(MinSegmentLength, baseSegmentLengths[segmentIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
private void RefreshLinePositions()
|
private void RefreshLinePositions()
|
||||||
{
|
{
|
||||||
linePositions.Clear();
|
linePositions.Clear();
|
||||||
@@ -460,70 +406,62 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExpandLineToCurrentLength()
|
private void SyncLogicalNodeTransforms()
|
||||||
{
|
{
|
||||||
if (points.Count < 2 || baseSegmentLengths.Count == 0)
|
for (int logicalIndex = 0; logicalIndex < logicalNodes.Count; logicalIndex++)
|
||||||
{
|
{
|
||||||
return;
|
FishingLineNode node = logicalNodes[logicalIndex];
|
||||||
}
|
RuntimePoint point = points[GetLogicalPointIndex(logicalIndex)];
|
||||||
|
node.transform.position = point.Position;
|
||||||
|
|
||||||
for (int segmentIndex = 0; segmentIndex < baseSegmentLengths.Count; segmentIndex++)
|
if (!node.AlignToLine)
|
||||||
{
|
|
||||||
RuntimePoint pointA = points[segmentIndex];
|
|
||||||
RuntimePoint pointB = points[segmentIndex + 1];
|
|
||||||
float targetLength = GetTargetSegmentLength(segmentIndex);
|
|
||||||
|
|
||||||
Vector3 delta = pointB.Position - pointA.Position;
|
|
||||||
Vector3 direction = delta.sqrMagnitude > Mathf.Epsilon
|
|
||||||
? delta.normalized
|
|
||||||
: (initialDirection.sqrMagnitude > 0f ? initialDirection.normalized : Vector3.down);
|
|
||||||
|
|
||||||
Vector3 targetPosition = pointA.Position + direction * targetLength;
|
|
||||||
|
|
||||||
if (pointB.IsAnchored)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 offset = targetPosition - pointB.Position;
|
Vector3 tangent = GetLogicalNodeTangent(logicalIndex);
|
||||||
pointB.Position += offset;
|
if (tangent.sqrMagnitude <= Mathf.Epsilon)
|
||||||
pointB.PreviousPosition += offset;
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion lineRotation = Quaternion.LookRotation(tangent.normalized, node.UpAxis.sqrMagnitude > 0f ? node.UpAxis.normalized : Vector3.up);
|
||||||
|
Quaternion axisOffset = Quaternion.FromToRotation(node.LocalForwardAxis.normalized, Vector3.forward);
|
||||||
|
node.transform.rotation = lineRotation * Quaternion.Inverse(axisOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float GetTargetSegmentLength(int segmentIndex)
|
private Vector3 GetStartAnchorPosition()
|
||||||
{
|
{
|
||||||
if (segmentIndex < 0 || segmentIndex >= baseSegmentLengths.Count || baseTotalLength <= MinSegmentLength)
|
if (startAnchor != null)
|
||||||
{
|
{
|
||||||
return MinSegmentLength;
|
return startAnchor.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
float normalizedLength = baseSegmentLengths[segmentIndex] / baseTotalLength;
|
if (logicalNodes.Count > 0 && logicalNodes[0] != null)
|
||||||
return Mathf.Max(MinSegmentLength, currentLineLength * normalizedLength);
|
{
|
||||||
|
return logicalNodes[0].transform.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTension()
|
private int GetLogicalPointIndex(int logicalNodeIndex)
|
||||||
{
|
{
|
||||||
if (baseSegmentLengths.Count == 0)
|
if (logicalNodeIndex < 0 || logicalNodeIndex >= logicalPointIndices.Count)
|
||||||
{
|
{
|
||||||
currentTensionNormalized = 0f;
|
return Mathf.Clamp(startSegmentSubsegments, 0, points.Count - 1);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float maxStretch = 0f;
|
return logicalPointIndices[logicalNodeIndex];
|
||||||
for (int segmentIndex = 0; segmentIndex < baseSegmentLengths.Count; segmentIndex++)
|
|
||||||
{
|
|
||||||
float currentLength = Vector3.Distance(points[segmentIndex].Position, points[segmentIndex + 1].Position);
|
|
||||||
float restLength = GetTargetSegmentLength(segmentIndex);
|
|
||||||
maxStretch = Mathf.Max(maxStretch, Mathf.Clamp01((currentLength - restLength) / restLength));
|
|
||||||
}
|
|
||||||
|
|
||||||
currentTensionNormalized = Mathf.Lerp(currentTensionNormalized, maxStretch, tensionSmoothing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReadOnlyList<FishingLineLogicalNodeDefinition> GetActiveDefinitions()
|
private Vector3 GetLogicalNodeTangent(int logicalNodeIndex)
|
||||||
{
|
{
|
||||||
return GetResolvedDefinitions();
|
int pointIndex = GetLogicalPointIndex(logicalNodeIndex);
|
||||||
|
Vector3 previous = pointIndex > 0 ? points[pointIndex - 1].Position : points[pointIndex].Position;
|
||||||
|
Vector3 next = pointIndex < points.Count - 1 ? points[pointIndex + 1].Position : points[pointIndex].Position;
|
||||||
|
return next - previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDrawGizmos()
|
private void OnDrawGizmos()
|
||||||
@@ -533,54 +471,133 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IReadOnlyList<FishingLineLogicalNodeDefinition> definitions = GetActiveDefinitions();
|
|
||||||
|
|
||||||
Gizmos.color = segmentColor;
|
Gizmos.color = segmentColor;
|
||||||
for (int segmentIndex = 0; segmentIndex < points.Count - 1; segmentIndex++)
|
for (int index = 0; index < points.Count - 1; index++)
|
||||||
{
|
{
|
||||||
Gizmos.DrawLine(points[segmentIndex].Position, points[segmentIndex + 1].Position);
|
Gizmos.DrawLine(points[index].Position, points[index + 1].Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int pointIndex = 0; pointIndex < points.Count; pointIndex++)
|
for (int pointIndex = 0; pointIndex < points.Count; pointIndex++)
|
||||||
{
|
{
|
||||||
RuntimePoint point = points[pointIndex];
|
RuntimePoint point = points[pointIndex];
|
||||||
if (point.IsLogicalNode)
|
if (point.LogicalNodeIndex >= 0 && point.LogicalNodeIndex < logicalNodes.Count)
|
||||||
{
|
{
|
||||||
FishingLineLogicalNodeDefinition definition = definitions[point.LogicalNodeIndex];
|
Gizmos.color = logicalNodes[point.LogicalNodeIndex].DebugColor;
|
||||||
Gizmos.color = definition.DebugColor;
|
Gizmos.DrawSphere(point.Position, debugPointRadius * 1.35f);
|
||||||
Gizmos.DrawSphere(point.Position, debugNodeRadius * 1.35f);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Gizmos.color = virtualNodeColor;
|
Gizmos.color = virtualPointColor;
|
||||||
Gizmos.DrawSphere(point.Position, debugNodeRadius);
|
Gizmos.DrawSphere(point.Position, debugPointRadius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
private void EnsureRuntimeTopologyMatchesLength()
|
||||||
private class RuntimeLogicalNode
|
|
||||||
{
|
{
|
||||||
public RuntimeLogicalNode(int logicalIndex, int pointIndex, RuntimePoint point)
|
if (logicalNodes.Count < 1)
|
||||||
{
|
{
|
||||||
LogicalIndex = logicalIndex;
|
return;
|
||||||
PointIndex = pointIndex;
|
|
||||||
Point = point;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int LogicalIndex { get; }
|
int minSubsegments = Mathf.Max(1, logicalNodes[0].VirtualNodeCount + 1);
|
||||||
public int PointIndex { get; }
|
int requiredSubsegments = Mathf.Max(minSubsegments, Mathf.CeilToInt(startSegmentLength / maxSolverSegmentLength));
|
||||||
public RuntimePoint Point { get; }
|
if (requiredSubsegments != startSegmentSubsegments)
|
||||||
|
{
|
||||||
|
BuildRuntime();
|
||||||
|
SnapAnchors();
|
||||||
|
RefreshLinePositions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeRuntimePointPositions(IReadOnlyList<Vector3> previousPolyline)
|
||||||
|
{
|
||||||
|
if (points.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 anchor = GetStartAnchorPosition();
|
||||||
|
points[0].Position = anchor;
|
||||||
|
points[0].PreviousPosition = anchor;
|
||||||
|
|
||||||
|
float targetTotalLength = TotalLineLength;
|
||||||
|
if (previousPolyline != null && previousPolyline.Count > 1)
|
||||||
|
{
|
||||||
|
Vector3 oldAnchor = previousPolyline[0];
|
||||||
|
Vector3 offset = anchor - oldAnchor;
|
||||||
|
float cumulativeDistance = 0f;
|
||||||
|
for (int pointIndex = 1; pointIndex < points.Count; pointIndex++)
|
||||||
|
{
|
||||||
|
cumulativeDistance += GetSegmentTargetLength(pointIndex - 1);
|
||||||
|
float normalized = targetTotalLength > MinSegmentLength ? cumulativeDistance / targetTotalLength : 0f;
|
||||||
|
Vector3 sampled = SamplePolylineNormalized(previousPolyline, normalized) + offset;
|
||||||
|
points[pointIndex].Position = sampled;
|
||||||
|
points[pointIndex].PreviousPosition = sampled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 direction = initialDirection.sqrMagnitude > 0f ? initialDirection.normalized : Vector3.down;
|
||||||
|
Vector3 cursor = anchor;
|
||||||
|
for (int pointIndex = 1; pointIndex < points.Count; pointIndex++)
|
||||||
|
{
|
||||||
|
cursor += direction * GetSegmentTargetLength(pointIndex - 1);
|
||||||
|
points[pointIndex].Position = cursor;
|
||||||
|
points[pointIndex].PreviousPosition = cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector3 SamplePolylineNormalized(IReadOnlyList<Vector3> polyline, float normalized)
|
||||||
|
{
|
||||||
|
if (polyline == null || polyline.Count == 0)
|
||||||
|
{
|
||||||
|
return Vector3.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polyline.Count == 1)
|
||||||
|
{
|
||||||
|
return polyline[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
float totalLength = 0f;
|
||||||
|
for (int index = 0; index < polyline.Count - 1; index++)
|
||||||
|
{
|
||||||
|
totalLength += Vector3.Distance(polyline[index], polyline[index + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalLength <= Mathf.Epsilon)
|
||||||
|
{
|
||||||
|
return polyline[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
float targetDistance = Mathf.Clamp01(normalized) * totalLength;
|
||||||
|
float traversed = 0f;
|
||||||
|
for (int index = 0; index < polyline.Count - 1; index++)
|
||||||
|
{
|
||||||
|
Vector3 from = polyline[index];
|
||||||
|
Vector3 to = polyline[index + 1];
|
||||||
|
float segmentLength = Vector3.Distance(from, to);
|
||||||
|
if (traversed + segmentLength >= targetDistance)
|
||||||
|
{
|
||||||
|
float t = segmentLength <= Mathf.Epsilon ? 0f : (targetDistance - traversed) / segmentLength;
|
||||||
|
return Vector3.Lerp(from, to, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
traversed += segmentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return polyline[polyline.Count - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
private class RuntimePoint
|
private class RuntimePoint
|
||||||
{
|
{
|
||||||
public RuntimePoint(Vector3 position, bool isAnchored, int logicalNodeIndex, float gravityScale, float damping)
|
public RuntimePoint(Vector3 position, bool anchored, int logicalNodeIndex, float gravityScale, float damping)
|
||||||
{
|
{
|
||||||
Position = position;
|
Position = position;
|
||||||
PreviousPosition = position;
|
PreviousPosition = position;
|
||||||
IsAnchored = isAnchored;
|
IsAnchored = anchored;
|
||||||
LogicalNodeIndex = logicalNodeIndex;
|
LogicalNodeIndex = logicalNodeIndex;
|
||||||
GravityScale = gravityScale;
|
GravityScale = gravityScale;
|
||||||
Damping = damping;
|
Damping = damping;
|
||||||
@@ -589,11 +606,8 @@ public class FishingLineSolver : MonoBehaviour
|
|||||||
public Vector3 Position;
|
public Vector3 Position;
|
||||||
public Vector3 PreviousPosition;
|
public Vector3 PreviousPosition;
|
||||||
public bool IsAnchored;
|
public bool IsAnchored;
|
||||||
public Transform Anchor;
|
|
||||||
public int LogicalNodeIndex;
|
public int LogicalNodeIndex;
|
||||||
public float GravityScale;
|
public float GravityScale;
|
||||||
public float Damping;
|
public float Damping;
|
||||||
|
|
||||||
public bool IsLogicalNode => LogicalNodeIndex >= 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class FishingGameplayController : MonoBehaviour
|
public class FishingLineTestController : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] private FishingLineSolver solver;
|
[SerializeField] private FishingLineSolver solver;
|
||||||
[SerializeField] [Min(0.01f)] private float reelSpeed = 1.5f;
|
[SerializeField] [Min(0.01f)] private float reelSpeed = 1.5f;
|
||||||
@@ -38,7 +38,7 @@ public class FishingGameplayController : MonoBehaviour
|
|||||||
|
|
||||||
if (Mathf.Abs(direction) > Mathf.Epsilon)
|
if (Mathf.Abs(direction) > Mathf.Epsilon)
|
||||||
{
|
{
|
||||||
solver.AdjustLineLength(direction * reelSpeed * Time.deltaTime);
|
solver.AdjustStartSegmentLength(direction * reelSpeed * Time.deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2
Assets/Scripts/FishingLineTestController.cs.meta
Normal file
2
Assets/Scripts/FishingLineTestController.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 465a2f7c62ee04948b577ee52382c43e
|
||||||
34
Assets/Scripts/FishingLureNodeBehaviour.cs
Normal file
34
Assets/Scripts/FishingLureNodeBehaviour.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class FishingLureNodeBehaviour : FishingLineNodeBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] [Min(0f)] private float swimStrength = 2f;
|
||||||
|
[SerializeField] [Min(0f)] private float swimFrequency = 6f;
|
||||||
|
[SerializeField] [Range(0f, 1f)] private float waterDrag = 0.12f;
|
||||||
|
[SerializeField] private Transform waterSurface;
|
||||||
|
[SerializeField] private float fallbackWaterHeight = 0f;
|
||||||
|
|
||||||
|
public override void Evaluate(ref FishingLineNodeInfluence influence, in FishingLineNodeContext context)
|
||||||
|
{
|
||||||
|
if (!BehaviourEnabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float surfaceY = waterSurface != null ? waterSurface.position.y : fallbackWaterHeight;
|
||||||
|
if (context.Position.y > surfaceY)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 side = Vector3.Cross(context.Tangent.sqrMagnitude > 0f ? context.Tangent.normalized : Vector3.forward, Vector3.up);
|
||||||
|
if (side.sqrMagnitude <= Mathf.Epsilon)
|
||||||
|
{
|
||||||
|
side = Vector3.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
float swim = Mathf.Sin(context.Time * swimFrequency) * swimStrength;
|
||||||
|
influence.AdditionalAcceleration += side.normalized * swim;
|
||||||
|
influence.ExtraDamping = Mathf.Max(influence.ExtraDamping, waterDrag);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/Scripts/FishingLureNodeBehaviour.cs.meta
Normal file
2
Assets/Scripts/FishingLureNodeBehaviour.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3c801f9083845c14088f6db1fdbc6020
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
[CreateAssetMenu(fileName = "FishingRigDefinition", menuName = "Fishing/Fishing Rig Definition")]
|
|
||||||
public class FishingRigDefinition : ScriptableObject
|
|
||||||
{
|
|
||||||
[SerializeField] private List<FishingLineLogicalNodeDefinition> logicalNodes = new List<FishingLineLogicalNodeDefinition>();
|
|
||||||
|
|
||||||
public IReadOnlyList<FishingLineLogicalNodeDefinition> LogicalNodes => logicalNodes;
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9d66919bfa33a7445b32a45410e0ccfe
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
%TAG !u! tag:unity3d.com,2011:
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
--- !u!78 &1
|
--- !u!78 &1
|
||||||
TagManager:
|
TagManager:
|
||||||
serializedVersion: 2
|
serializedVersion: 3
|
||||||
tags: []
|
tags: []
|
||||||
layers:
|
layers:
|
||||||
- Default
|
- Default
|
||||||
@@ -11,7 +11,7 @@ TagManager:
|
|||||||
-
|
-
|
||||||
- Water
|
- Water
|
||||||
- UI
|
- UI
|
||||||
-
|
- Terrain
|
||||||
-
|
-
|
||||||
-
|
-
|
||||||
-
|
-
|
||||||
@@ -50,27 +50,4 @@ TagManager:
|
|||||||
- Light Layer 5
|
- Light Layer 5
|
||||||
- Light Layer 6
|
- Light Layer 6
|
||||||
- Light Layer 7
|
- Light Layer 7
|
||||||
-
|
m_MigratedRenderPipelines: []
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
|
|||||||
Reference in New Issue
Block a user