填坑
背景
之前在刷知乎的时候刷到了一篇问题:如何模拟一根鱼竿
高赞回答只说了通过UE4和蓝图的一种实现。于是就想着自己通过Unity实现一版。
前言
木杆的弯曲,可以通过力学里的Cantilever beams(悬臂梁) algorithm算法进行模拟。
x
2
×
(
3
l
−
x
)
2
l
2
\frac{x^{2}\times \left ( 3l-x \right )}{2l^{2}}
2l2x2×(3l−x)
这个算法其实比较好理解,越靠近顶端权重逼近越快,越靠近起点权重变化越慢。这就很符合鱼竿的特征:顶端比较软,而手柄比较硬,整体表现比较软。
实现
对于悬臂梁算法的实现还是比较简单的
x:距离起点的距离
Input(x)
{
return pow(x,2) * (3 * l - x) / 2 * pow(l , 2);
}
在Unity中去这样方法还是比较简单的:
public static float GetWidth(float x,float l)
{
return Mathf.Pow(x, 2) * (3 * l - x) / (2 * Mathf.Pow(l, 3));
}
效果如下:
可以看到还是比较像的,这个可以模拟甩杆的效果。
More
那么只有这个模拟还是不够满意,我们希望实现更多的交互,比如收回来的时候回弹动画。这里就需要在Unity中实现一个Spring动画,如下面一样。
那么这个回弹动画该怎么实现?
回弹动画
首先,我们需要知道怎么做回弹效果。
回弹效果其实自需要对于每个顶点做一个回弹动画,让顶点去插值逼近原来的位置就行。
为什么是插值?
插值分为内插和外插,内插就是在
0
−
1
0-1
0−1的范围内,而外插就是在这个范围外,至于回弹出现的反弹出去的效果,可以通过外插实现。
这里给出一个springback的算法:
2
−
10
x
s
i
n
(
x
−
0.1
4
∗
2
π
f
a
c
t
i
o
n
)
+
1
2^{-10x}sin\left ( \frac{\frac{x-0.1}{4} *2\pi }{faction} \right ) + 1
2−10xsin(faction4x−0.1∗2π)+1
这个算法在图形上表示为:
可以从图上看到这个函数在y轴上会有一段曲线超出1的范围。这符合我们对于回弹的理解。而且根据调节不同的影响因子,回弹的效果会不同,也就可以模拟不同材质回弹结果
在Unity中进行实现:
public static float interpolationFaction = 0.3f;
public static float getInterpolation(float x)
{
return (Mathf.Pow(2, -10 * x) * Mathf.Sin((x - 0.1f / 4f) * (2f * Mathf.PI) / interpolationFaction) + 1f);
}
输入参数是当前回弹的进度,而输出是回弹当前进度的插值权重。
其他
在开发的时候也会遇到其他问题,这里做一个总结。
在Unity中,
Vector3D.lerp
函数没有外插值,范围会进行折叠到 [ 0 − 1 ] [0-1] [0−1]。因此我们需要自己实现一个Vector3D的线性插值版本:
public static Vector3 mylerp(Vector3 or, Vector3 tar, float input)
{
return tar * input + or * (1.0f - input);
}
测试通过,可以使用。
你可以通过一下链接找到测试工程:
https://github.com/ThisskyMain/UnityTestProject