using UnityEngine; namespace Obi { [ExecuteInEditMode] [RequireComponent(typeof(ObiCollider))] public class ObiForceZone : MonoBehaviour { [SerializeProperty("sourceCollider")] [SerializeField] private ObiCollider m_SourceCollider; protected ObiForceZoneHandle forcezoneHandle; /// /// The ObiCollider this ObiForceZone should affect. /// /// This is automatically set when you first create the ObiForceZone component, but you can override it afterwards. public ObiCollider SourceCollider { set { if (value != null && value.gameObject != this.gameObject) { Debug.LogError("The ObiCollider component must reside in the same GameObject as ObiForceZone."); return; } RemoveCollider(); m_SourceCollider = value; AddCollider(); } get { return m_SourceCollider; } } public ObiForceZoneHandle Handle { get { // don't check forcezoneHandle.isValid: // CreateForceZone may defer creation, so we get a non-null, but invalid handle. // If calling handle again right away before it becomes valid, it will call CreateForceZone again and create a second handle to the same zone. if (forcezoneHandle == null) { var world = ObiColliderWorld.GetInstance(); // create the material: forcezoneHandle = world.CreateForceZone(); forcezoneHandle.owner = this; } return forcezoneHandle; } } public ForceZone.ZoneType type; public ForceZone.ForceMode mode; public float intensity; [Header("Damping")] public ForceZone.DampingDirection dampingDir; public float damping = 0; [Header("Falloff")] public float minDistance; public float maxDistance; [Min(0)] public float falloffPower = 1; [Header("Tint")] public Color color = Color.clear; [Header("Pulse")] public float pulseIntensity; public float pulseFrequency; public float pulseSeed; protected float intensityVariation; public void OnEnable() { forcezoneHandle = ObiColliderWorld.GetInstance().CreateForceZone(); forcezoneHandle.owner = this; FindSourceCollider(); } public void OnDisable() { RemoveCollider(); ObiColliderWorld.GetInstance().DestroyForceZone(forcezoneHandle); } private void FindSourceCollider() { if (SourceCollider == null) SourceCollider = GetComponent(); else AddCollider(); } private void AddCollider() { if (m_SourceCollider != null) m_SourceCollider.ForceZone = this; } private void RemoveCollider() { if (m_SourceCollider != null) m_SourceCollider.ForceZone = null; } public virtual void UpdateIfNeeded() { if (!Handle.isValid) return; var fc = ObiColliderWorld.GetInstance().forceZones[Handle.index]; fc.type = type; fc.mode = mode; fc.intensity = intensity + intensityVariation; fc.minDistance = minDistance; fc.maxDistance = maxDistance; fc.falloffPower = falloffPower; fc.damping = damping; fc.dampingDir = dampingDir; fc.color = color; ObiColliderWorld.GetInstance().forceZones[Handle.index] = fc; } public void Update() { if (Application.isPlaying) intensityVariation = Mathf.PerlinNoise(Time.time * pulseFrequency, pulseSeed) * pulseIntensity; } } }