Syntax
Üstün
- Katılım
- 11 Şubat 2024
- Mesajlar
- 1.835
- Çözümler
- 10
- Beğeniler
- 1.843
Merhaba, bu rehberde NavMesh kullanarak basit bir düşman AI sistemi oluşturacağız. Düşman oyuncuyu takip edecek, belirli mesafede duracak ve ona bakacak.
Sonrasında haritamızın layerlarını seçmemiz lazım bu kısımda.
Layerları ayarladıktan sonra 'Bake' etmelisiniz.
- Düşmana mapi tanımlayalım
Hirerachyde boş bir obje oluşturalım. Adını 'NavMesh' koydum ben, siz istediğinizi koyabilirsiniz.
Bu boş objeye navmesh surface componenti ekliyoruz. Bu component AI karakterlerin haritada yürüyebileceği alanları belirlemesini sağlıyor.Sonrasında haritamızın layerlarını seçmemiz lazım bu kısımda.
Layerları ayarladıktan sonra 'Bake' etmelisiniz.
- Düşmana hareket etmesini sağlayan componenti ekleyelim.
Base offset: Düşmanın pivot noktasını ayarlamamız için bunu varsayılan olarak bırakacağız.
Speed: Düşmanın hızı.
Angular Speed: Düşmanın maksimum dönme hızı. (saniye başına derece cinsinden.)
Acceleration: düşmanın hızlanması.
Stopping Distance: düşmanın ile karakterimiz arasındaki durma mesafesi. Değeri arttıkça daha uzakta duracak.
Auto Braking: düşman hedefe yakınken yavaşlamaya başlar.
Radius:düşmanın genişliği/çapı
Height: Düşmanın boyu.
Quality: Engelden kaçınma.
Priority: Birden fazla düşman olacak oyunda. Bu düşmanların yolu kesişirse çarpışır, çarpışacaksa hangisi yol verir gibi bir ayar.
Auto Traverse OffMesh Link: navmesh Link'leri arasında otomatik geçiş yapsın mı? Navmesh link yüzeyler arasındaki geçiş oluyor. Mesela merdivenden zipline platformuna geçiş.
Auto Repath: yeniden yol oluşturur.
Area Mask: Düşman hangi alanlarda yürüyebilir?
- Scriptimizi yazalım
İlk olarak düşmanın temel özelliklerini ve referanslarını tutan scripti oluşturacağız.
C#:
using UnityEngine;
using UnityEngine.AI;
public class EnemyRef : MonoBehaviour
{
[HideInInspector] public NavMeshAgent agent;
[HideInInspector] public Animator animator;
public float health = 100f;
[Header("Stats")]
public float pathUpdateDelay = 0.2f;
private void Awake()
{
agent = GetComponent<NavMeshAgent>();
animator = GetComponent<Animator>();
}
public void TakeDamage(float damage)
{
health -= damage;
Debug.Log($"Düşman hasar aldı! Kalan can: {health}");
if (health <= 0f)
{
Debug.Log("Düşman öldü!");
Destroy(gameObject);
}
}
}
[HideInInspector]: Değişkenlerin Inspector'da gözükmesini engeller.
Pathupdatedelay değişkeni, yolu her frame yerine 0.2 saniyede bir güncellememiz için var.
TakeDamage fonksiyonu, hasar sistemini içeriyor.
Sıra enemy scriptine geldi. Bu script ile düşmanın menzilin içine girmesi ve karakterimize bakmasını sağlayacağız.
C#:
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;
public class Enemy : MonoBehaviour
{
public Transform target;
EnemyRef enemyRef;
float shootingDistance;
private float pathUpdateDeadLine;
private void Awake()
{
enemyRef = GetComponent<EnemyRef>();
}
private void Start()
{
shootingDistance = enemyRef.agent.stoppingDistance;
}
private void Update()
{
if (target != null)
{
bool inRange = Vector3.Distance(transform.position, target.position) <= shootingDistance;
if (inRange)
{
LookAtTarget();
}
else
{
UpdatePath();
}
enemyRef.animator.SetBool("shooting", inRange);
}
//enemyRef.animator.SetFloat("speed", enemyRef.agent.desiredVelocity.sqrMagnitude);
}
private void LookAtTarget()
{
Vector3 lookPos = target.position - transform.position;
lookPos.y = 0;
Quaternion rotation = Quaternion.LookRotation(lookPos);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, 0.2f);
}
private void UpdatePath()
{
if (Time.time >= pathUpdateDeadLine)
{
pathUpdateDeadLine = Time.time + enemyRef.pathUpdateDelay;
enemyRef.agent.SetDestination(target.position);
}
}
}
inRange boolu, iki pozisyon arasındaki mesafeyi hesaplar ve stopping distance ile karşılaştırır. Düşmanın durmasını kontrol etmek için var.
LookAtTarget() Fonksiyonu, düşmanın karakterimize bakmasını sağlıyor. Burada y eksenini sıfırlama sebebimiz düşmanın yukarı/aşağı eğilmesini engellemek için.
Slerp, yumuşak dönüş sağlaması için kullanıyoruz.
UpdatePath() Fonksiyonu, düşmanın yolunu güncelliyor.
- Düşman animasyonları
enemyRef.animator.SetBool("shooting", inRange);enemyRef.animator.SetFloat("speed", enemyRef.agent.desiredVelocity.sqrMagnitude);Bu kodlardan ilki ateş etme animasyonunu aktifleştiriyor. Eğer stopping distance olması gereken değerdeyse ateş ediyor.
İkincisi ise karakterimizin yürüme animasyonunu çalıştırmak için var.
- Scriptleri düşmana ekleyelim.
Target burada oyuncu olacak. Health değişkeni ise düşmanın canı. Path Update delay ise düşmanın yolunun hesaplanma gecikmesi.
Yapmamız gerekenler bunlar. Bunun sonunda düşmanımız karakterimizi takip edecek.
Animasyonları kendi düşman karakterinize göre ayarlamanız gerekmektedir.
Eğer yapmazsanız, oyun çalışır fakat animasyonlar çalışmaz. İyi sosyaller.
Animasyonları kendi düşman karakterinize göre ayarlamanız gerekmektedir.
Eğer yapmazsanız, oyun çalışır fakat animasyonlar çalışmaz. İyi sosyaller.