using System; using System.Linq; using UnityEngine; using static AffectingForcesManager; public class NimbleZoneDetection : MonoBehaviour { public AffectingForcesManager forcesManager; public GameObject renderedZoneObject; public enum Gravities { DownGravity, NoGravity, InwardsGravity, OutwardsGravity } [SerializeField] private static float gravityFactor = 30f; [SerializeField] private Gravities outsideGravityFunction = Gravities.NoGravity; [SerializeField] private Zone zone = Zone.NimbleZone; // Ripple properties [SerializeField] private float rippleFrequency = 3f; [SerializeField] private float rippleDensity = 30f; [SerializeField] private float rippleAmplitude = 0.2f; [SerializeField] private float rippleBlend = 1f; [SerializeField] private float rippleRadius = 2f; [SerializeField] private float rippleDuration = 2f; private int maxRippleAmount = 5; private int playerCount = 2; private int spawnedCount = 0; private MeshRenderer meshRenderer; private Material material; void Awake() { meshRenderer = renderedZoneObject.GetComponent(); material = meshRenderer.material; ResetRippleShaderProperties(); } private Func[] gravityFunctions = { DownGravity, NoGravity, InwardsGravity, OutwardsGravity }; private static Func NoGravity = new Func(position => new Vector3()); private static Func DownGravity = new Func(position => Vector3.down * gravityFactor); private static Func InwardsGravity = new Func (position => new Vector3(position.x, position.y, 0).normalized * -gravityFactor); private static Func OutwardsGravity = new Func (position => new Vector3(position.x, position.y, 0).normalized * gravityFactor); public Func GetGravityFunction(Gravities gravity) { return gravityFunctions[(int)gravity]; } private void OnTriggerEnter(Collider collider) { int instanceID = collider.gameObject.GetInstanceID(); if (spawnedCount < playerCount) ++spawnedCount; else SpawnRipple(collider, false); forcesManager.SetGravityForInstance(instanceID, NoGravity); forcesManager.SetZoneForInstance(instanceID, zone); } private void OnTriggerExit(Collider collider) { int instanceID = collider.gameObject.GetInstanceID(); SpawnRipple(collider, true); forcesManager.SetGravityForInstance(instanceID, GetGravityFunction(outsideGravityFunction)); forcesManager.SetZoneForInstance(instanceID, Zone.OutsideZone); } private void Update() { material.SetFloat("_ShaderTime", Time.timeSinceLevelLoad); } private void SpawnRipple(Collider collider, bool isOutwardsRipple) { Rigidbody body = collider.attachedRigidbody; GameObject gameObject = collider.gameObject; float velocity = body.velocity.magnitude; Vector3 position = (gameObject.transform.position - transform.position).normalized; Vector4[] rippleOrigins = material.GetVectorArray("_RippleOrigins"); float currentTime = Time.timeSinceLevelLoad; float[] startedTimes = material.GetFloatArray("_RippleStartTimes"); float[] startedRippleDurations = material.GetFloatArray("_RippleDurations"); float[] rippleAmplitudes = material.GetFloatArray("_RippleAmplitudes"); float[] rippleFrequencies = material.GetFloatArray("_RippleFrequencies"); float[] rippleDensities = material.GetFloatArray("_RippleDensities"); float[] rippleRadii = material.GetFloatArray("_RippleRadii"); for (int i = 0; i < startedTimes.Length; ++i) { if (startedTimes[i] + startedRippleDurations[i] < currentTime) { rippleOrigins[i] = new Vector4(position.x, position.y, position.z, 0); material.SetVectorArray("_RippleOrigins", rippleOrigins); startedTimes[i] = currentTime; material.SetFloatArray("_RippleStartTimes", startedTimes); rippleAmplitudes[i] = isOutwardsRipple ? rippleAmplitude : -rippleAmplitude; rippleFrequencies[i] = rippleFrequency; rippleDensities[i] = rippleDensity; startedRippleDurations[i] = rippleDuration; rippleRadii[i] = rippleRadius; material.SetFloatArray("_RippleAmplitudes", rippleAmplitudes); material.SetFloatArray("_RippleFrequencies", rippleFrequencies); material.SetFloatArray("_RippleDensities", rippleDensities); material.SetFloatArray("_RippleAmplitudes", rippleAmplitudes); material.SetFloatArray("_RippleDurations", startedRippleDurations); material.SetFloatArray("_RippleRadii", rippleRadii); break; } } } private void ResetRippleShaderProperties() { Vector4[] rippleOrigins = new Vector4[maxRippleAmount]; float[] startedTimes = new float[maxRippleAmount]; float[] rippleAmplitudes = new float[maxRippleAmount]; float[] rippleFrequencies = new float[maxRippleAmount]; float[] rippleDensities = new float[maxRippleAmount]; float[] rippleDurations = new float[maxRippleAmount]; float[] rippleRadii = new float[maxRippleAmount]; // Initialize Ripple Shader Properties material.SetVectorArray("_RippleOrigins", rippleOrigins); material.SetFloatArray("_RippleStartTimes", startedTimes); material.SetFloatArray("_RippleAmplitudes", rippleAmplitudes); material.SetFloatArray("_RippleFrequencies", rippleFrequencies); material.SetFloatArray("_RippleDensities", rippleDensities); material.SetFloatArray("_RippleDurations", rippleDurations); material.SetFloatArray("_RippleRadii", rippleRadii); } }