using UnityEngine; public class RealWaterCollider : MonoBehaviour { public enum Objecttype { RigidBody = 0, CharacterController = 1 } private float xCoord; private float YCoord; [Tooltip("If true this input will be used for collision culling and as the center of normal map mode simulations. You should only have one per scene!")] public bool mainInput; [Tooltip("Is the collider a Rigidbody or a Character controller?")] public Objecttype ObjectType; [Tooltip("Force Multiplier")] [Range(0.01f, 1f)] public float InputForce = 1f; [Tooltip("Only check for collisions if the collider velocity exceeds this value")] public float VelocityLimit = 0.05f; [Tooltip("Raycast origin position offset.")] public Vector3 RaycastOffset; public float RaycastLength = 1f; [Tooltip("Extrapolates between input points, allows for smoother more consistent input.")] public bool ExtrapolateInput = true; [Tooltip("Disables the visibility check so water collider will always check for collisions even when not visible.")] public bool FirstPersonMode; [Tooltip("Enables collision logging and ray drawing in the inspector. Also removes the velocity limitation.Very useful for Setup.")] public bool DebugMode; [Tooltip("Ensures input position of RealWaterNormal map instances is updated frequently enough to prevent errors with fade algorithm at low speeds (<~10).")] public bool lowSpeedMode; private float zPositionCurrent; private float xPositionCurrent; private float zPositionPrevious; private float xPositionPrevious; private bool checkWaterCollision = true; private bool crouching; private RWInput rwInput = new RWInput(); private BresenhamLineDrawer lineDrawer = new BresenhamLineDrawer(); private bool firstRun = true; private float collisionCheckFrequency = 60f; private bool isCharController; private bool isRigidbody; private CharacterController controller; private RaycastHit hit; private int baseForce = 18000000; private bool visible = true; private RealWaterInterface previousPlane; public static bool reseting; private void Start() { switch (ObjectType) { case Objecttype.CharacterController: isCharController = true; controller = GetComponent(); break; case Objecttype.RigidBody: isRigidbody = true; break; } if (DebugMode) { VelocityLimit = -1f; } else { InvokeRepeating("PositionCheck1", 0.001f, 1f / 30f); } if (!FirstPersonMode && !DebugMode) { InvokeRepeating("VisibilityCheck", 0.001f, 0.2f); } if (mainInput && lowSpeedMode) { InvokeRepeating("LowSpeedInputPositionSet", 0.001f, 1f / 30f); } } private void Update() { if (reseting) { Reset(); } } public void Reset() { rwInput.SetFirstInput(val: true); } private void LowSpeedInputPositionSet() { if (Physics.Raycast(base.transform.position + RaycastOffset, Vector3.down, out var hitInfo, RaycastLength) && hitInfo.collider.gameObject.name == "RealWater Plane") { xCoord = hitInfo.textureCoord.x; YCoord = hitInfo.textureCoord.y; int rows = hitInfo.collider.gameObject.GetComponent().GetRows(); int cols = hitInfo.collider.gameObject.GetComponent().GetCols(); int num = (int)(YCoord * (float)rows); int num2 = (int)(xCoord * (float)cols); if (!hitInfo.collider.gameObject.GetComponent().IsFullPlaneSim()) { hitInfo.collider.gameObject.GetComponent().SetInputPos(new Vector2(num, num2)); } } } private void PositionCheck1() { zPositionPrevious = Mathf.Round(base.transform.position.z * 10f) / 10f; xPositionPrevious = Mathf.Round(base.transform.position.x * 10f) / 10f; Invoke("PositionCheck2", 1f); } private void PositionCheck2() { zPositionCurrent = Mathf.Round(base.transform.position.z * 10f) / 10f; xPositionCurrent = Mathf.Round(base.transform.position.x * 10f) / 10f; if (isRigidbody) { if (Mathf.Round(GetComponent().velocity.y) == 0f) { if (zPositionCurrent == zPositionPrevious && xPositionCurrent == xPositionPrevious) { checkWaterCollision = false; } else if (!crouching) { checkWaterCollision = true; } } else { checkWaterCollision = true; } } else { if (!isCharController) { return; } if (Mathf.Round(controller.velocity.y) == 0f) { if (zPositionCurrent == zPositionPrevious && xPositionCurrent == xPositionPrevious) { checkWaterCollision = false; } else if (!crouching) { checkWaterCollision = true; } } else { checkWaterCollision = true; } } } private void VisibilityCheck() { if (!GetComponent().isVisible && !DebugMode) { CancelInvoke("CheckForCollisions"); CancelInvoke("PositionCheck1"); visible = false; } else if (!visible && GetComponent().isVisible) { InvokeRepeating("CheckForCollisions", 0.005f, 1f / collisionCheckFrequency); InvokeRepeating("PositionCheck1", 0.001f, 1f / 30f); rwInput.SetFirstInput(val: true); visible = true; } } private void OnDisable() { CancelInvoke(); RealWaterSpeedManager realWaterSpeedManager = Object.FindObjectOfType(typeof(RealWaterSpeedManager)) as RealWaterSpeedManager; if (realWaterSpeedManager != null) { realWaterSpeedManager.FindColliders(); } rwInput.SetFirstInput(val: true); } private void OnEnable() { if (!firstRun) { RealWaterSpeedManager realWaterSpeedManager = Object.FindObjectOfType(typeof(RealWaterSpeedManager)) as RealWaterSpeedManager; if (realWaterSpeedManager != null) { realWaterSpeedManager.FindColliders(); } if (!FirstPersonMode && !DebugMode) { InvokeRepeating("VisibilityCheck", 0.001f, 0.2f); } if (!crouching) { checkWaterCollision = true; } InvokeRepeating("PositionCheck1", 0.001f, 1f / 30f); } else { firstRun = false; } } private void CheckForCollisions() { if (!checkWaterCollision) { return; } if (Physics.Raycast(base.transform.position + RaycastOffset, Vector3.down, out var hitInfo, 100f) && hitInfo.collider.gameObject.name == "RealWater Plane") { xCoord = hitInfo.textureCoord.x; YCoord = hitInfo.textureCoord.y; int rows = hitInfo.collider.gameObject.GetComponent().GetRows(); int cols = hitInfo.collider.gameObject.GetComponent().GetCols(); int num = (int)(YCoord * (float)rows); int num2 = (int)(xCoord * (float)cols); if (!hitInfo.collider.gameObject.GetComponent().IsFullPlaneSim()) { hitInfo.collider.gameObject.GetComponent().SetInputPos(new Vector2(num, num2)); } } if (DebugMode) { Debug.DrawRay(base.transform.position + RaycastOffset, Vector3.down.normalized * RaycastLength, Color.red, 0.01f, depthTest: false); } if (Physics.Raycast(base.transform.position + RaycastOffset, Vector3.down, out hit, RaycastLength)) { if (DebugMode) { MonoBehaviour.print(hit.collider.gameObject.name); } if (hit.collider.gameObject.name == "RealWater Plane") { if (mainInput && previousPlane != null) { ((MonoBehaviour)previousPlane).CancelInvoke("Pause"); if (previousPlane.GetPaused() && hit.collider.gameObject.GetComponent().GetCollisionCulling() && !hit.collider.gameObject.GetComponent().GetAmbientMode()) { hit.collider.gameObject.GetComponent().Play(); } } if (isRigidbody) { if (GetComponent().velocity.magnitude > VelocityLimit) { ProcessCollision(); } else { rwInput.SetFirstInput(val: true); } } else if (controller.velocity.magnitude > VelocityLimit) { ProcessCollision(); } else { rwInput.SetFirstInput(val: true); } if (previousPlane == null) { previousPlane = hit.collider.gameObject.GetComponent(); } else if (previousPlane != hit.collider.gameObject.GetComponent() && mainInput && previousPlane.GetCollisionCulling() && !previousPlane.GetAmbientMode() && mainInput) { ((MonoBehaviour)previousPlane).Invoke("Pause", previousPlane.GetInterPlanePauseDelay()); previousPlane = hit.collider.gameObject.GetComponent(); } else { previousPlane = hit.collider.gameObject.GetComponent(); } } else if (previousPlane != null) { rwInput.SetFirstInput(val: true); if (!previousPlane.GetPaused() && mainInput && !previousPlane.GetAmbientMode() && previousPlane.GetCollisionCulling() && mainInput) { ((MonoBehaviour)previousPlane).Invoke("Pause", previousPlane.GetExitPauseDelay()); } } } else { rwInput.SetFirstInput(val: true); if (previousPlane != null && !previousPlane.GetPaused() && mainInput && !previousPlane.GetAmbientMode() && previousPlane.GetCollisionCulling() && mainInput) { ((MonoBehaviour)previousPlane).Invoke("Pause", previousPlane.GetExitPauseDelay()); } } } private void ProcessCollision() { xCoord = hit.textureCoord.x; YCoord = hit.textureCoord.y; int rows = hit.collider.gameObject.GetComponent().GetRows(); int cols = hit.collider.gameObject.GetComponent().GetCols(); int bR = hit.collider.gameObject.GetComponent().GetBR(); int num = (int)(YCoord * (float)rows); int num2 = (int)(xCoord * (float)cols); bool visibility = hit.collider.gameObject.GetComponent().GetVisibility(); bool paused = hit.collider.gameObject.GetComponent().GetPaused(); if (mainInput && !hit.collider.gameObject.GetComponent().IsFullPlaneSim()) { hit.collider.gameObject.GetComponent().SetInputPos(new Vector2(num, num2)); } if (!paused && visibility && num2 > bR + 1 && num2 < cols - bR + 1 && num < rows - (bR + 2) && num > bR + 2) { if (ExtrapolateInput) { if (!rwInput.GetFirstInput()) { if (rwInput.GetFirstPoint()) { rwInput.SetX1(num); rwInput.SetY1(num2); rwInput.SetPlane1(hit.collider.GetInstanceID()); } else { rwInput.SetX2(num); rwInput.SetY2(num2); rwInput.SetPlane2(hit.collider.GetInstanceID()); } if (rwInput.GetPlane1() == rwInput.GetPlane2()) { lineDrawer.DrawLine(rwInput.GetX1(), rwInput.GetX2(), rwInput.GetY1(), rwInput.GetY2(), hit, InputForce); } rwInput.SetFirstPoint(!rwInput.GetFirstPoint()); } else { rwInput.SetX1(num); rwInput.SetY1(num2); rwInput.SetX2(num); rwInput.SetY2(num2); rwInput.SetFirstInput(val: false); } } else { hit.collider.gameObject.GetComponent().DisturbBufferAt(num, num2, (int)(18000000f * InputForce), ambient: false); } } else { rwInput.SetFirstInput(val: true); } } public bool GetCrouching() { return crouching; } public void SetCrouching(bool val) { crouching = val; } public bool GetCheckCollisions() { return checkWaterCollision; } public void SetCheckCollisions(bool val) { checkWaterCollision = val; } public float GetCollisionFrequency() { return collisionCheckFrequency; } public void SetCollisionFrequency(float val) { collisionCheckFrequency = val; } public bool GetVisibility() { return visible; } }