using UnityEngine; using Obi; [RequireComponent(typeof(ObiRope))] public class HosePump : MonoBehaviour { [Header("Bulge controls")] public float pumpSpeed = 5; public float bulgeFrequency = 3; public float baseThickness = 0.04f; public float bulgeThickness = 0.06f; public Color bulgeColor = Color.cyan; [Header("Flow controls")] public ParticleSystem waterEmitter; public float flowSpeedMin = 0.5f; public float flowSpeedMax = 7; public float minEmitRate = 100; public float maxEmitRate = 1000; private ObiRope rope; public ObiPathSmoother smoother; private float time = 0; void OnEnable() { rope = GetComponent(); smoother = GetComponent(); rope.OnSimulationStart += Rope_OnBeginStep; } void OnDisable() { rope.OnSimulationStart -= Rope_OnBeginStep; } private void Rope_OnBeginStep(ObiActor actor, float stepTime, float substepTime) { time += stepTime * pumpSpeed; float distance = 0; float sine = 0; // iterate over all particles, changing their radius and color based on a sine wave: // (note this would not support resizable / cuttable ropes, to add support for that use rope.elements instead) for (int i = 0; i < rope.solverIndices.count; ++i) { int solverIndex = rope.solverIndices[i]; if (i > 0) { int previousIndex = rope.solverIndices[i - 1]; distance += Vector3.Distance(rope.solver.positions[solverIndex],rope.solver.positions[previousIndex]); } sine = Mathf.Max(0, Mathf.Sin(distance * bulgeFrequency - time)); rope.solver.principalRadii[solverIndex] = Vector3.one * Mathf.Lerp(baseThickness,bulgeThickness, sine); rope.solver.colors[solverIndex] = Color.Lerp(Color.white, bulgeColor, sine); } // change particle emission rate/speed based on sine wave at the last particle: if (waterEmitter != null) { var main = waterEmitter.main; main.startSpeed = Mathf.Lerp(flowSpeedMin,flowSpeedMax,sine); var emission = waterEmitter.emission; emission.rateOverTime = Mathf.Lerp(minEmitRate, maxEmitRate, sine); } } public void LateUpdate() { if (smoother != null && waterEmitter != null) { ObiPathFrame section = smoother.GetSectionAt(1); waterEmitter.transform.position = rope.solver.transform.TransformPoint(section.position); waterEmitter.transform.rotation = rope.solver.transform.rotation * (Quaternion.LookRotation(section.tangent, section.binormal)); } } }