597 lines
16 KiB
C#
597 lines
16 KiB
C#
using System;
|
|
using UltimateWater.Internal;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UltimateWater
|
|
{
|
|
[RequireComponent(typeof(Water))]
|
|
[AddComponentMenu("Ultimate Water/Spray", 1)]
|
|
public sealed class Spray : MonoBehaviour, IOverlaysRenderer
|
|
{
|
|
public struct Particle
|
|
{
|
|
public Vector3 Position;
|
|
|
|
public Vector3 Velocity;
|
|
|
|
public Vector2 Lifetime;
|
|
|
|
public float Offset;
|
|
|
|
public float MaxIntensity;
|
|
|
|
public Particle(Vector3 position, Vector3 velocity, float lifetime, float offset, float maxIntensity)
|
|
{
|
|
Position = position;
|
|
Velocity = velocity;
|
|
Lifetime = new Vector2(lifetime, lifetime);
|
|
Offset = offset;
|
|
MaxIntensity = maxIntensity;
|
|
}
|
|
}
|
|
|
|
[HideInInspector]
|
|
[SerializeField]
|
|
[FormerlySerializedAs("sprayTiledGeneratorShader")]
|
|
private Shader _SprayTiledGeneratorShader;
|
|
|
|
[FormerlySerializedAs("sprayLocalGeneratorShader")]
|
|
[SerializeField]
|
|
[HideInInspector]
|
|
private Shader _SprayLocalGeneratorShader;
|
|
|
|
[FormerlySerializedAs("sprayToFoamShader")]
|
|
[SerializeField]
|
|
[HideInInspector]
|
|
private Shader _SprayToFoamShader;
|
|
|
|
[FormerlySerializedAs("sprayControllerShader")]
|
|
[SerializeField]
|
|
[HideInInspector]
|
|
private ComputeShader _SprayControllerShader;
|
|
|
|
[FormerlySerializedAs("sprayMaterial")]
|
|
[SerializeField]
|
|
private Material _SprayMaterial;
|
|
|
|
[FormerlySerializedAs("maxParticles")]
|
|
[SerializeField]
|
|
[Range(16f, 327675f)]
|
|
private int _MaxParticles = 65535;
|
|
|
|
[FormerlySerializedAs("sprayToFoam")]
|
|
[SerializeField]
|
|
private bool _SprayToFoam = true;
|
|
|
|
private float _SpawnThreshold = 1f;
|
|
|
|
private float _SpawnSkipRatio = 0.9f;
|
|
|
|
private float _Scale = 1f;
|
|
|
|
private Water _Water;
|
|
|
|
private WindWaves _WindWaves;
|
|
|
|
private DynamicWater _Overlays;
|
|
|
|
private Material _SprayTiledGeneratorMaterial;
|
|
|
|
private Material _SprayLocalGeneratorMaterial;
|
|
|
|
private Material _SprayToFoamMaterial;
|
|
|
|
private Transform _ProbeAnchor;
|
|
|
|
private RenderTexture _BlankOutput;
|
|
|
|
private Texture2D _BlankWhiteTex;
|
|
|
|
private ComputeBuffer _ParticlesA;
|
|
|
|
private ComputeBuffer _ParticlesB;
|
|
|
|
private ComputeBuffer _ParticlesInfo;
|
|
|
|
private ComputeBuffer _SpawnBuffer;
|
|
|
|
private int _Resolution;
|
|
|
|
private Mesh _Mesh;
|
|
|
|
private bool _Supported;
|
|
|
|
private bool _ResourcesReady;
|
|
|
|
private Vector2 _LastSurfaceOffset;
|
|
|
|
private readonly int[] _CountBuffer = new int[4];
|
|
|
|
private float _SkipRatioPrecomp;
|
|
|
|
private Particle[] _ParticlesToSpawn = new Particle[10];
|
|
|
|
private int _NumParticlesToSpawn;
|
|
|
|
private MaterialPropertyBlock[] _PropertyBlocks;
|
|
|
|
public int MaxParticles
|
|
{
|
|
get
|
|
{
|
|
return _MaxParticles;
|
|
}
|
|
}
|
|
|
|
public int SpawnedParticles
|
|
{
|
|
get
|
|
{
|
|
if (_ParticlesA != null)
|
|
{
|
|
ComputeBuffer.CopyCount(_ParticlesA, _ParticlesInfo, 0);
|
|
_ParticlesInfo.GetData(_CountBuffer);
|
|
return _CountBuffer[0];
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public ComputeBuffer ParticlesBuffer
|
|
{
|
|
get
|
|
{
|
|
return _ParticlesA;
|
|
}
|
|
}
|
|
|
|
public void SpawnCustomParticle(Particle particle)
|
|
{
|
|
if (base.enabled)
|
|
{
|
|
if (_ParticlesToSpawn.Length <= _NumParticlesToSpawn)
|
|
{
|
|
Array.Resize(ref _ParticlesToSpawn, _ParticlesToSpawn.Length << 1);
|
|
}
|
|
_ParticlesToSpawn[_NumParticlesToSpawn] = particle;
|
|
_NumParticlesToSpawn++;
|
|
}
|
|
}
|
|
|
|
public void SpawnCustomParticles(Particle[] particles, int numParticles)
|
|
{
|
|
if (!base.enabled)
|
|
{
|
|
return;
|
|
}
|
|
CheckResources();
|
|
if (_SpawnBuffer == null || _SpawnBuffer.count < particles.Length)
|
|
{
|
|
if (_SpawnBuffer != null)
|
|
{
|
|
_SpawnBuffer.Release();
|
|
}
|
|
_SpawnBuffer = new ComputeBuffer(particles.Length, 40);
|
|
}
|
|
_SpawnBuffer.SetData(particles);
|
|
_SprayControllerShader.SetFloat("particleCount", numParticles);
|
|
_SprayControllerShader.SetBuffer(2, "SourceParticles", _SpawnBuffer);
|
|
_SprayControllerShader.SetBuffer(2, "TargetParticles", _ParticlesA);
|
|
_SprayControllerShader.Dispatch(2, 1, 1, 1);
|
|
}
|
|
|
|
public void RenderOverlays(DynamicWaterCameraData overlays)
|
|
{
|
|
}
|
|
|
|
public void RenderFoam(DynamicWaterCameraData overlays)
|
|
{
|
|
if (base.enabled)
|
|
{
|
|
CheckResources();
|
|
if (_SprayToFoam)
|
|
{
|
|
GenerateLocalFoam(overlays);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
_Water = GetComponent<Water>();
|
|
_WindWaves = _Water.WindWaves;
|
|
_Overlays = _Water.DynamicWater;
|
|
_WindWaves.ResolutionChanged.AddListener(OnResolutionChanged);
|
|
_Supported = CheckSupport();
|
|
_LastSurfaceOffset = _Water.SurfaceOffset;
|
|
if (!_Supported)
|
|
{
|
|
base.enabled = false;
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
_Water = GetComponent<Water>();
|
|
_Water.ProfilesManager.Changed.AddListener(OnProfilesChanged);
|
|
OnProfilesChanged(_Water);
|
|
Camera.onPreCull = (Camera.CameraCallback)Delegate.Remove(Camera.onPreCull, new Camera.CameraCallback(OnSomeCameraPreCull));
|
|
Camera.onPreCull = (Camera.CameraCallback)Delegate.Combine(Camera.onPreCull, new Camera.CameraCallback(OnSomeCameraPreCull));
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (_Water != null)
|
|
{
|
|
_Water.ProfilesManager.Changed.RemoveListener(OnProfilesChanged);
|
|
}
|
|
Camera.onPreCull = (Camera.CameraCallback)Delegate.Remove(Camera.onPreCull, new Camera.CameraCallback(OnSomeCameraPreCull));
|
|
Dispose();
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (Time.frameCount >= 10)
|
|
{
|
|
if (!_ResourcesReady)
|
|
{
|
|
CheckResources();
|
|
}
|
|
SwapParticleBuffers();
|
|
ClearParticles();
|
|
UpdateParticles();
|
|
if (Camera.main != null)
|
|
{
|
|
SpawnWindWavesParticlesTiled(Camera.main.transform);
|
|
}
|
|
if (_NumParticlesToSpawn != 0)
|
|
{
|
|
SpawnCustomParticles(_ParticlesToSpawn, _NumParticlesToSpawn);
|
|
_NumParticlesToSpawn = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnValidate()
|
|
{
|
|
_MaxParticles = Mathf.RoundToInt((float)_MaxParticles / 65535f) * 65535;
|
|
if (_SprayTiledGeneratorShader == null)
|
|
{
|
|
_SprayTiledGeneratorShader = Shader.Find("UltimateWater/Spray/Generator (Tiles)");
|
|
}
|
|
if (_SprayLocalGeneratorShader == null)
|
|
{
|
|
_SprayLocalGeneratorShader = Shader.Find("UltimateWater/Spray/Generator (Local)");
|
|
}
|
|
if (_SprayToFoamShader == null)
|
|
{
|
|
_SprayToFoamShader = Shader.Find("UltimateWater/Spray/Spray To Foam");
|
|
}
|
|
UpdatePrecomputedParams();
|
|
}
|
|
|
|
private void OnSomeCameraPreCull(Camera cameraComponent)
|
|
{
|
|
if (!_ResourcesReady)
|
|
{
|
|
return;
|
|
}
|
|
WaterCamera waterCamera = WaterCamera.GetWaterCamera(cameraComponent);
|
|
if (waterCamera != null && waterCamera.Type == WaterCamera.CameraType.Normal)
|
|
{
|
|
_SprayMaterial.SetBuffer("_Particles", _ParticlesA);
|
|
_SprayMaterial.SetVector("_CameraUp", cameraComponent.transform.up);
|
|
_SprayMaterial.SetVector("_WrapSubsurfaceScatteringPack", _Water.Renderer.PropertyBlock.GetVector("_WrapSubsurfaceScatteringPack"));
|
|
_SprayMaterial.SetFloat("_UniformWaterScale", _Water.UniformWaterScale);
|
|
if (_ProbeAnchor == null)
|
|
{
|
|
GameObject gameObject = new GameObject("Spray Probe Anchor");
|
|
gameObject.hideFlags = HideFlags.HideAndDontSave;
|
|
GameObject gameObject2 = gameObject;
|
|
_ProbeAnchor = gameObject2.transform;
|
|
}
|
|
_ProbeAnchor.position = cameraComponent.transform.position;
|
|
int num = _PropertyBlocks.Length;
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
Graphics.DrawMesh(_Mesh, Matrix4x4.identity, _SprayMaterial, 0, cameraComponent, 0, _PropertyBlocks[i], ShadowCastingMode.Off, false, _ProbeAnchor);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SpawnWindWavesParticlesTiled(Transform origin)
|
|
{
|
|
Vector3 position = origin.position;
|
|
float num = 400f / (float)_BlankOutput.width;
|
|
_SprayTiledGeneratorMaterial.CopyPropertiesFromMaterial(_Water.Materials.SurfaceMaterial);
|
|
_SprayTiledGeneratorMaterial.SetVector("_SurfaceOffset", new Vector3(_Water.SurfaceOffset.x, _Water.transform.position.y, _Water.SurfaceOffset.y));
|
|
_SprayTiledGeneratorMaterial.SetVector("_Params", new Vector4(_SpawnThreshold * 0.25835f, _SkipRatioPrecomp, 0f, _Scale * 0.455f));
|
|
_SprayTiledGeneratorMaterial.SetVector("_Coordinates", new Vector4(position.x - 200f + UnityEngine.Random.value * num, position.z - 200f + UnityEngine.Random.value * num, 400f, 400f));
|
|
if (_Overlays == null)
|
|
{
|
|
_SprayTiledGeneratorMaterial.SetTexture("_LocalNormalMap", GetBlankWhiteTex());
|
|
}
|
|
Graphics.SetRandomWriteTarget(1, _ParticlesA);
|
|
GraphicsUtilities.Blit(null, _BlankOutput, _SprayTiledGeneratorMaterial, 0, _Water.Renderer.PropertyBlock);
|
|
Graphics.ClearRandomWriteTargets();
|
|
}
|
|
|
|
private void GenerateLocalFoam(DynamicWaterCameraData data)
|
|
{
|
|
RenderTexture temporary = RenderTexture.GetTemporary(512, 512, 0, RenderTextureFormat.RHalf, RenderTextureReadWrite.Linear);
|
|
Graphics.SetRenderTarget(temporary);
|
|
GL.Clear(false, true, new Color(0f, 0f, 0f, 0f));
|
|
_SprayToFoamMaterial.SetBuffer("_Particles", _ParticlesA);
|
|
_SprayToFoamMaterial.SetVector("_LocalMapsCoords", data.Camera.LocalMapsShaderCoords);
|
|
_SprayToFoamMaterial.SetFloat("_UniformWaterScale", 50f * _Water.UniformWaterScale / data.Camera.LocalMapsRect.width);
|
|
Vector4 vector = _SprayMaterial.GetVector("_ParticleParams");
|
|
vector.x *= 8f;
|
|
vector.z = 1f;
|
|
_SprayToFoamMaterial.SetVector("_ParticleParams", vector);
|
|
int num = _PropertyBlocks.Length;
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
_SprayToFoamMaterial.SetFloat("_ParticleOffset", i * 65535);
|
|
if (_SprayToFoamMaterial.SetPass(0))
|
|
{
|
|
Graphics.DrawMeshNow(_Mesh, Matrix4x4.identity, 0);
|
|
}
|
|
}
|
|
Camera planeProjectorCamera = data.Camera.PlaneProjectorCamera;
|
|
Rect localMapsRect = data.Camera.LocalMapsRect;
|
|
Vector2 center = localMapsRect.center;
|
|
float num2 = localMapsRect.width * 0.5f;
|
|
Matrix4x4 matrix = new Matrix4x4
|
|
{
|
|
m03 = center.x,
|
|
m13 = _Water.transform.position.y,
|
|
m23 = center.y,
|
|
m00 = num2,
|
|
m11 = num2,
|
|
m22 = num2,
|
|
m33 = 1f
|
|
};
|
|
GL.PushMatrix();
|
|
GL.modelview = planeProjectorCamera.worldToCameraMatrix;
|
|
GL.LoadProjectionMatrix(planeProjectorCamera.projectionMatrix);
|
|
Graphics.SetRenderTarget(data.FoamMap);
|
|
_SprayToFoamMaterial.mainTexture = temporary;
|
|
if (_SprayToFoamMaterial.SetPass(1))
|
|
{
|
|
Graphics.DrawMeshNow(Quads.BipolarXZ, matrix, 0);
|
|
}
|
|
GL.PopMatrix();
|
|
RenderTexture.ReleaseTemporary(temporary);
|
|
}
|
|
|
|
private void UpdateParticles()
|
|
{
|
|
Vector2 vector = _WindWaves.WindSpeed * 0.0008f;
|
|
Vector3 gravity = Physics.gravity;
|
|
float deltaTime = Time.deltaTime;
|
|
if (_Overlays != null)
|
|
{
|
|
DynamicWaterCameraData cameraOverlaysData = _Overlays.GetCameraOverlaysData(Camera.main, false);
|
|
if (cameraOverlaysData != null)
|
|
{
|
|
_SprayControllerShader.SetTexture(0, "TotalDisplacementMap", cameraOverlaysData.TotalDisplacementMap);
|
|
WaterCamera waterCamera = WaterCamera.GetWaterCamera(Camera.main);
|
|
if (waterCamera != null)
|
|
{
|
|
_SprayControllerShader.SetVector("localMapsCoords", waterCamera.LocalMapsShaderCoords);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_SprayControllerShader.SetTexture(0, "TotalDisplacementMap", GetBlankWhiteTex());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_SprayControllerShader.SetTexture(0, "TotalDisplacementMap", GetBlankWhiteTex());
|
|
}
|
|
Vector2 surfaceOffset = _Water.SurfaceOffset;
|
|
_SprayControllerShader.SetVector("deltaTime", new Vector4(deltaTime, 1f - deltaTime * 0.2f, 0f, 0f));
|
|
_SprayControllerShader.SetVector("externalForces", new Vector3((vector.x + gravity.x) * deltaTime, gravity.y * deltaTime, (vector.y + gravity.z) * deltaTime));
|
|
_SprayControllerShader.SetVector("surfaceOffsetDelta", new Vector3(_LastSurfaceOffset.x - surfaceOffset.x, 0f, _LastSurfaceOffset.y - surfaceOffset.y));
|
|
_SprayControllerShader.SetFloat("surfaceOffsetY", base.transform.position.y);
|
|
_SprayControllerShader.SetVector("waterTileSizesInv", _WindWaves.TileSizesInv);
|
|
_SprayControllerShader.SetBuffer(0, "SourceParticles", _ParticlesB);
|
|
_SprayControllerShader.SetBuffer(0, "TargetParticles", _ParticlesA);
|
|
_SprayControllerShader.Dispatch(0, _MaxParticles / 256, 1, 1);
|
|
_LastSurfaceOffset = surfaceOffset;
|
|
}
|
|
|
|
private Texture2D GetBlankWhiteTex()
|
|
{
|
|
if (_BlankWhiteTex == null)
|
|
{
|
|
_BlankWhiteTex = new Texture2D(2, 2, TextureFormat.ARGB32, false, true);
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
_BlankWhiteTex.SetPixel(i, j, new Color(1f, 1f, 1f, 1f));
|
|
}
|
|
}
|
|
_BlankWhiteTex.Apply(false, true);
|
|
}
|
|
return _BlankWhiteTex;
|
|
}
|
|
|
|
private void ClearParticles()
|
|
{
|
|
_SprayControllerShader.SetBuffer(1, "TargetParticlesFlat", _ParticlesA);
|
|
_SprayControllerShader.Dispatch(1, _MaxParticles / 256, 1, 1);
|
|
}
|
|
|
|
private void SwapParticleBuffers()
|
|
{
|
|
ComputeBuffer particlesB = _ParticlesB;
|
|
_ParticlesB = _ParticlesA;
|
|
_ParticlesA = particlesB;
|
|
}
|
|
|
|
private void OnResolutionChanged(WindWaves windWaves)
|
|
{
|
|
if (_BlankOutput != null)
|
|
{
|
|
UnityEngine.Object.Destroy(_BlankOutput);
|
|
_BlankOutput = null;
|
|
}
|
|
_ResourcesReady = false;
|
|
}
|
|
|
|
private void OnProfilesChanged(Water water)
|
|
{
|
|
Water.WeightedProfile[] profiles = water.ProfilesManager.Profiles;
|
|
_SpawnThreshold = 0f;
|
|
_SpawnSkipRatio = 0f;
|
|
_Scale = 0f;
|
|
if (profiles != null)
|
|
{
|
|
for (int i = 0; i < profiles.Length; i++)
|
|
{
|
|
Water.WeightedProfile weightedProfile = profiles[i];
|
|
WaterProfileData profile = weightedProfile.Profile;
|
|
float weight = weightedProfile.Weight;
|
|
_SpawnThreshold += profile.SprayThreshold * weight;
|
|
_SpawnSkipRatio += profile.SpraySkipRatio * weight;
|
|
_Scale += profile.SpraySize * weight;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdatePrecomputedParams()
|
|
{
|
|
if (_Water != null)
|
|
{
|
|
_Resolution = _WindWaves.FinalResolution;
|
|
}
|
|
_SkipRatioPrecomp = Mathf.Pow(_SpawnSkipRatio, 1024f / (float)_Resolution);
|
|
}
|
|
|
|
private bool CheckSupport()
|
|
{
|
|
return SystemInfo.supportsComputeShaders && _SprayTiledGeneratorShader != null && _SprayTiledGeneratorShader.isSupported;
|
|
}
|
|
|
|
private void CheckResources()
|
|
{
|
|
if (_SprayTiledGeneratorMaterial == null)
|
|
{
|
|
_SprayTiledGeneratorMaterial = new Material(_SprayTiledGeneratorShader)
|
|
{
|
|
hideFlags = HideFlags.DontSave
|
|
};
|
|
}
|
|
if (_SprayLocalGeneratorMaterial == null)
|
|
{
|
|
_SprayLocalGeneratorMaterial = new Material(_SprayLocalGeneratorShader)
|
|
{
|
|
hideFlags = HideFlags.DontSave
|
|
};
|
|
}
|
|
if (_SprayToFoamMaterial == null)
|
|
{
|
|
_SprayToFoamMaterial = new Material(_SprayToFoamShader)
|
|
{
|
|
hideFlags = HideFlags.DontSave
|
|
};
|
|
}
|
|
if (_BlankOutput == null)
|
|
{
|
|
UpdatePrecomputedParams();
|
|
_BlankOutput = new RenderTexture(_Resolution, _Resolution, 0, SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.R8) ? RenderTextureFormat.R8 : RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear)
|
|
{
|
|
name = "[UWS] Spray - WaterSpray Blank Output Texture",
|
|
filterMode = FilterMode.Point
|
|
};
|
|
_BlankOutput.Create();
|
|
}
|
|
if (_Mesh == null)
|
|
{
|
|
int num = Mathf.Min(_MaxParticles, 65535);
|
|
_Mesh = new Mesh
|
|
{
|
|
name = "Spray",
|
|
hideFlags = HideFlags.DontSave,
|
|
vertices = new Vector3[num]
|
|
};
|
|
int[] array = new int[num];
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
array[i] = i;
|
|
}
|
|
_Mesh.SetIndices(array, MeshTopology.Points, 0);
|
|
_Mesh.bounds = new Bounds(Vector3.zero, new Vector3(10000000f, 10000000f, 10000000f));
|
|
}
|
|
if (_PropertyBlocks == null)
|
|
{
|
|
int num2 = Mathf.CeilToInt((float)_MaxParticles / 65535f);
|
|
_PropertyBlocks = new MaterialPropertyBlock[num2];
|
|
for (int j = 0; j < num2; j++)
|
|
{
|
|
(_PropertyBlocks[j] = new MaterialPropertyBlock()).SetFloat("_ParticleOffset", j * 65535);
|
|
}
|
|
}
|
|
if (_ParticlesA == null)
|
|
{
|
|
_ParticlesA = new ComputeBuffer(_MaxParticles, 40, ComputeBufferType.Append);
|
|
}
|
|
if (_ParticlesB == null)
|
|
{
|
|
_ParticlesB = new ComputeBuffer(_MaxParticles, 40, ComputeBufferType.Append);
|
|
}
|
|
if (_ParticlesInfo == null)
|
|
{
|
|
_ParticlesInfo = new ComputeBuffer(1, 16, ComputeBufferType.IndirectArguments);
|
|
_ParticlesInfo.SetData(new int[4] { 0, 1, 0, 0 });
|
|
}
|
|
_ResourcesReady = true;
|
|
}
|
|
|
|
private void Dispose()
|
|
{
|
|
if (_BlankOutput != null)
|
|
{
|
|
UnityEngine.Object.Destroy(_BlankOutput);
|
|
_BlankOutput = null;
|
|
}
|
|
if (_ParticlesA != null)
|
|
{
|
|
_ParticlesA.Dispose();
|
|
_ParticlesA = null;
|
|
}
|
|
if (_ParticlesB != null)
|
|
{
|
|
_ParticlesB.Dispose();
|
|
_ParticlesB = null;
|
|
}
|
|
if (_ParticlesInfo != null)
|
|
{
|
|
_ParticlesInfo.Release();
|
|
_ParticlesInfo = null;
|
|
}
|
|
if (_Mesh != null)
|
|
{
|
|
UnityEngine.Object.Destroy(_Mesh);
|
|
_Mesh = null;
|
|
}
|
|
if (_ProbeAnchor != null)
|
|
{
|
|
UnityEngine.Object.Destroy(_ProbeAnchor.gameObject);
|
|
_ProbeAnchor = null;
|
|
}
|
|
if (_SpawnBuffer != null)
|
|
{
|
|
_SpawnBuffer.Release();
|
|
_SpawnBuffer = null;
|
|
}
|
|
_ResourcesReady = false;
|
|
}
|
|
}
|
|
}
|