Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using System.Threading;
- using UnityEngine;
- public class TowerAI : MonoBehaviour
- {
- public bool IsAggressive = true;
- public float IdleRotationSpeed = 20f;
- public float AttackRotationSpeed = 50f;
- public float ViewDistance = 10f;
- public float ViewAngle = 45f;
- public int RaysNumber = 12;
- public GameObject Target;
- public GameObject BulletType;
- public float ProjectileSpeed = 10f;
- public GameObject BGMSource;
- public float AggressionResetTime = 3f;
- public float TargetLoadTime = .6f;
- public float ReloadTime = 2f;
- public float TargettingTime = 5f;
- private Vector3 _rayOrigin;
- private bool _targetVisible = false;
- private float _targetLoadingTimer = 0f;
- private float _targettingTimer = 0f;
- private float _reloadTimer = 0f;
- private float _aggressionResetTimer = 0f;
- private bool _isLoadingTarget = false;
- private bool _isReloading = false;
- private bool _isTargetting = false;
- private bool _isLookingForTarget = false;
- private bool _canShoot = false;
- private LineRenderer _targetRay;
- private AudioClip _laserClip;
- private AudioClip _firingClip;
- private AudioSource _sfxSource;
- private IEnumerator _bgmFadeCoroutine;
- // Start is called before the first frame update
- void Start()
- {
- _laserClip = Resources.Load<AudioClip>("Sounds/LaserCharge");
- _firingClip = Resources.Load<AudioClip>("Sounds/GuardianFiring");
- _sfxSource = GetComponentInChildren<AudioSource>();
- _targetRay = transform.Find("GunPivot").Find("RayOrigin").GetComponentInChildren<LineRenderer>();
- }
- void SetRayOrigin()
- {
- try
- {
- _rayOrigin = this.gameObject.transform.Find("GunPivot").Find("RayOrigin").gameObject.transform.position;
- }
- catch (System.Exception e)
- {
- _rayOrigin = this.gameObject.transform.position;
- }
- }
- // Update is called once per frame
- void Update()
- {
- // Ho cercato di simulare il comportamento dei guardiani di Breath of the Wild. Questo è il massimo che riesca a fare senza spenderci più di mezza giornata.
- // IDLE BEHAVIOUR: Rotate the tower around its Y axis
- if (!_targetVisible && !_isLookingForTarget)
- {
- transform.RotateAround(transform.position, Vector3.up, IdleRotationSpeed * Time.deltaTime);
- SetRayOrigin();
- }
- // Check if target is visible to the tower by shooting many rays in an area
- RaycastHit hit;
- Ray[] rays = new Ray[RaysNumber];
- float angleStep = ViewAngle / (RaysNumber - 1);
- bool found = false;
- for (int i = 0; i < RaysNumber; i++)
- {
- rays[i] = new Ray(_rayOrigin, Quaternion.Euler(0, -ViewAngle / 2 + angleStep * i, 0) * transform.forward);
- Debug.DrawRay(rays[i].origin, rays[i].direction * ViewDistance, Color.red);
- LayerMask mask = LayerMask.GetMask(LayerMask.LayerToName(2));
- if (Physics.Raycast(rays[i], out hit, ViewDistance, ~mask))
- {
- if (IsAggressive && hit.collider.gameObject == Target)
- {
- found = true;
- //Debug.Log("Target is visible");
- }
- }
- }
- // If at least one ray hits the target, the target is visible
- if (found)
- {
- if (!_targetVisible) // Runs when the target is first found
- {
- if (_bgmFadeCoroutine != null) StopCoroutine(_bgmFadeCoroutine);
- if (!BGMSource.GetComponent<AudioSource>().isPlaying)
- {
- BGMSource.GetComponent<AudioSource>().Play(0);
- BGMSource.GetComponent<AudioSource>().mute = false;
- BGMSource.GetComponent<AudioSource>().volume = 1;
- }
- _targetLoadingTimer = TargetLoadTime;
- _isLoadingTarget = true;
- }
- else _aggressionResetTimer = 0;
- // Target has been found
- _targetVisible = true;
- }
- else
- {
- // Target has not been found
- if (_targetVisible)
- {
- // Target was visible but isn't anymore. Start a timer to reset aggro.
- _aggressionResetTimer = AggressionResetTime;
- _isLookingForTarget = true;
- }
- _targetVisible = false;
- }
- // Wait for some time before starting the targetting process
- if (_targetLoadingTimer > 0)
- {
- _targetLoadingTimer -= Time.deltaTime;
- if (_targetLoadingTimer <= 0)
- {
- _isLoadingTarget = false;
- if (_targetVisible)
- {
- _sfxSource.clip = _laserClip;
- _sfxSource.Play();
- _isTargetting = true;
- _targettingTimer = TargettingTime;
- }
- }
- }
- // Targetting process
- if (_targettingTimer > 0)
- {
- _targettingTimer -= Time.deltaTime;
- if (_targettingTimer < TargettingTime / 2)
- {
- _sfxSource.pitch = 2;
- }
- if (_targettingTimer <= 0)
- {
- _isTargetting = false;
- _sfxSource.pitch = 1;
- _sfxSource.Stop();
- if (_targetVisible)
- {
- _canShoot = true;
- }
- }
- }
- // AGGRESSIVE BEHAVIOUR: Point the tower towards the target and shoot
- if (IsAggressive && Target != null)
- {
- if (_targetVisible)
- {
- // Smoothly rotate towards the target when found
- Vector3 direction = (Target.transform.position - transform.position).normalized;
- Quaternion lookRotation = Quaternion.LookRotation(direction);
- Quaternion rot = Quaternion.Slerp(transform.rotation, lookRotation, AttackRotationSpeed / 20 * Time.deltaTime);
- rot.x = 0;
- rot.z = 0;
- transform.rotation = rot;
- SetRayOrigin();
- // Show targetting ray during the targetting process
- if (_isTargetting) _targetRay.SetPosition(1, transform.InverseTransformPoint(Target.transform.position));
- if (_canShoot && BulletType != null)
- {
- _sfxSource.clip = _firingClip;
- _sfxSource.Play();
- _canShoot = false;
- // Instantiate a new bullet and shoot it towards the player
- GameObject bullet = GameObject.Instantiate(BulletType);
- bullet.transform.forward = transform.forward;
- bullet.transform.position = _rayOrigin;
- bullet.GetComponent<Rigidbody>().velocity = direction * ProjectileSpeed;
- _reloadTimer = ReloadTime;
- _isReloading = true;
- }
- }
- if(!_isTargetting) _targetRay.SetPosition(1, _targetRay.GetPosition(0));
- }
- // Reload process
- if (_reloadTimer > 0)
- {
- _reloadTimer -= Time.deltaTime;
- if (_reloadTimer <= 0)
- {
- _isReloading = false;
- if (_targetVisible)
- {
- _sfxSource.clip = _laserClip;
- _sfxSource.Play();
- _isTargetting = true;
- _targettingTimer = TargettingTime;
- }
- }
- }
- // Reset aggression after some time
- if (_aggressionResetTimer > 0)
- {
- _aggressionResetTimer -= Time.deltaTime;
- if (_aggressionResetTimer <= 0)
- {
- _bgmFadeCoroutine = FadeAudioSource.StartFade(BGMSource.GetComponent<AudioSource>(), 1f, 0f);
- StartCoroutine(_bgmFadeCoroutine); // Fade out combat music
- _isLookingForTarget = false;
- }
- }
- }
- }
- // SRC: https://johnleonardfrench.com/how-to-fade-audio-in-unity-i-tested-every-method-this-ones-the-best/#first_method
- public static class FadeAudioSource
- {
- public static IEnumerator StartFade(AudioSource audioSource, float duration, float targetVolume)
- {
- float currentTime = 0;
- float start = audioSource.volume;
- while (currentTime < duration)
- {
- currentTime += Time.deltaTime;
- audioSource.volume = Mathf.Lerp(start, targetVolume, currentTime / duration);
- yield return null;
- }
- audioSource.Stop();
- yield break;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement