168 lines
5.0 KiB
C#
168 lines
5.0 KiB
C#
|
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);
|
|||
|
private float _defaultRadius = 0;
|
|||
|
public float radius = 0.05f;
|
|||
|
public float scale = 1f;
|
|||
|
|
|||
|
//各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
|
|||
|
//Log("force :x = {0}, y = {1} z = {2}", force);
|
|||
|
//Log("prevTipPos :x = {0}, y = {1} z = {2}", prevTipPos);
|
|||
|
//Log("currTipPos :x = {0}, y = {1} z = {2}", currTipPos);
|
|||
|
force += (prevTipPos - currTipPos)* 2.3f / managerRef.transform.lossyScale.x * dragForce / sqrDt;
|
|||
|
|
|||
|
force += springForce / sqrDt;
|
|||
|
//Log("force :x = {0}, y = {1} z = {2}", force);
|
|||
|
|
|||
|
//前フレームと値が同じにならないように
|
|||
|
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++) {
|
|||
|
float dis = Vector3.Distance(currTipPos, colliders[i].transform.position);
|
|||
|
float radiusDis = radius + colliders[i].radius;
|
|||
|
if (dis <= radiusDis) {
|
|||
|
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 Log(string str, Vector3 vect)
|
|||
|
{
|
|||
|
if (trs.name == "Bone003" && prevTipPos != currTipPos)
|
|||
|
{
|
|||
|
UnityEngine.Debug.LogError(string.Format(str, vect.x, vect.y, vect.z));
|
|||
|
//UnityEngine.Debug.LogError(string.Format("dragForce = {0} stiness = {1}", dragForce, stiffnessForce));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void SetRedius()
|
|||
|
{
|
|||
|
scale = 1;
|
|||
|
if (_defaultRadius == 0)
|
|||
|
{
|
|||
|
_defaultRadius = radius;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
radius = _defaultRadius;
|
|||
|
}
|
|||
|
if (transform.parent)
|
|||
|
{
|
|||
|
SetScale(transform.parent);
|
|||
|
}
|
|||
|
radius = scale * radius;
|
|||
|
}
|
|||
|
|
|||
|
private void SetScale(Transform trans)
|
|||
|
{
|
|||
|
scale *= trans.localScale.x;
|
|||
|
if (trans.parent)
|
|||
|
{
|
|||
|
SetScale(trans.parent);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void OnDrawGizmos ()
|
|||
|
{
|
|||
|
currTipPos = child.position;
|
|||
|
Gizmos.color = Color.yellow;
|
|||
|
Gizmos.DrawWireSphere(currTipPos, radius);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|