Advertisement
CWHAHN

Liquid C#

Sep 7th, 2023 (edited)
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.29 KB | Gaming | 0 0
  1. using UnityEngine;
  2.  
  3. [ExecuteInEditMode]
  4. public class Liquid : MonoBehaviour
  5. {
  6.     Vector3 velocity;
  7.     Vector3 angularVelocity;
  8.     Vector3 lastPos;
  9.     Quaternion lastRot;
  10.  
  11.     Transform tr;
  12.  
  13.     public Mesh mesh;
  14.     public Renderer rend;
  15.  
  16.     float wobbleAddX, wobbleAddZ = 0;
  17.     public float wobbleMoveSpeed = 5f;
  18.     public float recoverySpeed = 0.8f;
  19.     float sinX;
  20.     float sinewave;
  21.     bool isMoving = false;
  22.  
  23.     [Range(0, 0.05f)]
  24.     public float maxWobble = 0.025f;
  25.  
  26.     float time = 1f;
  27.     float deltaTime = 0;
  28.     Vector3 localYDirection;
  29.  
  30.     void Start()
  31.     {
  32.         tr = GetComponent<Transform>();
  33.         lastPos = tr.position; //시작 가속도를 없애기 위해 설정
  34.  
  35.         if (mesh == null)
  36.         {
  37.             mesh = GetComponent<MeshFilter>().sharedMesh;
  38.         }
  39.         if (rend == null)
  40.         {
  41.             rend = GetComponent<Renderer>();
  42.         }
  43.         wobbleAddX = 0;
  44.         wobbleAddZ = 0;
  45.     }
  46.  
  47.  
  48.     void Update()
  49.     {
  50.         deltaTime = Time.deltaTime;
  51.         //움직이는동안에는 시간을 더해주는 것을 멈추어 물이 좌우로 움직이는 것을 멈춘다.
  52.         if (!isMoving)
  53.         { time += deltaTime; }
  54.  
  55.         //액체 움직임정도를 shader에 보낸다.
  56.         VelocityCalculation(deltaTime);
  57.  
  58.         //Mesh의 가장 밑부분을 shader에 보낸다.
  59.         rend.sharedMaterial.SetFloat("_WorldLowestYPos", GetLowestPoint());
  60.  
  61.  
  62.         //local Y Direction을 shader에 보낸다.
  63.         localYDirection = this.tr.up;
  64.         rend.sharedMaterial.SetVector("_LocalYDir", localYDirection.normalized);
  65.         //foam 위치
  66.         Vector3 WSCenterPos = tr.TransformPoint(new Vector3(mesh.bounds.center.x, mesh.bounds.center.y, mesh.bounds.center.z));
  67.         //float WSPosY = tr.position.y;
  68.         rend.sharedMaterial.SetFloat("_WSPosY", WSCenterPos.y);
  69.  
  70.  
  71.     }
  72.  
  73.     void VelocityCalculation(float deltaTime)
  74.     {
  75.         Vector3 currentPos = tr.position;
  76.         Quaternion currentRot = tr.rotation;
  77.  
  78.         //sin y값에 의해 좌우로 흔들리게 된다. sin x좌표의 위치를 지정해두는 것 1.0f/2.0f 5/2는 y값이 1이 나오기 때문 나눠줄때는 float 값으로 나눠주어야 float 값결과가 제대로 나온다.
  79.         sinX = 1.0f / 2.0f * Mathf.PI * wobbleMoveSpeed;
  80.         //velocity.magnitude혹은angularVelocity.magnitude가 0보다 크면 sin x좌표의 움직임을 멈춘다.
  81.         // if (velocity.magnitude > 0 || angularVelocity.magnitude > 0)
  82.         // { isMoving = true; time = 1; }
  83.         if (currentPos != lastPos || currentRot != lastRot)
  84.         { isMoving = true; time = 1; }
  85.         else
  86.         { isMoving = false; }
  87.         //sin y축 값
  88.         sinewave = Mathf.Sin(sinX * time);
  89.  
  90.         wobbleAddX = Mathf.Lerp(wobbleAddX, 0, deltaTime * recoverySpeed);
  91.         wobbleAddZ = Mathf.Lerp(wobbleAddZ, 0, deltaTime * recoverySpeed);
  92.  
  93.         //속력 구하기
  94.         velocity = (lastPos - currentPos) / deltaTime;
  95.         angularVelocity = GetAngularVelocity(lastRot, currentRot);
  96.  
  97.         //new Temp
  98.         //angularVelocity = GetPedestrianAngularVelocity();
  99.  
  100.         //maxWobble 값을 꼭 설정할 것 //속력을 낼수록 액체의 각도를 점점 기울인다.
  101.         wobbleAddX += Mathf.Clamp(velocity.x + velocity.y * 0.01f, -maxWobble, maxWobble);
  102.         wobbleAddZ += Mathf.Clamp(velocity.z + velocity.y * 0.01f, -maxWobble, maxWobble);
  103.         wobbleAddX += Mathf.Clamp(angularVelocity.z, -maxWobble - 0.03f, maxWobble + 0.03f);
  104.         wobbleAddZ += Mathf.Clamp(angularVelocity.x, -maxWobble - 0.03f, maxWobble + 0.03f);
  105.  
  106.         float wobbleX = wobbleAddX * sinewave;
  107.         float wobbleZ = wobbleAddZ * sinewave;
  108.  
  109.         lastPos = tr.position;
  110.         lastRot = tr.rotation;
  111.  
  112.         rend.sharedMaterial.SetFloat("_WobbleX", wobbleX);
  113.         rend.sharedMaterial.SetFloat("_WobbleZ", -wobbleZ);
  114.     }
  115.  
  116.  
  117.     //각 속도
  118.     Vector3 GetAngularVelocity(Quaternion foreLastFrameRotation, Quaternion lastFrameRotation)
  119.     {
  120.         var q = lastFrameRotation * Quaternion.Inverse(foreLastFrameRotation);
  121.         // no rotation?
  122.         // You may want to increase this closer to 1 if you want to handle very small rotations.
  123.         // Beware, if it is too close to one your answer will be Nan
  124.         if (Mathf.Abs(q.w) > 1023.9f / 1024.0f)  //if (Mathf.Abs(q.w) > 1023.5f / 1024.0f)
  125.             return Vector3.zero;
  126.         float gain;
  127.         // handle negatives, we could just flip it but this is faster
  128.         if (q.w < 0.0f)
  129.         {
  130.             var angle = Mathf.Acos(-q.w);
  131.             gain = -2.0f * angle / (Mathf.Sin(angle) * Time.deltaTime);
  132.         }
  133.         else
  134.         {
  135.             var angle = Mathf.Acos(q.w);
  136.             gain = 2.0f * angle / (Mathf.Sin(angle) * Time.deltaTime);
  137.         }
  138.         Vector3 angularVelocity = new Vector3(q.x * gain, q.y * gain, q.z * gain);
  139.  
  140.         if (float.IsNaN(angularVelocity.z))
  141.         {
  142.             angularVelocity = Vector3.zero;
  143.         }
  144.         return angularVelocity;
  145.     }
  146.     //가장 밑부분 vertex position 찾기
  147.     float GetLowestPoint()
  148.     {
  149.         float lowestY = float.MaxValue;
  150.         Vector3 lowestVert = Vector3.zero;
  151.         Vector3[] vertices = mesh.vertices;
  152.  
  153.         for (int i = 0; i < vertices.Length; i++)
  154.         {
  155.  
  156.             Vector3 position = transform.TransformPoint(vertices[i]);
  157.  
  158.             if (position.y < lowestY)
  159.             {
  160.                 lowestY = position.y;
  161.                 lowestVert = position;
  162.             }
  163.         }
  164.         return lowestVert.y;
  165.     }
  166.  
  167.     //Angular Velocity
  168.     Quaternion previousRotation; //전 프레임의 로테이션 값
  169.                                  //Vector3 angularVelocity; //각속도를 관리할 변수
  170.  
  171.     //이 함수를 업데이트에서 굴려줍니다.
  172.     public Vector3 GetPedestrianAngularVelocity()
  173.     {
  174.         Quaternion deltaRotation = tr.rotation * Quaternion.Inverse(previousRotation);
  175.  
  176.         previousRotation = tr.rotation;
  177.  
  178.         deltaRotation.ToAngleAxis(out var angle, out var axis);
  179.  
  180.         //각도에서 라디안으로 변환
  181.         angle *= Mathf.Deg2Rad;
  182.  
  183.         angularVelocity = (1.0f / Time.deltaTime) * angle * axis;
  184.  
  185.         //각속도 반환
  186.         return angularVelocity;
  187.     }
  188.  
  189.  
  190.  
  191. }
  192.  
Tags: Liquid
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement