Menu
CoddyTech

Kahraman

Coddy'nin Unity Journey'sinin Unity'de Oyun Mimarisi bölümünün bir parçası. Ders 41 / 50.

Bu bölüm, yolculuğun son oyunu olan Arena Survivor'ı geliştiriyor. Düşman dalgaları duvarlarla çevrili bir arenaya akın ediyor ve sen kılıçla onları püskürtüyorsun: sana doğru yürüyen piyadeler ve bekleyip sonra atılan küreler. Yenilen bir dalga bir güçlendirme bırakıyor, HUD sağlığını ve dalgayı gösteriyor; sağlığın tükendiğinde oyun sona eriyor ve en iyi oyun kaydediliyor. Oyun, bu bölümdeki araçları uygun oldukları yerlerde kullanıyor: iki türü olan soyut bir Enemy, zarar görebilecek her şey için IDamageable, ScriptableObject varlığı olarak dalgalar, bir arayüzün arkasındaki toplanabilir güçlendirmeler, yalnızca C# olaylarını dinleyen bir HUD ve JSON kaydı. On iki betiğin tümü en baştan projede yer alıyor. Şimdilik yalnızca Hero kod içeriyor ve her ders daha fazlasını ekliyor.

Kahramanın kılıcı önündeki şeylere isabet eder, bu yüzden kılıç savuruşunun "önde" olup olmadığını sınaması gerekir. Vector3.Dot(a, b) iki vektörün karşılık gelen bileşenlerini çarpar ve sonuçları toplar: a.x * b.x + a.y * b.y + a.z * b.z. Uzunlukları 1 olan iki yön için bu, aralarındaki açının kosinüsüdür: aynı yönü gösterdiklerinde 1, 30 derecede 0.866, 45 derecede 0.707, dik açıda 0 ve zıt yönü gösterdiklerinde -1. Böylece "baktığım yönden en fazla 30 derece uzakta" ifadesi, hesaplanacak bir açı olmadan "noktasal çarpım en az 0.866" hâline gelir. Bu nöbetçi robot, oyuncu 10 birim yakınında ve 30 derecelik görüş alanının içindeyken alarmı çalıştırır:

public Transform player;
public float range = 10f;

void Update()
{
    Vector3 toPlayer = player.position - transform.position;
    toPlayer.y = 0f;
    bool near = toPlayer.magnitude <= range;
    bool inView = Vector3.Dot(transform.forward, toPlayer.normalized) >= 0.866f;
    if (near && inView)
    {
        Debug.Log("Alarm!");
    }
}

Her iki yönün de uzunluğu 1 olmalıdır. transform.forward her zaman bu uzunluktadır, ancak toPlayer uzaklık kadar uzundur; bu yüzden önce normalize edilir. Aksi hâlde iki kat uzaktaki bir oyuncu, noktasal çarpımın iki kat olmasına neden olurdu. Bundan önce y değeri 0 olarak ayarlanır; böylece daha yüksek bir yürüyüş yolundaki oyuncu, ne kadar yüksekte olduğuna göre değil, haritada durduğu konuma göre hesaba katılır. İşaret, önü arkadan ayırır: 0'dan büyük noktasal çarpım ön yarım dairenin herhangi bir yerini, 0'dan küçük olan ise arka tarafın herhangi bir yerini gösterir.

challenge icon

Görev

Orta

Arena Survivor'a kahramanın kılıcıyla başla. Yürüme şöyle yazılır: Move eylemi, SimpleMove ile kahramanı yürütür ve yürüdüğü yöne bakmasını sağlar. Etrafında Enemy etiketi taşıyan beş eğitim mankeni durur. Inspector, Hero için reach (2) ve swingCooldown (0.5) değerlerini ve savuruş sırasında gösterdiği kılıç darbesi efektini ayarlar.

  • Space tuşuna basmak veya sol tıklamak savuruş yapar; bu, swingCooldown saniyede en fazla bir kez gerçekleşir: bekleme süresi bitmeden yapılan bir basış hiçbir şey yapmaz. Tuşları Keyboard.current ve Mouse.current ile oku ve Swing() çağrısını yap.
  • Swing() içinde, kılıç darbesi gösterildikten sonra reach mesafesinde ve kahramanın önünde bulunan Enemy etiketli her nesneyi yok et. Erişme mesafesi içinde olmak, Physics.OverlapSphere'ın kahramanın etrafında reach yarıçapıyla bulduğu herhangi bir çarpıştırıcı demektir. Önde olmak, kahramanın ileri yönü ile nesneye doğru, zemin boyunca olan yön arasındaki nokta çarpımının en az 0.5 olması demektir: her iki yana doğru en fazla 60 derece.

Diğer betikleri olduğu gibi bırak. Play'e bas, mankenlere doğru yürü ve savuruş yap, ardından Kontrol Et'e bas.

Kendin dene

using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;

public class Hero : MonoBehaviour
{
    [SerializeField] private float speed = 5f;
    [SerializeField] private float reach = 2f;
    [SerializeField] private float swingCooldown = 0.5f;
    [SerializeField] private GameObject slash;

    private CharacterController controller;
    private InputAction moveAction;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        moveAction = InputSystem.actions.FindAction("Move");
    }

    void Update()
    {
        Vector2 input = moveAction.ReadValue<Vector2>();
        Vector3 move = new Vector3(input.x, 0f, input.y);
        controller.SimpleMove(move * speed);
        if (move != Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(move);
        }

        // Space tuşu veya sol tıklama saldırı yapar; en fazla swingCooldown saniyede bir kez
    }

    void Swing()
    {
        StartCoroutine(ShowSlash());
        // kahramanın önünde ve reach mesafesinde bulunan, Enemy etiketi taşıyan her şeyi yok et
    }

    IEnumerator ShowSlash()
    {
        slash.SetActive(true);
        yield return new WaitForSeconds(0.1f);
        slash.SetActive(false);
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Unity'de Oyun Mimarisi bölümündeki tüm dersler