Advertisement
Guest User

Untitled

a guest
Apr 26th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.99 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3.  
  4. [AddComponentMenu("Jiggle Bone/Jiggle Bone")]
  5. public class Jiggle : MonoBehaviour
  6. {
  7. public Transform m_Root = null;
  8. public float m_UpdateRate = 60.0f;
  9. public bool useUnscaledTime;
  10. [Range(0,1)] public float m_Damping = 0.1f;
  11. public AnimationCurve m_DampingDistrib;
  12. [Range(0,1)] public float m_Elasticity = 0.1f;
  13. public AnimationCurve m_ElasticityDistrib;
  14. [Range(0,1)] public float m_Stiffness = 0.1f;
  15. public AnimationCurve m_StiffnessDistrib;
  16. [Range(0,1)] public float m_Inert = 0;
  17. public AnimationCurve m_InertDistrib;
  18. public float m_Radius = 0;
  19. public AnimationCurve m_RadiusDistrib;
  20.  
  21. public float m_EndLength = 0;
  22. public Vector3 m_EndOffset = Vector3.zero;
  23. public Vector3 m_Gravity = Vector3.zero;
  24. public Vector3 m_Force = Vector3.zero;
  25. public List<Transform> m_Exclusions;
  26.  
  27. Vector3 m_LocalGravity = Vector3.zero;
  28. Vector3 m_ObjectMove = Vector3.zero;
  29. Vector3 m_ObjectPrevPosition = Vector3.zero;
  30. float m_BoneTotalLength = 0;
  31. float m_ObjectScale = 1.0f;
  32. float m_Time = 0;
  33. float m_Weight = 1.0f;
  34.  
  35. class Particle
  36. {
  37. public Transform m_Transform = null;
  38. public int m_ParentIndex = -1;
  39. public float m_Damping = 0;
  40. public float m_Elasticity = 0;
  41. public float m_Stiffness = 0;
  42. public float m_Inert = 0;
  43. public float m_Radius = 0;
  44. public float m_BoneLength = 0;
  45.  
  46. public Vector3 m_Position = Vector3.zero;
  47. public Vector3 m_PrevPosition = Vector3.zero;
  48. public Vector3 m_EndOffset = Vector3.zero;
  49. public Vector3 m_InitLocalPosition = Vector3.zero;
  50. public Quaternion m_InitLocalRotation = Quaternion.identity;
  51. }
  52.  
  53. List<Particle> m_Particles = new List<Particle>();
  54.  
  55. void Start()
  56. {
  57. SetupParticles();
  58. }
  59.  
  60. void Update()
  61. {
  62. if (m_Weight > 0)
  63. {
  64. InitTransforms();
  65. }
  66. }
  67.  
  68. void LateUpdate()
  69. {
  70. if (m_Weight > 0)
  71. {
  72. var dt = Time.deltaTime;
  73. if (useUnscaledTime)
  74. {
  75. dt = Time.unscaledDeltaTime;
  76. }
  77. UpdateJiggleBones(dt);
  78. }
  79. }
  80.  
  81. void OnEnable()
  82. {
  83. ResetParticlesPosition();
  84. m_ObjectPrevPosition = transform.position;
  85. }
  86.  
  87. void OnDisable()
  88. {
  89. InitTransforms();
  90. }
  91.  
  92. void OnValidate()
  93. {
  94. m_UpdateRate = Mathf.Max(m_UpdateRate, 0);
  95. m_Damping = Mathf.Clamp01(m_Damping);
  96. m_Elasticity = Mathf.Clamp01(m_Elasticity);
  97. m_Stiffness = Mathf.Clamp01(m_Stiffness);
  98. m_Inert = Mathf.Clamp01(m_Inert);
  99. m_Radius = Mathf.Max(m_Radius, 0);
  100.  
  101. if (Application.isEditor && Application.isPlaying)
  102. {
  103. InitTransforms();
  104. SetupParticles();
  105. }
  106. }
  107.  
  108. void OnDrawGizmosSelected()
  109. {
  110. if (!enabled || m_Root == null)
  111. return;
  112.  
  113. if (Application.isEditor && !Application.isPlaying && transform.hasChanged)
  114. {
  115. InitTransforms();
  116. SetupParticles();
  117. }
  118.  
  119. Gizmos.color = Color.white;
  120. foreach (Particle p in m_Particles)
  121. {
  122. if (p.m_ParentIndex >= 0)
  123. {
  124. Particle p0 = m_Particles[p.m_ParentIndex];
  125. Gizmos.DrawLine(p.m_Position, p0.m_Position);
  126. }
  127. if (p.m_Radius > 0)
  128. {
  129. Gizmos.DrawWireSphere(p.m_Position, p.m_Radius * m_ObjectScale);
  130. }
  131. }
  132. }
  133.  
  134. public void SetWeight(float w)
  135. {
  136. if (m_Weight != w)
  137. {
  138. if (w == 0)
  139. {
  140. InitTransforms();
  141. }
  142. else if (m_Weight == 0)
  143. {
  144. ResetParticlesPosition();
  145. m_ObjectPrevPosition = transform.position;
  146. }
  147. m_Weight = w;
  148. }
  149. }
  150.  
  151. public float GetWeight()
  152. {
  153. return m_Weight;
  154. }
  155.  
  156. void UpdateJiggleBones(float t)
  157. {
  158. if (m_Root == null)
  159. return;
  160.  
  161. m_ObjectScale = Mathf.Abs(transform.lossyScale.x);
  162. m_ObjectMove = transform.position - m_ObjectPrevPosition;
  163. m_ObjectPrevPosition = transform.position;
  164.  
  165. int loop = 1;
  166. if (m_UpdateRate > 0)
  167. {
  168. float dt = 1.0f / m_UpdateRate;
  169. m_Time += t;
  170. loop = 0;
  171.  
  172. while (m_Time >= dt)
  173. {
  174. m_Time -= dt;
  175. if (++loop >= 3)
  176. {
  177. m_Time = 0;
  178. break;
  179. }
  180. }
  181. }
  182.  
  183. if (loop > 0)
  184. {
  185. for (int j=0; j<loop; ++j)
  186. {
  187. UpdateParticles1();
  188. UpdateParticles2();
  189. m_ObjectMove = Vector3.zero;
  190. }
  191. }
  192. else
  193. {
  194. SkipUpdateParticles();
  195. }
  196.  
  197. ApplyParticlesToTransforms();
  198. }
  199.  
  200. void SetupParticles()
  201. {
  202. m_Particles.Clear();
  203. if (m_Root == null)
  204. return;
  205.  
  206. m_LocalGravity = m_Root.InverseTransformDirection(m_Gravity);
  207. m_ObjectScale = transform.lossyScale.x;
  208. m_ObjectPrevPosition = transform.position;
  209. m_ObjectMove = Vector3.zero;
  210. m_BoneTotalLength = 0;
  211. AppendParticles(m_Root, -1, 0);
  212.  
  213. foreach (Particle p in m_Particles)
  214. {
  215. p.m_Damping = m_Damping;
  216. p.m_Elasticity = m_Elasticity;
  217. p.m_Stiffness = m_Stiffness;
  218. p.m_Inert = m_Inert;
  219. p.m_Radius = m_Radius;
  220.  
  221. if (m_BoneTotalLength > 0)
  222. {
  223. float a = p.m_BoneLength / m_BoneTotalLength;
  224. if (m_DampingDistrib.keys.Length > 0)
  225. p.m_Damping *= m_DampingDistrib.Evaluate(a);
  226. if (m_ElasticityDistrib.keys.Length > 0)
  227. p.m_Elasticity *= m_ElasticityDistrib.Evaluate(a);
  228. if (m_StiffnessDistrib.keys.Length > 0)
  229. p.m_Stiffness *= m_StiffnessDistrib.Evaluate(a);
  230. if (m_InertDistrib.keys.Length > 0)
  231. p.m_Inert *= m_InertDistrib.Evaluate(a);
  232. if (m_RadiusDistrib.keys.Length > 0)
  233. p.m_Radius *= m_RadiusDistrib.Evaluate(a);
  234. }
  235.  
  236. p.m_Damping = Mathf.Clamp01(p.m_Damping);
  237. p.m_Elasticity = Mathf.Clamp01(p.m_Elasticity);
  238. p.m_Stiffness = Mathf.Clamp01(p.m_Stiffness);
  239. p.m_Inert = Mathf.Clamp01(p.m_Inert);
  240. p.m_Radius = Mathf.Max(p.m_Radius, 0);
  241. }
  242. }
  243.  
  244. void AppendParticles(Transform b, int parentIndex, float boneLength)
  245. {
  246. Particle p = new Particle();
  247. p.m_Transform = b;
  248. p.m_ParentIndex = parentIndex;
  249. if (b != null)
  250. {
  251. p.m_Position = p.m_PrevPosition = b.position;
  252. p.m_InitLocalPosition = b.localPosition;
  253. p.m_InitLocalRotation = b.localRotation;
  254. }
  255. else // end bone
  256. {
  257. Transform pb = m_Particles[parentIndex].m_Transform;
  258. if (m_EndLength > 0)
  259. {
  260. Transform ppb = pb.parent;
  261. if (ppb != null)
  262. {
  263. p.m_EndOffset = pb.InverseTransformPoint((pb.position * 2 - ppb.position)) * m_EndLength;
  264. }
  265. else
  266. {
  267. p.m_EndOffset = new Vector3(m_EndLength, 0, 0);
  268. }
  269. }
  270. else
  271. {
  272. p.m_EndOffset = pb.InverseTransformPoint(transform.TransformDirection(m_EndOffset) + pb.position);
  273. }
  274. p.m_Position = p.m_PrevPosition = pb.TransformPoint(p.m_EndOffset);
  275. }
  276.  
  277. if (parentIndex >= 0)
  278. {
  279. boneLength += (m_Particles[parentIndex].m_Transform.position - p.m_Position).magnitude;
  280. p.m_BoneLength = boneLength;
  281. m_BoneTotalLength = Mathf.Max(m_BoneTotalLength, boneLength);
  282. }
  283.  
  284. int index = m_Particles.Count;
  285. m_Particles.Add(p);
  286.  
  287. if (b != null)
  288. {
  289. for (int i=0; i<b.childCount; ++i)
  290. {
  291. bool exclude = false;
  292. foreach (Transform e in m_Exclusions)
  293. {
  294. if (e == b.GetChild(i))
  295. {
  296. exclude = true;
  297. break;
  298. }
  299. }
  300. if (!exclude)
  301. {
  302. AppendParticles(b.GetChild(i), index, boneLength);
  303. }
  304. }
  305.  
  306. if (b.childCount == 0 && (m_EndLength > 0 || m_EndOffset != Vector3.zero))
  307. {
  308. AppendParticles(null, index, boneLength);
  309. }
  310. }
  311. }
  312.  
  313. void InitTransforms()
  314. {
  315. foreach (Particle p in m_Particles)
  316. {
  317. if (p.m_Transform != null)
  318. {
  319. p.m_Transform.localPosition = p.m_InitLocalPosition;
  320. p.m_Transform.localRotation = p.m_InitLocalRotation;
  321. }
  322. }
  323. }
  324.  
  325. void ResetParticlesPosition()
  326. {
  327. foreach (Particle p in m_Particles)
  328. {
  329. if (p.m_Transform != null)
  330. {
  331. p.m_Position = p.m_PrevPosition = p.m_Transform.position;
  332. }
  333. else // end bone
  334. {
  335. Transform pb = m_Particles[p.m_ParentIndex].m_Transform;
  336. p.m_Position = p.m_PrevPosition = pb.TransformPoint(p.m_EndOffset);
  337. }
  338. }
  339. }
  340.  
  341. void UpdateParticles1()
  342. {
  343. Vector3 force = m_Gravity;
  344. Vector3 fdir = m_Gravity.normalized;
  345. Vector3 rf = m_Root.TransformDirection(m_LocalGravity);
  346. Vector3 pf = fdir * Mathf.Max(Vector3.Dot(rf, fdir), 0); // project current gravity to rest gravity
  347. force -= pf; // remove projected gravity
  348. force = (force + m_Force) * m_ObjectScale;
  349.  
  350. foreach (Particle p in m_Particles)
  351. {
  352. if (p.m_ParentIndex >= 0)
  353. {
  354. // verlet integration
  355. Vector3 v = p.m_Position - p.m_PrevPosition;
  356. Vector3 rmove = m_ObjectMove * p.m_Inert;
  357. p.m_PrevPosition = p.m_Position + rmove;
  358. p.m_Position += v * (1 - p.m_Damping) + force + rmove;
  359. }
  360. else
  361. {
  362. p.m_PrevPosition = p.m_Position;
  363. p.m_Position = p.m_Transform.position;
  364. }
  365. }
  366. }
  367.  
  368. void UpdateParticles2()
  369. {
  370. for (int i=1; i<m_Particles.Count; ++i)
  371. {
  372. Particle p = m_Particles[i];
  373. Particle p0 = m_Particles[p.m_ParentIndex];
  374.  
  375. float restLen;
  376. if (p.m_Transform != null)
  377. {
  378. restLen = (p0.m_Transform.position - p.m_Transform.position).magnitude;
  379. }
  380. else
  381. {
  382. restLen = p.m_EndOffset.magnitude * m_ObjectScale;
  383. }
  384.  
  385. // keep shape
  386. float stiffness = Mathf.Lerp(1.0f, p.m_Stiffness, m_Weight);
  387. if (stiffness > 0 || p.m_Elasticity > 0)
  388. {
  389. Matrix4x4 m0 = p0.m_Transform.localToWorldMatrix;
  390. m0.SetColumn(3, p0.m_Position);
  391. Vector3 restPos;
  392. if (p.m_Transform != null)
  393. {
  394. restPos = m0.MultiplyPoint3x4(p.m_Transform.localPosition);
  395. }
  396. else
  397. {
  398. restPos = m0.MultiplyPoint3x4(p.m_EndOffset);
  399. }
  400.  
  401. Vector3 d = restPos - p.m_Position;
  402. p.m_Position += d * p.m_Elasticity;
  403.  
  404. if (stiffness > 0)
  405. {
  406. d = restPos - p.m_Position;
  407. float len = d.magnitude;
  408. float maxlen = restLen * (1 - stiffness) * 2;
  409. if (len > maxlen)
  410. {
  411. p.m_Position += d * ((len - maxlen) / len);
  412. }
  413. }
  414. }
  415.  
  416. // keep length
  417. Vector3 dd = p0.m_Position - p.m_Position;
  418. float leng = dd.magnitude;
  419. if (leng > 0)
  420. {
  421. p.m_Position += dd * ((leng - restLen) / leng);
  422. }
  423. }
  424. }
  425.  
  426. // only update stiffness and keep bone length
  427. void SkipUpdateParticles()
  428. {
  429. foreach (Particle p in m_Particles)
  430. {
  431. if (p.m_ParentIndex >= 0)
  432. {
  433. Vector3 rmove = m_ObjectMove * p.m_Inert;
  434. p.m_PrevPosition += rmove;
  435. p.m_Position += rmove;
  436.  
  437. Particle p0 = m_Particles[p.m_ParentIndex];
  438.  
  439. float restLen;
  440. if (p.m_Transform != null)
  441. {
  442. restLen = (p0.m_Transform.position - p.m_Transform.position).magnitude;
  443. }
  444. else
  445. {
  446. restLen = p.m_EndOffset.magnitude * m_ObjectScale;
  447. }
  448.  
  449. // keep shape
  450. float stiffness = Mathf.Lerp(1.0f, p.m_Stiffness, m_Weight);
  451. if (stiffness > 0)
  452. {
  453. Matrix4x4 m0 = p0.m_Transform.localToWorldMatrix;
  454. m0.SetColumn(3, p0.m_Position);
  455. Vector3 restPos;
  456. if (p.m_Transform != null)
  457. {
  458. restPos = m0.MultiplyPoint3x4(p.m_Transform.localPosition);
  459. }
  460. else
  461. {
  462. restPos = m0.MultiplyPoint3x4(p.m_EndOffset);
  463. }
  464.  
  465. Vector3 d = restPos - p.m_Position;
  466. float len = d.magnitude;
  467. float maxlen = restLen * (1 - stiffness) * 2;
  468. if (len > maxlen)
  469. {
  470. p.m_Position += d * ((len - maxlen) / len);
  471. }
  472. }
  473.  
  474. // keep length
  475. Vector3 dd = p0.m_Position - p.m_Position;
  476. float leng = dd.magnitude;
  477. if (leng > 0)
  478. p.m_Position += dd * ((leng - restLen) / leng);
  479. }
  480. else
  481. {
  482. p.m_PrevPosition = p.m_Position;
  483. p.m_Position = p.m_Transform.position;
  484. }
  485. }
  486. }
  487.  
  488. void ApplyParticlesToTransforms()
  489. {
  490. for (int i=1; i<m_Particles.Count; ++i)
  491. {
  492. Particle p = m_Particles[i];
  493. Particle p0 = m_Particles[p.m_ParentIndex];
  494.  
  495. if (p0.m_Transform.childCount <= 1) // do not modify bone orientation if has more then one child
  496. {
  497. Vector3 v;
  498. if (p.m_Transform != null)
  499. {
  500. v = p.m_Transform.localPosition;
  501. }
  502. else
  503. {
  504. v = p.m_EndOffset;
  505. }
  506. Quaternion rot = Quaternion.FromToRotation(p0.m_Transform.TransformDirection(v), p.m_Position - p0.m_Position);
  507. p0.m_Transform.rotation = rot * p0.m_Transform.rotation;
  508. }
  509.  
  510. if (p.m_Transform)
  511. {
  512. p.m_Transform.position = p.m_Position;
  513. }
  514. }
  515. }
  516. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement