Guest User

Liquid.cs

a guest
Dec 7th, 2022
3,304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.78 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. [ExecuteInEditMode]
  6. public class Liquid : MonoBehaviour
  7. {
  8.     public enum UpdateMode { Normal, UnscaledTime }
  9.     public UpdateMode updateMode;
  10.  
  11.     [SerializeField]
  12.     float MaxWobble = 0.03f;
  13.     [SerializeField]
  14.     float WobbleSpeedMove = 1f;
  15.     [SerializeField]
  16.     float fillAmount = 0.5f;
  17.     [SerializeField]
  18.     float Recovery = 1f;
  19.     [SerializeField]
  20.     float Thickness = 1f;
  21.     [Range(0, 1)]
  22.     public float CompensateShapeAmount;
  23.     [SerializeField]
  24.     Mesh mesh;
  25.     [SerializeField]
  26.     Renderer rend;
  27.     Vector3 pos;
  28.     Vector3 lastPos;
  29.     Vector3 velocity;
  30.     Quaternion lastRot;
  31.     Vector3 angularVelocity;
  32.     float wobbleAmountX;
  33.     float wobbleAmountZ;
  34.     float wobbleAmountToAddX;
  35.     float wobbleAmountToAddZ;
  36.     float pulse;
  37.     float sinewave;
  38.     float time = 0.5f;
  39.     Vector3 comp;
  40.  
  41.     // Use this for initialization
  42.     void Start()
  43.     {
  44.         GetMeshAndRend();
  45.     }
  46.  
  47.     private void OnValidate()
  48.     {
  49.         GetMeshAndRend();
  50.     }
  51.  
  52.     void GetMeshAndRend()
  53.     {
  54.         if (mesh == null)
  55.         {
  56.             mesh = GetComponent<MeshFilter>().sharedMesh;
  57.         }
  58.         if (rend == null)
  59.         {
  60.             rend = GetComponent<Renderer>();
  61.         }
  62.     }
  63.     void Update()
  64.     {
  65.         float deltaTime = 0;
  66.         switch (updateMode)
  67.         {
  68.             case UpdateMode.Normal:
  69.                 deltaTime = Time.deltaTime;
  70.                 break;
  71.  
  72.             case UpdateMode.UnscaledTime:
  73.                 deltaTime = Time.unscaledDeltaTime;
  74.                 break;
  75.         }
  76.  
  77.         time += deltaTime;
  78.  
  79.         if (deltaTime != 0)
  80.         {
  81.  
  82.  
  83.             // decrease wobble over time
  84.             wobbleAmountToAddX = Mathf.Lerp(wobbleAmountToAddX, 0, (deltaTime * Recovery));
  85.             wobbleAmountToAddZ = Mathf.Lerp(wobbleAmountToAddZ, 0, (deltaTime * Recovery));
  86.  
  87.  
  88.  
  89.             // make a sine wave of the decreasing wobble
  90.             pulse = 2 * Mathf.PI * WobbleSpeedMove;
  91.             sinewave = Mathf.Lerp(sinewave, Mathf.Sin(pulse * time), deltaTime * Mathf.Clamp(velocity.magnitude + angularVelocity.magnitude, Thickness, 10));
  92.  
  93.             wobbleAmountX = wobbleAmountToAddX * sinewave;
  94.             wobbleAmountZ = wobbleAmountToAddZ * sinewave;
  95.  
  96.  
  97.  
  98.             // velocity
  99.             velocity = (lastPos - transform.position) / deltaTime;
  100.  
  101.             angularVelocity = GetAngularVelocity(lastRot, transform.rotation);
  102.  
  103.             // add clamped velocity to wobble
  104.             wobbleAmountToAddX += Mathf.Clamp((velocity.x + (velocity.y * 0.2f) + angularVelocity.z + angularVelocity.y) * MaxWobble, -MaxWobble, MaxWobble);
  105.             wobbleAmountToAddZ += Mathf.Clamp((velocity.z + (velocity.y * 0.2f) + angularVelocity.x + angularVelocity.y) * MaxWobble, -MaxWobble, MaxWobble);
  106.         }
  107.  
  108.         // send it to the shader
  109.         rend.sharedMaterial.SetFloat("_WobbleX", wobbleAmountX);
  110.         rend.sharedMaterial.SetFloat("_WobbleZ", wobbleAmountZ);
  111.  
  112.         // set fill amount
  113.         UpdatePos(deltaTime);
  114.  
  115.         // keep last position
  116.         lastPos = transform.position;
  117.         lastRot = transform.rotation;
  118.     }
  119.  
  120.     void UpdatePos(float deltaTime)
  121.     {
  122.  
  123.         Vector3 worldPos = transform.TransformPoint(new Vector3(mesh.bounds.center.x, mesh.bounds.center.y, mesh.bounds.center.z));
  124.         if (CompensateShapeAmount > 0)
  125.         {
  126.             // only lerp if not paused/normal update
  127.             if (deltaTime != 0)
  128.             {
  129.                 comp = Vector3.Lerp(comp, (worldPos - new Vector3(0, GetLowestPoint(), 0)), deltaTime * 10);
  130.             }
  131.             else
  132.             {
  133.                 comp = (worldPos - new Vector3(0, GetLowestPoint(), 0));
  134.             }
  135.  
  136.             pos = worldPos - transform.position - new Vector3(0, fillAmount - (comp.y * CompensateShapeAmount), 0);
  137.         }
  138.         else
  139.         {
  140.             pos = worldPos - transform.position - new Vector3(0, fillAmount, 0);
  141.         }
  142.         rend.sharedMaterial.SetVector("_FillAmount", pos);
  143.     }
  144.  
  145.     //https://forum.unity.com/threads/manually-calculate-angular-velocity-of-gameobject.289462/#post-4302796
  146.     Vector3 GetAngularVelocity(Quaternion foreLastFrameRotation, Quaternion lastFrameRotation)
  147.     {
  148.         var q = lastFrameRotation * Quaternion.Inverse(foreLastFrameRotation);
  149.         // no rotation?
  150.         // You may want to increase this closer to 1 if you want to handle very small rotations.
  151.         // Beware, if it is too close to one your answer will be Nan
  152.         if (Mathf.Abs(q.w) > 1023.5f / 1024.0f)
  153.             return Vector3.zero;
  154.         float gain;
  155.         // handle negatives, we could just flip it but this is faster
  156.         if (q.w < 0.0f)
  157.         {
  158.             var angle = Mathf.Acos(-q.w);
  159.             gain = -2.0f * angle / (Mathf.Sin(angle) * Time.deltaTime);
  160.         }
  161.         else
  162.         {
  163.             var angle = Mathf.Acos(q.w);
  164.             gain = 2.0f * angle / (Mathf.Sin(angle) * Time.deltaTime);
  165.         }
  166.         Vector3 angularVelocity = new Vector3(q.x * gain, q.y * gain, q.z * gain);
  167.  
  168.         if (float.IsNaN(angularVelocity.z))
  169.         {
  170.             angularVelocity = Vector3.zero;
  171.         }
  172.         return angularVelocity;
  173.     }
  174.  
  175.     float GetLowestPoint()
  176.     {
  177.         float lowestY = float.MaxValue;
  178.         Vector3 lowestVert = Vector3.zero;
  179.         Vector3[] vertices = mesh.vertices;
  180.  
  181.         for (int i = 0; i < vertices.Length; i++)
  182.         {
  183.  
  184.             Vector3 position = transform.TransformPoint(vertices[i]);
  185.  
  186.             if (position.y < lowestY)
  187.             {
  188.                 lowestY = position.y;
  189.                 lowestVert = position;
  190.             }
  191.         }
  192.         return lowestVert.y;
  193.     }
  194. }
  195.  
Add Comment
Please, Sign In to add comment