您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

210 行
5.6 KiB

using System.Collections.Generic;
using UnityEngine;
using NonSerializedAttribute = System.NonSerializedAttribute;
namespace AxelF {
public abstract class Zone : MonoBehaviour {
public static readonly List<Zone> allZones = new List<Zone>();
public static bool dontProbeZones;
public static Collider FindTrigger(Zone z) {
var c = z.GetComponent<Collider>();
return (c != null && c.isTrigger) ? c : null;
}
static float GetTriggerRadius(Collider c) {
var e = c.bounds.extents;
return Mathf.Max(e.x, e.z);
}
#if UNITY_EDITOR
[System.Serializable]
public struct GizmoParams {
public Color activeColor;
public Color inactiveColor;
}
[Colorize]
public GizmoParams gizmo = new GizmoParams {
activeColor = Color.magenta,
inactiveColor = Color.blue
};
#endif
internal Zone parent;
internal List<Zone> children;
public float radius = 5f;
[Range(0, 1)]
public float parentExclusion;
internal float volumeExclusion;
internal float volumeInfluence;
internal int hash;
internal bool inited;
internal bool wantActive;
internal TernaryBool active;
protected Collider _trigger;
protected int _triggerRefs;
public bool isVolumeExcluded { get { return volumeExclusion > 0f; }}
public Collider trigger { get { return inited ? _trigger : FindTrigger(this); }}
#if UNITY_EDITOR
public bool IsActive() { return active == true; }
public Color GetGizmoColor() { return IsActive() ? gizmo.activeColor : gizmo.inactiveColor; }
#endif
protected void OnEnable() {
if (!inited)
OnInit();
allZones.Add(this);
OnUpdateActivation(wantActive);
}
protected virtual void OnInit() {
if ((_trigger = FindTrigger(this)) == null)
RegisterWithParentZone();
hash = (int) Synthesizer.GetNextHandle();
inited = true;
}
void RegisterWithParentZone() {
var z = FindParentZone();
if (z != null) {
if (z.children == null)
z.children = new List<Zone>(4);
z.children.Add(this);
parent = z;
}
}
public float GetRadius() {
var t = trigger;
return t ? GetTriggerRadius(t) : radius;
}
public Zone FindParentZone() {
return FindParentZoneRecursive(transform.parent);
}
Zone FindParentZoneRecursive(Transform t) {
if (t != null) {
var z = t.GetComponent<Zone>();
return (z != null) ? z : FindParentZoneRecursive(t.parent);
}
return null;
}
protected void OnDisable() {
allZones.Remove(this);
OnUpdateActivation(false);
_triggerRefs = 0;
}
protected void SetActive(bool state) {
wantActive = state;
}
protected bool OnUpdateActivation(bool state) {
if (active == state)
return false;
active = state;
if (children != null)
foreach (var i in children)
i.enabled = state;
return true;
}
protected virtual void OnProbe(Vector3 lpos, int thisFrame) {
}
protected virtual void OnUpdateEmitters() {
}
internal static void Update(int thisFrame) {
UpdateProbes(thisFrame);
UpdateActivation();
UpdateInfluence();
UpdateExclusion();
UpdateEmitters();
}
static void UpdateProbes(int thisFrame) {
if (!dontProbeZones) {
var l = Heartbeat.listenerTransform;
if (l) {
var lpos = l.position;
foreach (var z in allZones)
z.OnProbe(lpos, thisFrame);
}
}
}
static void UpdateActivation() {
_10:
foreach (var z in allZones)
if (z.OnUpdateActivation(z.wantActive))
goto _10;
}
static void UpdateInfluence() {
foreach (var z in allZones) {
// default is full influence and no exclusion
z.volumeExclusion = 0f;
z.volumeInfluence = z.active == true ? 1f : 0f;
// for active audio zones with peripheral fade, adjust the influence
AudioZone az;
if (z.active == true && (az = z as AudioZone) != null) {
float pfMin = az.peripheralFade.min;
float pfMax = az.peripheralFade.max;
if (pfMin < 1f) {
float x = az.sqrDistance / az.sqrRadius;
float y = 1f - Mathf.Clamp01((x - pfMin) / (pfMax - pfMin));
az.volumeInfluence = y * y;
}
}
}
}
static void UpdateExclusion() {
foreach (var z in allZones)
if (z.active == true && z.parent == null) {
float e;
UpdateExclusionDepthFirst(z, out e);
}
}
static void UpdateExclusionDepthFirst(Zone z, out float exclusion) {
// calculate max exclusion of all children
float e = 0f;
if (z.children != null)
foreach (var c in z.children) {
float f;
UpdateExclusionDepthFirst(c, out f);
e = Mathf.Max(e, f);
}
// keep track of our own exclusion
z.volumeExclusion = e;
// apply our own influence and exclusion and pass it up to parent
float k = e + 1f;
k *= z.volumeInfluence * z.parentExclusion + 1f;
exclusion = Mathf.Clamp01(k - 1f);
}
static void UpdateEmitters() {
foreach (var z in allZones)
z.OnUpdateEmitters();
}
}
} // AxelF