Files
Fishing2/Assets/Obi/Scripts/Common/Utils/Forces/ObiForceZone.cs
2025-11-10 00:08:26 +08:00

138 lines
4.1 KiB
C#

using UnityEngine;
namespace Obi
{
[ExecuteInEditMode]
[RequireComponent(typeof(ObiCollider))]
public class ObiForceZone : MonoBehaviour
{
[SerializeProperty("sourceCollider")]
[SerializeField] private ObiCollider m_SourceCollider;
protected ObiForceZoneHandle forcezoneHandle;
/// <summary>
/// The ObiCollider this ObiForceZone should affect.
/// </summary>
/// 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<ObiCollider>();
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;
}
}
}