鱼竿弯曲
This commit is contained in:
194
Assets/Scripts/Editor/Fix/CCDIKRodWeightEditor.cs
Normal file
194
Assets/Scripts/Editor/Fix/CCDIKRodWeightEditor.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using RootMotion.FinalIK;
|
||||
|
||||
public static class CCDIKRodWeightEditor
|
||||
{
|
||||
// 默认鱼竿权重曲线:
|
||||
// 根部硬,末端软
|
||||
private static readonly AnimationCurve DefaultRodCurve = new AnimationCurve(
|
||||
new Keyframe(0.00f, 1.00f),
|
||||
new Keyframe(0.30f, 0.88f),
|
||||
new Keyframe(0.60f, 0.58f),
|
||||
new Keyframe(0.82f, 0.22f),
|
||||
new Keyframe(1.00f, 0.05f)
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// 对当前选中物体上的 CCDIK 应用默认鱼竿权重
|
||||
/// </summary>
|
||||
[MenuItem("Tools/FinalIK/CCDIK/Apply Rod Weights (Selected)")]
|
||||
public static void ApplyRodWeightsToSelected()
|
||||
{
|
||||
var go = Selection.activeGameObject;
|
||||
if (go == null)
|
||||
{
|
||||
Debug.LogWarning("没有选中任何 GameObject。");
|
||||
return;
|
||||
}
|
||||
|
||||
var ccdik = go.GetComponent<CCDIK>();
|
||||
if (ccdik == null)
|
||||
{
|
||||
Debug.LogWarning($"选中的物体 [{go.name}] 上没有 CCDIK 组件。");
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyWeights(ccdik, DefaultRodCurve, 0.05f, 1.0f, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 稍微软一点的版本
|
||||
/// </summary>
|
||||
[MenuItem("Tools/FinalIK/CCDIK/Apply Rod Weights Soft (Selected)")]
|
||||
public static void ApplyRodWeightsSoftToSelected()
|
||||
{
|
||||
var go = Selection.activeGameObject;
|
||||
if (go == null)
|
||||
{
|
||||
Debug.LogWarning("没有选中任何 GameObject。");
|
||||
return;
|
||||
}
|
||||
|
||||
var ccdik = go.GetComponent<CCDIK>();
|
||||
if (ccdik == null)
|
||||
{
|
||||
Debug.LogWarning($"选中的物体 [{go.name}] 上没有 CCDIK 组件。");
|
||||
return;
|
||||
}
|
||||
|
||||
var softCurve = new AnimationCurve(
|
||||
new Keyframe(0.00f, 1.00f),
|
||||
new Keyframe(0.25f, 0.92f),
|
||||
new Keyframe(0.50f, 0.72f),
|
||||
new Keyframe(0.75f, 0.35f),
|
||||
new Keyframe(1.00f, 0.10f)
|
||||
);
|
||||
|
||||
ApplyWeights(ccdik, softCurve, 0.10f, 1.0f, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更硬的版本
|
||||
/// </summary>
|
||||
[MenuItem("Tools/FinalIK/CCDIK/Apply Rod Weights Stiff (Selected)")]
|
||||
public static void ApplyRodWeightsStiffToSelected()
|
||||
{
|
||||
var go = Selection.activeGameObject;
|
||||
if (go == null)
|
||||
{
|
||||
Debug.LogWarning("没有选中任何 GameObject。");
|
||||
return;
|
||||
}
|
||||
|
||||
var ccdik = go.GetComponent<CCDIK>();
|
||||
if (ccdik == null)
|
||||
{
|
||||
Debug.LogWarning($"选中的物体 [{go.name}] 上没有 CCDIK 组件。");
|
||||
return;
|
||||
}
|
||||
|
||||
var stiffCurve = new AnimationCurve(
|
||||
new Keyframe(0.00f, 1.00f),
|
||||
new Keyframe(0.35f, 0.94f),
|
||||
new Keyframe(0.65f, 0.65f),
|
||||
new Keyframe(0.88f, 0.18f),
|
||||
new Keyframe(1.00f, 0.03f)
|
||||
);
|
||||
|
||||
ApplyWeights(ccdik, stiffCurve, 0.03f, 1.0f, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 核心逻辑:
|
||||
/// 第0个bone = 杆尾(高权重)
|
||||
/// 最后一个bone = 竿稍(低权重)
|
||||
/// </summary>
|
||||
public static void ApplyWeights(CCDIK ccdik, AnimationCurve curve, float minWeight, float maxWeight, bool logResult)
|
||||
{
|
||||
if (ccdik == null)
|
||||
{
|
||||
Debug.LogWarning("CCDIK 为空。");
|
||||
return;
|
||||
}
|
||||
|
||||
var solver = ccdik.solver;
|
||||
if (solver == null)
|
||||
{
|
||||
Debug.LogWarning("CCDIK.solver 为空。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (solver.bones == null || solver.bones.Length == 0)
|
||||
{
|
||||
Debug.LogWarning($"[{ccdik.name}] 的 solver.bones 为空,请先正确配置 CCDIK Chain。");
|
||||
return;
|
||||
}
|
||||
|
||||
Undo.RecordObject(ccdik, "Apply CCDIK Rod Weights");
|
||||
|
||||
int count = solver.bones.Length;
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
solver.bones[0].weight = maxWeight;
|
||||
EditorUtility.SetDirty(ccdik);
|
||||
Debug.Log($"[{ccdik.name}] 只有 1 根 bone,已设置 weight = {maxWeight:F3}");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// 0 = 杆尾,1 = 竿稍
|
||||
float t = 1f - (i / (float)(count - 1));
|
||||
|
||||
// 曲线前高后低
|
||||
float curveValue = curve.Evaluate(t);
|
||||
|
||||
// 限制范围
|
||||
float weight = Mathf.Lerp(minWeight, maxWeight, curveValue);
|
||||
weight = Mathf.Clamp(weight, minWeight, maxWeight);
|
||||
|
||||
solver.bones[i].weight = weight;
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(ccdik);
|
||||
|
||||
if (logResult)
|
||||
{
|
||||
Debug.Log(BuildWeightLog(ccdik));
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildWeightLog(CCDIK ccdik)
|
||||
{
|
||||
if (ccdik == null || ccdik.solver == null || ccdik.solver.bones == null)
|
||||
return "CCDIK 或 bones 无效。";
|
||||
|
||||
var bones = ccdik.solver.bones;
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine($"[{ccdik.name}] CCDIK Rod Weights Applied");
|
||||
sb.AppendLine($"Bone Count = {bones.Length}");
|
||||
sb.AppendLine("Index 0 = 杆尾,Last = 竿稍");
|
||||
sb.AppendLine("--------------------------------");
|
||||
|
||||
for (int i = 0; i < bones.Length; i++)
|
||||
{
|
||||
string boneName = bones[i].transform != null ? bones[i].transform.name : "NULL";
|
||||
sb.AppendLine($"[{i}] {boneName} weight = {bones[i].weight:F3}");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[MenuItem("Tools/FinalIK/CCDIK/Apply Rod Weights (Selected)", true)]
|
||||
[MenuItem("Tools/FinalIK/CCDIK/Apply Rod Weights Soft (Selected)", true)]
|
||||
[MenuItem("Tools/FinalIK/CCDIK/Apply Rod Weights Stiff (Selected)", true)]
|
||||
private static bool ValidateApplyRodWeights()
|
||||
{
|
||||
return Selection.activeGameObject != null &&
|
||||
Selection.activeGameObject.GetComponent<CCDIK>() != null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
3
Assets/Scripts/Editor/Fix/CCDIKRodWeightEditor.cs.meta
Normal file
3
Assets/Scripts/Editor/Fix/CCDIKRodWeightEditor.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b74c53bf2b849e3a899b34a5dbc348b
|
||||
timeCreated: 1775056514
|
||||
@@ -10,6 +10,8 @@ namespace NBF
|
||||
// [SerializeField] private Buoyancy _buoyancy;
|
||||
public Rigidbody rbody => _rbody;
|
||||
|
||||
public Rigidbody JointRb => joint.connectedBody;
|
||||
|
||||
public void SetJoint(Rigidbody rb)
|
||||
{
|
||||
joint = joint == null ? GetComponent<ConfigurableJoint>() : joint;
|
||||
|
||||
@@ -88,10 +88,10 @@ namespace NBF
|
||||
_tension = value;
|
||||
}
|
||||
|
||||
Scene.EventComponent.Publish(new PlayerItemRodLingChangeEvent
|
||||
{
|
||||
Item = this
|
||||
});
|
||||
// Scene.EventComponent.Publish(new PlayerItemRodLingChangeEvent
|
||||
// {
|
||||
// Item = this
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,15 +22,24 @@ namespace NBF
|
||||
|
||||
[SerializeField] private bool isLureConnect;
|
||||
[SerializeField] private RodLine rodLine;
|
||||
|
||||
/// <summary>
|
||||
/// 主线
|
||||
/// </summary>
|
||||
[SerializeField] private Rope fishingRope;
|
||||
|
||||
/// <summary>
|
||||
/// 浮漂和鱼钩线
|
||||
/// </summary>
|
||||
[SerializeField] private Rope bobberRope;
|
||||
|
||||
public LureController Lure;
|
||||
public BobberController Bobber;
|
||||
|
||||
|
||||
public JointPinchController PinchController;
|
||||
|
||||
|
||||
// public event Action OnLinePulled;
|
||||
public float LinelenghtDiferent;
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
@@ -112,8 +121,6 @@ namespace NBF
|
||||
Lure.RBody.useGravity = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void SetTargetLength(float value)
|
||||
{
|
||||
Log.Error($"SetObiRopeStretch={value}");
|
||||
@@ -121,13 +128,44 @@ namespace NBF
|
||||
{
|
||||
// value -= 0.2f;
|
||||
}
|
||||
|
||||
fishingRope.SetTargetLength(value);
|
||||
}
|
||||
|
||||
|
||||
public void SetLureLength(float value)
|
||||
{
|
||||
Log.Error($"SetObiRopeStretch={value}");
|
||||
bobberRope.SetTargetLength(value);
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
LinelenghtDiferent = GetLineDistance();
|
||||
|
||||
//非钓鱼状态
|
||||
Rod.PlayerItem.Tension = Mathf.Clamp(LinelenghtDiferent, 0f, 0.05f);
|
||||
}
|
||||
|
||||
#region Tension
|
||||
|
||||
private float GetLineDistance()
|
||||
{
|
||||
if (!Bobber.JointRb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//第一个节点到竿稍的位置-第一段鱼线长度
|
||||
return Vector3.Distance(Bobber.transform.position, Bobber.JointRb.transform.position) -
|
||||
fishingRope.GetCurrentLength();
|
||||
}
|
||||
|
||||
public float GetTension(float weight)
|
||||
{
|
||||
return weight * GetLineDistance();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using NBC.Asset;
|
||||
@@ -40,8 +41,14 @@ namespace NBF
|
||||
Asset = GetComponent<RodAsset>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Asset.CCDIK.enabled = true;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
BendControl();
|
||||
// if (Input.GetKeyDown(KeyCode.Alpha0))
|
||||
// {
|
||||
// SetLineLength(lineLength);
|
||||
@@ -68,7 +75,8 @@ namespace NBF
|
||||
Line.Lure.SetJointDistance(PlayerItem.LineLength);
|
||||
if (PlayerItem.StretchRope)
|
||||
{
|
||||
Line.SetTargetLength(PlayerItem.Tension > 0f ? 0f : PlayerItem.LineLength);
|
||||
// Line.SetTargetLength(PlayerItem.Tension > 0f ? 0f : PlayerItem.LineLength);
|
||||
Line.SetTargetLength(PlayerItem.LineLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -78,7 +86,8 @@ namespace NBF
|
||||
Line.Bobber.SetJointDistance(PlayerItem.LineLength - PlayerItem.FloatLength);
|
||||
if (PlayerItem.StretchRope)
|
||||
{
|
||||
Line.SetTargetLength(PlayerItem.Tension > 0f ? 0f : PlayerItem.LineLength - PlayerItem.FloatLength);
|
||||
// Line.SetTargetLength(PlayerItem.Tension > 0f ? 0f : PlayerItem.LineLength - PlayerItem.FloatLength);
|
||||
Line.SetTargetLength(PlayerItem.LineLength - PlayerItem.FloatLength);
|
||||
Line.SetLureLength(PlayerItem.FloatLength);
|
||||
}
|
||||
}
|
||||
@@ -115,8 +124,6 @@ namespace NBF
|
||||
|
||||
var obj = new GameObject($"rod_{ConfigId}");
|
||||
obj.transform.SetParent(SceneSettings.Instance.GearNode);
|
||||
// obj.transform.SetParent(player.transform);
|
||||
// obj.transform.localPosition = Vector3.zero;
|
||||
obj.transform.position = playerViewUnity.transform.position;
|
||||
obj.transform.rotation = playerViewUnity.transform.rotation;
|
||||
obj.transform.localScale = Vector3.one;
|
||||
@@ -124,8 +131,6 @@ namespace NBF
|
||||
|
||||
var parent = GearRoot;
|
||||
|
||||
// List<ItemInfo> children = RoleModel.Instance.GetBindItems(itemInfo.Id);
|
||||
|
||||
CreateFishingHandler();
|
||||
await FTask.WaitFrame(playerView.Scene); //等待1帧
|
||||
// children.Sort();
|
||||
@@ -301,6 +306,46 @@ namespace NBF
|
||||
rings = list.ToArray();
|
||||
}
|
||||
|
||||
|
||||
#region 鱼竿弯曲
|
||||
|
||||
private List<float> previousWeights = Enumerable.Repeat(0f, 10).ToList();
|
||||
private float bendSmooth = 1f;
|
||||
|
||||
private void BendControl()
|
||||
{
|
||||
// Vector3 vector = (FishEntity.CurrentFishInFight
|
||||
// ? FishEntity.CurrentFishInFight.transform.position
|
||||
// : fishingLine.currentLineHandler.LineConnector_1.transform.position);
|
||||
|
||||
var ccdik = Asset.CCDIK;
|
||||
|
||||
Vector3 vector = Line.Bobber.transform.position;
|
||||
// float num = Vector3.Distance(ccdik.solver.bones.Last().transform.position, vector);
|
||||
float num2 = 0.05f;
|
||||
|
||||
float num6 = 0.3f;
|
||||
// if (isThrowing)
|
||||
// {
|
||||
// num6 = 0.1f;
|
||||
// }
|
||||
// else if (!FishEntity.CurrentFishInFight)
|
||||
// {
|
||||
// num6 = 0.2f;
|
||||
// }
|
||||
|
||||
float target = num2 * num6;
|
||||
float item = Mathf.MoveTowards(ccdik.solver.IKPositionWeight, target, Time.deltaTime * bendSmooth);
|
||||
previousWeights.RemoveAt(0);
|
||||
previousWeights.Add(item);
|
||||
float num7 = previousWeights.Average();
|
||||
|
||||
ccdik.solver.SetIKPosition(vector);
|
||||
ccdik.solver.SetIKPositionWeight(num7);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void Test()
|
||||
{
|
||||
// var root = Player.ModelAsset.RodRoot;
|
||||
|
||||
@@ -561,7 +561,7 @@ public class Rope : MonoBehaviour
|
||||
LockAnchorsHard();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
private void Update()
|
||||
{
|
||||
if (!startAnchor || !endAnchor || _pCurr == null || _physicsNodes < 2) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user