358 lines
10 KiB
C#
358 lines
10 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;
|
|
}
|
|
|
|
ArmEquipment equipment = _armsSystem.GetArmEquipment(_equipmentArmIndex);
|
|
if (equipment != null)
|
|
{
|
|
equipment.PlayTapAnimation();
|
|
equipment.StartShake();
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|