Files
Ipseity-Demo/Assets/Scripts/DiapasonEquipmentManager.cs
T
2026-02-23 14:10:46 +01:00

368 lines
11 KiB
C#

using UnityEngine;
using UnityEngine.InputSystem;
using Unheimlich.Audio;
using System;
using System.Collections;
public class DiapasonEquipmentManager : MonoBehaviour
{
[Header("References")]
[SerializeField] private OctoIkArmsImproved _armsSystem;
[SerializeField] private GameObject _diapasonPrefab;
[SerializeField] private int _equipmentArmIndex = 1;
[Header("Detection Settings")]
[SerializeField] private LayerMask _soundEmitterLayer;
[SerializeField] private float _detectionRadius = 0.15f;
[SerializeField] private Transform[] _detectionPoints;
[Header("Visual Feedback")]
[SerializeField] private GameObject _contactFeedbackPrefab;
[Header("Diapason Animation")]
[SerializeField] private string _vibratingBoolParam = "IsVibrating";
[SerializeField] private string _tapTriggerParam = "Tap";
[Header("Tap Settings")]
[SerializeField] private AudioClip _tapSound;
[SerializeField] [Range(0f, 1f)] private float _tapVolume = 1f;
[SerializeField] private float _vibrationDuration = 15f;
public bool IsEquipped => _isEquipped;
public AudioListenable CurrentDetectedEmitter => _currentDetectedEmitter;
public bool CanTap => _isEquipped && _currentDetectedEmitter != null && !_isVibrating && !_currentDetectedEmitter.HasBeenTapped;
public event Action<AudioListenable> OnEmitterDetected;
public event Action<AudioListenable> OnEmitterLost;
private GameObject _spawnedDiapason;
private bool _isEquipped = false;
private AudioListenable _currentDetectedEmitter;
private GameObject _contactFeedback;
private bool _isVibrating = false;
private AudioSource _audioSource;
private Coroutine _vibrationCoroutine;
private Animator _diapasonAnimator;
private ParticleSystem _diapasonParticles;
void Awake()
{
if (_armsSystem == null)
{
_armsSystem = GetComponent<OctoIkArmsImproved>();
if (_armsSystem == null)
{
Debug.LogError("[DiapasonEquipment] OctoIkArmsImproved not found!");
}
}
_audioSource = GetComponent<AudioSource>();
if (_audioSource == null)
{
_audioSource = gameObject.AddComponent<AudioSource>();
}
}
void Update()
{
if (_isEquipped && _armsSystem.GetArmState(_equipmentArmIndex) == ArmState.Equipped)
{
CheckForSoundEmitters();
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame)
{
if (CanTap)
{
TapDiapason();
}
}
}
}
public void EquipDiapason()
{
if (_isEquipped)
{
Debug.LogWarning("[DiapasonEquipment] Diapason already equipped!");
return;
}
if (_diapasonPrefab == null)
{
Debug.LogError("[DiapasonEquipment] Diapason prefab not assigned!");
return;
}
_spawnedDiapason = Instantiate(_diapasonPrefab);
_spawnedDiapason.SetActive(true);
_diapasonAnimator = _spawnedDiapason.GetComponentInChildren<Animator>(true);
if (_diapasonAnimator == null)
{
Debug.LogWarning("[DiapasonEquipment] No Animator found on spawned diapason");
}
else
{
_diapasonAnimator.enabled = false;
}
_diapasonParticles = _spawnedDiapason.GetComponentInChildren<ParticleSystem>(true);
if (_diapasonParticles == null)
{
Debug.LogWarning("[DiapasonEquipment] No ParticleSystem found on spawned diapason");
}
_armsSystem.EquipObjectOnArm(_equipmentArmIndex, _spawnedDiapason, () => {
_isEquipped = true;
OnDiapasonEquipped();
});
}
public void UnequipDiapason()
{
if (!_isEquipped)
{
Debug.LogWarning("[DiapasonEquipment] Diapason not equipped!");
return;
}
if (_vibrationCoroutine != null)
{
StopCoroutine(_vibrationCoroutine);
_vibrationCoroutine = null;
}
if (_currentDetectedEmitter != null)
{
_currentDetectedEmitter.SetConcentrating(false);
_currentDetectedEmitter.StopListening(cancelConcentrationFade: false);
_currentDetectedEmitter = null;
}
_armsSystem.UnequipObjectFromArm(_equipmentArmIndex, () => {
_isEquipped = false;
_spawnedDiapason = null;
OnDiapasonUnequipped();
});
}
private void CheckForSoundEmitters()
{
if (_detectionPoints == null || _detectionPoints.Length == 0)
return;
AudioListenable closestEmitter = null;
float closestDistance = float.MaxValue;
foreach (Transform detectionPoint in _detectionPoints)
{
if (detectionPoint == null)
continue;
Collider[] hits = Physics.OverlapSphere(detectionPoint.position, _detectionRadius, _soundEmitterLayer);
foreach (Collider hit in hits)
{
AudioListenable emitter = hit.GetComponent<AudioListenable>();
if (emitter != null)
{
float distance = Vector3.Distance(detectionPoint.position, hit.transform.position);
if (distance < closestDistance)
{
closestDistance = distance;
closestEmitter = emitter;
}
}
}
}
if (closestEmitter != _currentDetectedEmitter)
{
if (_currentDetectedEmitter != null)
{
OnEmitterExited(_currentDetectedEmitter);
}
_currentDetectedEmitter = closestEmitter;
if (_currentDetectedEmitter != null)
{
OnEmitterEntered(_currentDetectedEmitter);
}
}
}
private void OnDiapasonEquipped()
{
if (_diapasonAnimator != null)
{
_diapasonAnimator.enabled = true;
_diapasonAnimator.SetBool(_vibratingBoolParam, false);
}
if (_diapasonParticles != null)
{
_diapasonParticles.Stop();
var emission = _diapasonParticles.emission;
emission.enabled = false;
}
}
private void OnDiapasonUnequipped()
{
_isVibrating = false;
_diapasonAnimator = null;
_diapasonParticles = null;
}
public void TapDiapason()
{
if (!CanTap)
{
Debug.LogWarning("[DiapasonEquipment] Cannot tap: not equipped, no contact, or already tapped");
return;
}
TapAnimationSettings tapSettings = null;
if (_spawnedDiapason != null)
{
EquippableTapSettings equippable = _spawnedDiapason.GetComponent<EquippableTapSettings>();
if (equippable != null)
{
tapSettings = equippable.TapSettings;
}
}
ArmEquipment equipment = _armsSystem.GetArmEquipment(_equipmentArmIndex);
if (equipment != null && tapSettings != null)
{
equipment.PlayTapAnimation(tapSettings);
equipment.StartShake(tapSettings);
}
if (_tapSound != null && _audioSource != null)
{
_audioSource.PlayOneShot(_tapSound, _tapVolume);
}
if (_diapasonAnimator != null)
{
_diapasonAnimator.SetTrigger(_tapTriggerParam);
_diapasonAnimator.SetBool(_vibratingBoolParam, true);
}
if (_diapasonParticles != null)
{
var emission = _diapasonParticles.emission;
emission.enabled = true;
_diapasonParticles.Play();
}
_isVibrating = true;
if (_currentDetectedEmitter != null)
{
_currentDetectedEmitter.StartListening(transform.position);
}
if (_vibrationCoroutine != null)
StopCoroutine(_vibrationCoroutine);
_vibrationCoroutine = StartCoroutine(StopVibrationAfterDuration());
}
private IEnumerator StopVibrationAfterDuration()
{
yield return new WaitForSeconds(_vibrationDuration);
if (_diapasonAnimator != null)
{
_diapasonAnimator.SetBool(_vibratingBoolParam, false);
}
if (_diapasonParticles != null)
{
_diapasonParticles.Stop();
var emission = _diapasonParticles.emission;
emission.enabled = false;
}
if (_currentDetectedEmitter != null)
{
_currentDetectedEmitter.StopListening();
}
ArmEquipment equipment = _armsSystem.GetArmEquipment(_equipmentArmIndex);
if (equipment != null)
{
equipment.StopShake();
}
_isVibrating = false;
_vibrationCoroutine = null;
}
private void OnEmitterEntered(AudioListenable emitter)
{
emitter.SetConcentrating(true);
if (_contactFeedbackPrefab != null && _contactFeedback == null)
{
_contactFeedback = Instantiate(_contactFeedbackPrefab, emitter.transform);
_contactFeedback.transform.localPosition = Vector3.zero;
}
OnEmitterDetected?.Invoke(emitter);
}
private void OnEmitterExited(AudioListenable emitter)
{
emitter.SetConcentrating(false);
if (!emitter.HasBeenTapped)
{
emitter.StopListening();
}
if (_contactFeedback != null)
{
Destroy(_contactFeedback);
_contactFeedback = null;
}
if (_diapasonAnimator != null)
{
_diapasonAnimator.SetBool(_vibratingBoolParam, false);
}
if (_diapasonParticles != null)
{
_diapasonParticles.Stop();
var emission = _diapasonParticles.emission;
emission.enabled = false;
}
_isVibrating = false;
OnEmitterLost?.Invoke(emitter);
}
void OnDrawGizmosSelected()
{
if (_detectionPoints == null || !_isEquipped)
return;
Gizmos.color = Color.yellow;
foreach (Transform detectionPoint in _detectionPoints)
{
if (detectionPoint != null)
{
Gizmos.DrawWireSphere(detectionPoint.position, _detectionRadius);
}
}
}
}