/
arti4
/
CourseWork
Обзор
Документация
Войти
/
arti4
/
CourseWork
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Scriptes/Swordsman.cs
478 строк
15 KB
arti4
Загрузить файлы в «Scriptes»
01 июн 2025, 11:57
01 июн 2025, 11:57
3eddd7a
Код
Авторство
О чём код?
using UnityEngine; using System.Collections; public class Swordsman : MonoBehaviour { public int health; public float speed; public float deathDelay = 2f; public float attackRadius = 5f; public float attackCooldown = 1f; public float patrolDistance = 5f; public int attackDamage = 10; private float lastAttackTime = -Mathf.Infinity; private Vector2 startPoint; private bool movingRight = true; private Animator animator; private Transform player; private bool isIdle = false; private bool stoppedByBarbwire = false; private bool stoppedBySwordsman = false; private Collider2D currentBarbwire; private bool isDeadHandled = false; private float fixedYPosition; private bool isDying=false; private PlayerHealth playerHealth; [SerializeField] private GameObject medicine; [SerializeField] private int medicineSpawnChance; [SerializeField] private BoxCollider2D boxCollider; [SerializeField] private AudioSource audioSourceShoot; [SerializeField] private AudioClip hitSound; [SerializeField] private AudioSource audioSourceWalk; [SerializeField] private AudioClip walkSound; [SerializeField] private float basePitch = 0.7f; [SerializeField] private float maxHearingDistance = 15f; public float exitAttackGracePeriod = 0.3f; private float timeSinceOutOfAttackRange = 0f; private bool playerWasInAttackRange = false; private bool anybody; public bool logger; private Rigidbody2D rb; private void Start() { lastAttackTime = Time.time; boxCollider = GetComponentInChildren<BoxCollider2D>(); rb = GetComponent<Rigidbody2D>(); startPoint = transform.position; animator = transform.Find("Body")?.GetComponent<Animator>(); GameObject playerObject = GameObject.FindWithTag("Player"); if (playerObject != null) { player = playerObject.transform; playerHealth = playerObject.GetComponentInParent<PlayerHealth>() ?? playerObject.GetComponentInChildren<PlayerHealth>(); } audioSourceWalk.pitch = basePitch; } private void Update() { if (isDying) { transform.position = new Vector3(transform.position.x, fixedYPosition, transform.position.z); return; } if (health > 0) { IsObstacleAhead(); float distanceToPlayer = player != null ? Vector2.Distance(transform.position, player.position) : Mathf.Infinity; if (stoppedByBarbwire && (currentBarbwire == null || !currentBarbwire.gameObject.activeInHierarchy)) { stoppedByBarbwire = false; } //Если остановлен препятствием if (stoppedByBarbwire || stoppedBySwordsman) { if (distanceToPlayer > 3 * patrolDistance) { Flip(); movingRight = !movingRight; stoppedByBarbwire = false; stoppedBySwordsman = false; } if (distanceToPlayer <= 3 * patrolDistance) { rb.linearVelocity = Vector2.zero; animator.SetBool("Running", false); audioSourceWalk.Stop(); FlipTowardsPlayer(); } if (distanceToPlayer <= attackRadius) { StopAndAttack(); } if (!anybody) { if (transform.position.x < player.position.x && stoppedByBarbwire) { stoppedByBarbwire = false; } if (transform.position.x > player.position.x && !stoppedByBarbwire) { stoppedBySwordsman = false; } } } if (stoppedByBarbwire) return; if (stoppedBySwordsman) return; if (player != null) { //Если игрок в радиусе атаки if (distanceToPlayer <= attackRadius) { playerWasInAttackRange = true; timeSinceOutOfAttackRange = 0f; StopAndAttack(); animator.SetBool("Running", false); audioSourceWalk.Stop(); } else { if (playerWasInAttackRange) { timeSinceOutOfAttackRange += Time.deltaTime; if (timeSinceOutOfAttackRange < exitAttackGracePeriod) { animator.SetBool("Idle", true); animator.SetBool("Running", false); return; } else { playerWasInAttackRange = false; } } if (distanceToPlayer <= 3 * patrolDistance) { FollowPlayer(); } else { Patrol(); } } } else { Patrol(); } AdjustSoundVolume(); } else { Die(); } } //Остоновка при касании другого мечника private void IsObstacleAhead() { Vector2 offset = new Vector2(movingRight ? 0.8f : -0.8f, 0); Vector2 direction = movingRight ? Vector2.right : Vector2.left; Debug.DrawRay((Vector2)transform.position + offset, direction * 1f, Color.red); RaycastHit2D hit = Physics2D.Raycast((Vector2)transform.position + offset, direction, 1f); if (hit.collider != null) { string hitObjectName = hit.collider.gameObject.name; if (hitObjectName == "Body" && hit.collider.CompareTag("Swordsman")) { anybody = true; stoppedBySwordsman = true; rb.linearVelocity = Vector2.zero; animator.SetBool("Running", false); audioSourceWalk.Stop(); } else { anybody = false; stoppedBySwordsman = false; } } else { anybody = false; stoppedBySwordsman = false; } } //Настройка громкости private void AdjustSoundVolume() { if (audioSourceWalk == null || player == null) return; float distance = Vector2.Distance(transform.position, player.position); if (distance > maxHearingDistance) { audioSourceWalk.volume = 0; return; } if (distance <= maxHearingDistance / 2) { audioSourceWalk.volume = 1; return; } float volumeFactor = Mathf.Clamp01(1 - ((distance - (maxHearingDistance / 2)) / (maxHearingDistance / 2))); audioSourceWalk.volume = volumeFactor; } //Патрулирование private void Patrol() { if (animator != null && !isIdle) { animator.SetBool("Running", true); animator.SetBool("Idle", false); } if (!audioSourceWalk.isPlaying) { audioSourceWalk.clip = walkSound; audioSourceWalk.Play(); } float targetX = movingRight ? startPoint.x + patrolDistance : startPoint.x - patrolDistance; if (movingRight && transform.position.x >= targetX) { Flip(); movingRight = false; } else if (!movingRight && transform.position.x <= targetX) { Flip(); movingRight = true; } Vector2 direction = movingRight ? Vector2.right : Vector2.left; rb.linearVelocity = new Vector2(direction.x * speed, rb.linearVelocity.y); } //Преследвоание игрока private void FollowPlayer() { if (animator != null) { animator.SetBool("Running", true); animator.SetBool("Idle", false); } if (!audioSourceWalk.isPlaying) { audioSourceWalk.clip = walkSound; audioSourceWalk.Play(); } FlipTowardsPlayer(); Vector2 direction = (player.position - transform.position).normalized; rb.linearVelocity = new Vector2(direction.x * speed, rb.linearVelocity.y); } //Отрисовка кругов для отладки private void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, attackRadius); Gizmos.color = Color.green; Gizmos.DrawWireSphere(transform.position, maxHearingDistance); } //Остановка и атака private void StopAndAttack() { if (animator != null) { float distanceToPlayer = Vector2.Distance(transform.position, player.position); FlipTowardsPlayer(); if (distanceToPlayer > attackRadius) { animator.SetBool("Idle", true); return; } if (Time.time < lastAttackTime + attackCooldown) { if (Time.time < lastAttackTime + attackCooldown) { if (!IsAnimationPlaying("Attack")) { if (!isIdle) { animator.SetBool("Idle", true); isIdle = true; } } return; } } else { lastAttackTime = Time.time; animator.SetTrigger("Attacking"); animator.SetBool("Idle", false); isIdle = false; audioSourceShoot.PlayOneShot(hitSound); StartCoroutine(DealDamageAfterAttack()); } } } //Нанесение урона с задержкой private IEnumerator DealDamageAfterAttack() { yield return new WaitForSeconds(0.5f); if (playerHealth != null) { float distanceToPlayer = Vector2.Distance(transform.position, player.position); if (distanceToPlayer <= attackRadius) { playerHealth.TakeDamage(attackDamage); lastAttackTime = Time.time; } } animator.ResetTrigger("Attacking"); float distanceAfterAttack = Vector2.Distance(transform.position, player.position); if (distanceAfterAttack > attackRadius) { animator.SetBool("Running", true); animator.SetBool("Idle", false); } else { animator.SetBool("Idle", true); animator.SetBool("Running", false); } } //Проверка атаки public void CheckAttackAndResumePatrol() { if (animator != null) { if (!IsAnimationPlaying("Attacking")) { animator.SetBool("Attacking", false); } } } //Проверка на проигрывание анимации private bool IsAnimationPlaying(string animationName) { return animator.GetCurrentAnimatorStateInfo(0).IsName(animationName) && animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1f; } //Поворот в сторону игркоа private void FlipTowardsPlayer() { if (player != null) { if (transform.position.x < player.position.x) { if (!movingRight) Flip(); movingRight = true; } else { if (movingRight) Flip(); movingRight = false; } } } //Разворот private void Flip() { Vector3 scale = transform.localScale; scale.x *= -1; transform.localScale = scale; } //Запуск процесса смерти private void Die() { if (animator != null) { if (!IsAnimationPlaying("Die")) { animator.SetTrigger("Die"); animator.SetBool("Running", false); animator.SetBool("Attacking", false); animator.SetBool("Idle", false); fixedYPosition = transform.position.y; isDying = true; Collider2D col = GetComponent<Collider2D>(); if (col != null) col.enabled = false; if (Random.Range(0f, 100f) <= medicineSpawnChance) { Instantiate(medicine, transform.position, transform.rotation); } Invoke("OnDeathAnimationEnd", deathDelay); } } } //Получение урона public void TakeDamage(int damage) { health -= damage; if (health <= 0) { Die(); } } //Уничтожение с задержкой врага после смерти public void OnDeathAnimationEnd() { if (isDeadHandled) return; isDeadHandled = true; Destroy(gameObject); isDying = false; } //Столкновение со стоппером или колючей проволокой private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("Barbwire") || other.CompareTag("Stopper")) { stoppedByBarbwire = true; currentBarbwire = other; float distanceToPlayer = player != null ? Vector2.Distance(transform.position, player.position) : Mathf.Infinity; if (distanceToPlayer <= 3 * patrolDistance) { animator.SetBool("Idle", true); animator.SetBool("Running", false); } else { Flip(); movingRight = !movingRight; stoppedByBarbwire = false; } } } //Выход из зоны стоппера или колючей проволоки private void OnTriggerExit2D(Collider2D other) { if ((other.CompareTag("Barbwire") || other.CompareTag("Stopper")) && stoppedByBarbwire) { stoppedByBarbwire = false; currentBarbwire = null; float distanceToPlayer = player != null ? Vector2.Distance(transform.position, player.position) : Mathf.Infinity; if (distanceToPlayer > 3 * patrolDistance) { Patrol(); } } } }