meteorgame/Assets/UnityChan/Scripts/SpringBone.cs

136 lines
3.7 KiB
C#
Raw Permalink Normal View History

2021-03-18 15:56:10 +00:00
//
//SpringBone.cs for unity-chan!
//
//Original Script is here:
//ricopin / SpringBone.cs
//Rocket Jump : http://rocketjump.skr.jp/unity3d/109/
//https://twitter.com/ricopin416
//
//Revised by N.Kobayashi 2014/06/20
//
using UnityEngine;
using System.Collections;
namespace UnityChan
{
public class SpringBone : MonoBehaviour
{
//次のボーン
public Transform child;
//ボーンの向き
public Vector3 boneAxis = new Vector3 (-1.0f, 0.0f, 0.0f);
public float radius = 0.05f;
//各SpringBoneに設定されているstiffnessForceとdragForceを使用するか
public bool isUseEachBoneForceSettings = false;
//バネが戻る力
public float stiffnessForce = 0.01f;
//力の減衰力
public float dragForce = 0.4f;
public Vector3 springForce = new Vector3 (0.0f, -0.0001f, 0.0f);
public SpringCollider[] colliders;
public bool debug = true;
//Kobayashi:Thredshold Starting to activate activeRatio
public float threshold = 0.01f;
private float springLength;
private Quaternion localRotation;
private Transform trs;
private Vector3 currTipPos;
private Vector3 prevTipPos;
//Kobayashi
private Transform org;
//Kobayashi:Reference for "SpringManager" component with unitychan
private SpringManager managerRef;
private void Awake ()
{
trs = transform;
localRotation = transform.localRotation;
//Kobayashi:Reference for "SpringManager" component with unitychan
// GameObject.Find("unitychan_dynamic").GetComponent<SpringManager>();
managerRef = GetParentSpringManager (transform);
}
private SpringManager GetParentSpringManager (Transform t)
{
var springManager = t.GetComponent<SpringManager> ();
if (springManager != null)
return springManager;
if (t.parent != null) {
return GetParentSpringManager (t.parent);
}
return null;
}
private void Start ()
{
springLength = Vector3.Distance (trs.position, child.position);
currTipPos = child.position;
prevTipPos = child.position;
}
public void UpdateSpring ()
{
//Kobayashi
org = trs;
//回転をリセット
trs.localRotation = Quaternion.identity * localRotation;
float sqrDt = Time.deltaTime * Time.deltaTime;
//stiffness
Vector3 force = trs.rotation * (boneAxis * stiffnessForce) / sqrDt;
//drag
force += (prevTipPos - currTipPos) * dragForce / sqrDt;
force += springForce / sqrDt;
//前フレームと値が同じにならないように
Vector3 temp = currTipPos;
//verlet
currTipPos = (currTipPos - prevTipPos) + currTipPos + (force * sqrDt);
//長さを元に戻す
currTipPos = ((currTipPos - trs.position).normalized * springLength) + trs.position;
//衝突判定
for (int i = 0; i < colliders.Length; i++) {
if (Vector3.Distance (currTipPos, colliders [i].transform.position) <= (radius + colliders [i].radius)) {
Vector3 normal = (currTipPos - colliders [i].transform.position).normalized;
currTipPos = colliders [i].transform.position + (normal * (radius + colliders [i].radius));
currTipPos = ((currTipPos - trs.position).normalized * springLength) + trs.position;
}
}
prevTipPos = temp;
//回転を適用;
Vector3 aimVector = trs.TransformDirection (boneAxis);
Quaternion aimRotation = Quaternion.FromToRotation (aimVector, currTipPos - trs.position);
//original
//trs.rotation = aimRotation * trs.rotation;
//Kobayahsi:Lerp with mixWeight
Quaternion secondaryRotation = aimRotation * trs.rotation;
trs.rotation = Quaternion.Lerp (org.rotation, secondaryRotation, managerRef.dynamicRatio);
}
private void OnDrawGizmos ()
{
if (debug) {
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere (currTipPos, radius);
}
}
}
}