97ac0f71f5
https://assetstore.unity.com/packages/tools/generative-ai/synaptic-ai-pro-natural-language-control-for-unity-336030
268 lines
8.3 KiB
C#
268 lines
8.3 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
namespace SynapticPro
|
|
{
|
|
/// <summary>
|
|
/// Controller for Synaptic DissolvePro shader
|
|
/// Provides easy animation control and particle system integration
|
|
/// </summary>
|
|
[ExecuteAlways]
|
|
public class DissolveController : MonoBehaviour
|
|
{
|
|
[Header("Target")]
|
|
public Renderer targetRenderer;
|
|
public int materialIndex = 0;
|
|
|
|
[Header("Dissolve Settings")]
|
|
[Range(0f, 1f)]
|
|
public float dissolveAmount = 0f;
|
|
|
|
[Header("Direction")]
|
|
public DissolveDirection direction = DissolveDirection.Up;
|
|
public Vector3 customDirection = Vector3.up;
|
|
public Transform directionSource;
|
|
|
|
[Header("Animation")]
|
|
public float animationDuration = 2f;
|
|
public AnimationCurve dissolveCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
|
|
public bool autoReverse = false;
|
|
public float reverseDelay = 0.5f;
|
|
|
|
[Header("Particles")]
|
|
public ParticleSystem dissolveParticles;
|
|
public bool spawnParticlesOnEdge = true;
|
|
public float particleEmissionRate = 50f;
|
|
|
|
[Header("Audio")]
|
|
public AudioSource dissolveAudio;
|
|
public AudioClip dissolveSound;
|
|
|
|
[Header("Events")]
|
|
public UnityEngine.Events.UnityEvent onDissolveStart;
|
|
public UnityEngine.Events.UnityEvent onDissolveComplete;
|
|
public UnityEngine.Events.UnityEvent onAppearStart;
|
|
public UnityEngine.Events.UnityEvent onAppearComplete;
|
|
|
|
public enum DissolveDirection
|
|
{
|
|
Up,
|
|
Down,
|
|
Left,
|
|
Right,
|
|
Forward,
|
|
Back,
|
|
Spherical,
|
|
Custom
|
|
}
|
|
|
|
private Material material;
|
|
private Coroutine animationCoroutine;
|
|
private bool isAnimating = false;
|
|
|
|
// Shader property IDs
|
|
private static readonly int DissolveAmountID = Shader.PropertyToID("_DissolveAmount");
|
|
private static readonly int DissolveDirectionID = Shader.PropertyToID("_DissolveDirection");
|
|
private static readonly int DirectionalDissolveID = Shader.PropertyToID("_DirectionalDissolve");
|
|
|
|
private void OnEnable()
|
|
{
|
|
SetupMaterial();
|
|
}
|
|
|
|
private void SetupMaterial()
|
|
{
|
|
if (targetRenderer == null)
|
|
targetRenderer = GetComponent<Renderer>();
|
|
|
|
if (targetRenderer != null && targetRenderer.sharedMaterials.Length > materialIndex)
|
|
{
|
|
// Use instance material in play mode, shared in edit mode
|
|
if (Application.isPlaying)
|
|
{
|
|
material = targetRenderer.materials[materialIndex];
|
|
}
|
|
else
|
|
{
|
|
material = targetRenderer.sharedMaterials[materialIndex];
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (material == null)
|
|
return;
|
|
|
|
// Update dissolve amount
|
|
material.SetFloat(DissolveAmountID, dissolveAmount);
|
|
|
|
// Update direction
|
|
Vector3 dir = GetDissolveDirection();
|
|
material.SetVector(DissolveDirectionID, new Vector4(dir.x, dir.y, dir.z, 0));
|
|
material.SetFloat(DirectionalDissolveID, direction == DissolveDirection.Spherical ? 0f : 1f);
|
|
|
|
// Update particles
|
|
UpdateParticles();
|
|
}
|
|
|
|
private Vector3 GetDissolveDirection()
|
|
{
|
|
switch (direction)
|
|
{
|
|
case DissolveDirection.Up: return Vector3.up;
|
|
case DissolveDirection.Down: return Vector3.down;
|
|
case DissolveDirection.Left: return Vector3.left;
|
|
case DissolveDirection.Right: return Vector3.right;
|
|
case DissolveDirection.Forward: return Vector3.forward;
|
|
case DissolveDirection.Back: return Vector3.back;
|
|
case DissolveDirection.Spherical: return Vector3.zero;
|
|
case DissolveDirection.Custom:
|
|
if (directionSource != null)
|
|
return (directionSource.position - transform.position).normalized;
|
|
return customDirection.normalized;
|
|
default: return Vector3.up;
|
|
}
|
|
}
|
|
|
|
private void UpdateParticles()
|
|
{
|
|
if (dissolveParticles == null || !spawnParticlesOnEdge)
|
|
return;
|
|
|
|
var emission = dissolveParticles.emission;
|
|
|
|
// Only emit particles while dissolving is active and in progress
|
|
if (isAnimating && dissolveAmount > 0.01f && dissolveAmount < 0.99f)
|
|
{
|
|
emission.rateOverTime = particleEmissionRate;
|
|
|
|
// Position particles at dissolve edge (approximate)
|
|
Vector3 edgePosition = transform.position + GetDissolveDirection() * dissolveAmount * 2f;
|
|
dissolveParticles.transform.position = edgePosition;
|
|
}
|
|
else
|
|
{
|
|
emission.rateOverTime = 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Start dissolving the object
|
|
/// </summary>
|
|
public void Dissolve()
|
|
{
|
|
if (animationCoroutine != null)
|
|
StopCoroutine(animationCoroutine);
|
|
|
|
animationCoroutine = StartCoroutine(AnimateDissolve(0f, 1f, onDissolveStart, onDissolveComplete));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Make the object appear (reverse dissolve)
|
|
/// </summary>
|
|
public void Appear()
|
|
{
|
|
if (animationCoroutine != null)
|
|
StopCoroutine(animationCoroutine);
|
|
|
|
animationCoroutine = StartCoroutine(AnimateDissolve(1f, 0f, onAppearStart, onAppearComplete));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Toggle between dissolved and visible states
|
|
/// </summary>
|
|
public void Toggle()
|
|
{
|
|
if (dissolveAmount < 0.5f)
|
|
Dissolve();
|
|
else
|
|
Appear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set dissolve amount instantly
|
|
/// </summary>
|
|
public void SetDissolveInstant(float amount)
|
|
{
|
|
if (animationCoroutine != null)
|
|
StopCoroutine(animationCoroutine);
|
|
|
|
dissolveAmount = Mathf.Clamp01(amount);
|
|
isAnimating = false;
|
|
}
|
|
|
|
private IEnumerator AnimateDissolve(float from, float to,
|
|
UnityEngine.Events.UnityEvent onStart, UnityEngine.Events.UnityEvent onComplete)
|
|
{
|
|
isAnimating = true;
|
|
onStart?.Invoke();
|
|
|
|
// Play audio
|
|
if (dissolveAudio != null && dissolveSound != null)
|
|
{
|
|
dissolveAudio.clip = dissolveSound;
|
|
dissolveAudio.Play();
|
|
}
|
|
|
|
float elapsed = 0f;
|
|
dissolveAmount = from;
|
|
|
|
while (elapsed < animationDuration)
|
|
{
|
|
elapsed += Time.deltaTime;
|
|
float t = elapsed / animationDuration;
|
|
float curveT = dissolveCurve.Evaluate(t);
|
|
dissolveAmount = Mathf.Lerp(from, to, curveT);
|
|
yield return null;
|
|
}
|
|
|
|
dissolveAmount = to;
|
|
isAnimating = false;
|
|
onComplete?.Invoke();
|
|
|
|
// Auto reverse
|
|
if (autoReverse)
|
|
{
|
|
yield return new WaitForSeconds(reverseDelay);
|
|
|
|
if (to > 0.5f)
|
|
Appear();
|
|
else
|
|
Dissolve();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Trigger dissolve from damage or hit
|
|
/// </summary>
|
|
public void OnDamage(Vector3 hitPoint)
|
|
{
|
|
// Set direction from hit point
|
|
direction = DissolveDirection.Custom;
|
|
customDirection = (transform.position - hitPoint).normalized;
|
|
|
|
Dissolve();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private void OnValidate()
|
|
{
|
|
SetupMaterial();
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
// Draw dissolve direction
|
|
Gizmos.color = Color.cyan;
|
|
Vector3 dir = GetDissolveDirection();
|
|
if (dir.magnitude > 0.01f)
|
|
{
|
|
Gizmos.DrawRay(transform.position, dir * 2f);
|
|
Gizmos.DrawWireSphere(transform.position + dir * dissolveAmount * 2f, 0.1f);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|