Unity下实现弹簧⾻骼(SpringBone)
家用电器销售
关于这个效果的名称,我⼀直没到⼀个⽐较正式的说法。Spring Bone这个说法是来⾃于Anima2D这个插件中的⼀个演⽰⽤的脚本,我直接译成弹簧⾻骼。⼀般常见于对⼈物的头发的模拟上。
效果的实现是通过改变物体的旋转进⾏的。在LateUpdate执⾏代码。我们在脚本中保存上⼀帧的⾻骼末端位置,当运⾏当前帧时,如AnimatorController之类的组件会在Update中将物体的旋转设置为指定值。我们在LateUpdate中,通过保存的上⼀帧的⾻骼末端位置以及当前的旋转值,进⾏计算,得到⼀个类似的插值位置,然后转化为旋转值,将物体旋转到对应位置。 部分代码如下:送煤气罐
currentTipPos = transform.TransformPoint(springEnd);
currentTipPos = Vector3.Lerp(lastFrameTip, currentTipPos, Time.deltaTime);
currentTipPos = springLength * (currentTipPos - transform.position).normalized + transform.position; //clamp length.
兑换券制作Quaternion.FromToRotation(transform.TransformDirection(springEnd), (currentTipPos - transform.position).normalized)
* ation;
currentTipPos = springLength * (currentTipPos - transform.position).normalized + transform.position; //clamp length.
Quaternion.FromToRotation(transform.TransformDirection(springEnd), (currentTipPos - transform.position).normalized)
* ation;
这样的实现快速有效,但是最终效果仅仅是物体的运动变为慢慢靠近⽬标点,显得不够真实。
想要加⼊类似弹簧的效果,我们需要进⾏真实的⼒、速度的计算。我们保存当前的速度,根据位置计算当前受到的⼒,然后根据⼒修改速度,通过这个速度去修改⽬标位置。
currentTipPos = transform.TransformPoint(springEnd);
var force = bounciness * (currentTipPos - lastFrameTip); //spring force.
force += stiffness * (currentTipPos - transform.position).normalized; //stiffness
force -= dampness * velocity; //damp force.
velocity = velocity + force * Time.deltaTime; //v = v0 + at. we don't need integration here, you won't notice any "wrong".
currentTipPos = lastFrameTip + velocity * Time.deltaTime; //s = s0 + vt
currentTipPos = springLength * (currentTipPos - transform.position).normalized + transform.position; //clamp length.
太阳能沼气ation =
金属表面耐磨涂层
Quaternion.FromToRotation(transform.TransformDirection(springEnd), (currentTipPos - transform.position).normalized)核桃杨
* ation;
我设置了3个⼒的选项,分别是bounciness弹性⼒,提供“归位“的⼒,⼒由当前⾻骼末端指向归位时的⾻骼末端,stiffness刚性⼒,提供保持原状的⼒,⼒⽅向往⾻骼⽅向延长,以及dampbess阻⼒,沿着速度反⽅向。 通过设置三个⼒的⼤⼩,可以实现不同的效果。最终效果如⽂章开篇的图2
此外还有⼀个细节需要注意,⾻骼更新的顺序应该严格的遵守从⽗物体的⾻骼更新到⼦物体。不然可能会出现奇怪的情况。