Advertisement
Guest User

Verlet Bobblehead

a guest
Aug 22nd, 2017
479
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.77 KB | None | 0 0
  1. using UnityEngine;
  2.  
  3. public class Bobble : MonoBehaviour {    
  4.     // We'll sproing about this transform's origin point.
  5.     public Transform pivot;
  6.  
  7.     // Tunable parameters for how sharply the bobble spring pulls back,
  8.     // and how long we keep bobbling after a shake.
  9.     public float stiffness = 100f;
  10.     [Range(0, 1)]
  11.     public float conservation = 0.98f;
  12.  
  13.     // Used to constrain the bobble to a shell around the pivot.
  14.     Vector3 _restPosition;
  15.     float _radius;
  16.  
  17.     // Track physics state for Verlet integration.
  18.     Vector3 _worldPosNew;
  19.     Vector3 _worldPosOld;
  20.  
  21.     // Used for interpolation between fixed steps.
  22.     float _timeElapsed;
  23.    
  24.     private void Start() {
  25.         // Cache our initial offset from the pivot as our resting position.
  26.         _restPosition = pivot.InverseTransformDirection(transform.position - pivot.position);
  27.         _radius = _restPosition.magnitude;
  28.     }
  29.        
  30.     private void FixedUpdate() {
  31.         // Compute a desired position our spring wants to push us to.
  32.         Vector3 desired = pivot.TransformPoint(_restPosition);
  33.  
  34.         // The further we are from this position, the more correcting force it applies.
  35.         Vector3 acceleration = stiffness * (desired - _worldPosNew);
  36.  
  37.         // Step forward a new position using Verlet integration.
  38.         Vector3 newPos = _worldPosNew + conservation * (_worldPosNew - _worldPosOld)
  39.             + Time.deltaTime * Time.deltaTime * acceleration;
  40.         _worldPosOld = _worldPosNew;
  41.  
  42.         // Constrain the bobble within our radius.
  43.         _worldPosNew = ClampedOffset(newPos) + pivot.position;
  44.  
  45.         // Clear the accumulated time now that we have a new sample.
  46.         _timeElapsed = 0f;
  47.     }
  48.  
  49.     private void Update() {
  50.         // Interpolate our position so we get nice smooth movement,
  51.         // without stutters or beats with the FixedUpdate rate.
  52.         _timeElapsed += Time.deltaTime;
  53.         float t = (_timeElapsed / Time.fixedDeltaTime) % 1.0f;
  54.         Vector3 blend = Vector3.Lerp(_worldPosOld, _worldPosNew, t);
  55.  
  56.         // Correct the interpolated position to one on the shell around our pivot.
  57.         Vector3 offset = ClampedOffset(blend);
  58.         transform.position = offset + pivot.position;
  59.  
  60.         // Orient so "up" points away from the pivot,
  61.         // and "forward" aligns roughly to the pivot's forward.
  62.         transform.rotation = Quaternion.LookRotation(offset, -pivot.forward)
  63.             * Quaternion.Euler(90f, 0f, 0f);
  64.     }
  65.  
  66.     Vector3 ClampedOffset(Vector3 position) {
  67.         // Clamp our position onto a spherical shell surrounding the pivot
  68.         // (as though we were swivelling on a rod of fixed length)
  69.         Vector3 offset = position - pivot.position;
  70.         return offset.normalized * _radius;
  71.     }
  72. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement