Unity için Sonsuz Koşucu Eğitimi

Video oyunlarında dünya ne kadar büyük olursa olsun her zaman bir sonu vardır. Ancak bazı oyunlar sonsuz dünyayı taklit etmeye çalışır, bu tür oyunlar Endless Runner kategorisine girer.

Endless Runner, oyuncunun puan toplarken ve engellerden kaçarken sürekli ilerlediği bir oyun türüdür. Ana amaç, engellere düşmeden veya engellerle çarpışmadan seviyenin sonuna ulaşmaktır, ancak çoğu zaman seviye, oyuncu engelle çarpıncaya kadar kademeli olarak zorluk derecesini artırarak kendini sonsuz bir şekilde tekrar eder.

Subway Surfers'ın Oynanışı

Modern bilgisayarların/oyun cihazlarının bile sınırlı işlem gücüne sahip olduğu düşünülürse gerçek anlamda sonsuz bir dünya yaratmak imkansızdır.

Peki bazı oyunlar nasıl sonsuz bir dünya yanılsaması yaratıyor? Cevap, yapı taşlarının yeniden kullanılmasıdır (diğer adıyla nesne havuzu), diğer bir deyişle, blok Kamera görünümünün arkasına veya dışına çıktığında öne doğru hareket ettirilir.

Unity'de sonsuz koşucu oyunu yapmak için engellerin ve oyuncu kontrol cihazının olduğu bir platform yapmamız gerekecek.

Adım 1: Platformu Oluşturun

Daha sonra Prefab:'de saklanacak döşemeli bir platform oluşturarak başlıyoruz.

  • Yeni bir GameObject oluşturun ve onu çağırın "TilePrefab"
  • Yeni Küp oluştur (GameObject -> 3D Nesne -> Küp)
  • Küpü "TilePrefab" nesnesinin içine taşıyın, konumunu (0, 0, 0) olarak değiştirin ve (8, 0,4, 20) olarak ölçeklendirin

  • İsteğe bağlı olarak ek Küpler oluşturarak kenarlara aşağıdaki gibi Raylar ekleyebilirsiniz:

Engeller için 3 engel varyasyonum olacak, ancak siz istediğiniz kadar engel oluşturabilirsiniz:

  • "TilePrefab" nesnesinin içinde 3 GameObject oluşturun ve bunları "Obstacle1", "Obstacle2" ve olarak adlandırın "Obstacle3"
  • İlk engel için yeni bir Küp oluşturun ve onu "Obstacle1" nesnesinin içine taşıyın
  • Yeni Küpü platformla yaklaşık aynı genişliğe ölçeklendirin ve yüksekliğini azaltın (oyuncunun bu engelden kaçınmak için atlaması gerekecektir)
  • Yeni bir Malzeme oluşturun, onu "RedMaterial" olarak adlandırın ve rengini Kırmızı olarak değiştirin, ardından onu Küp'e atayın (bu sadece engelin ana platformdan ayırt edilmesi içindir)

  • "Obstacle2" için birkaç küp oluşturun ve bunları üçgen şeklinde yerleştirin, altta bir açık alan bırakın (oyuncunun bu engelden kaçınmak için çömelmesi gerekecektir)

  • Ve son olarak, "Obstacle3", "Obstacle1" ve "Obstacle2"'nin birleştirilmiş kopyası olacak

  • Şimdi Engellerin içindeki tüm Nesneleri seçin ve etiketlerini "Finish" olarak değiştirin; buna daha sonra Oyuncu ile Engel arasındaki çarpışmayı tespit etmek için ihtiyaç duyulacaktır.

Sonsuz bir platform oluşturmak için Nesne Havuzu Oluşturma ve Engel aktivasyonunu yönetecek birkaç komut dosyasına ihtiyacımız olacak:

  • yeni bir komut dosyası oluşturun, onu "SC_PlatformTile" olarak adlandırın ve içine aşağıdaki kodu yapıştırın:

SC_PlatformTile.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SC_PlatformTile : MonoBehaviour
{
    public Transform startPoint;
    public Transform endPoint;
    public GameObject[] obstacles; //Objects that contains different obstacle types which will be randomly activated

    public void ActivateRandomObstacle()
    {
        DeactivateAllObstacles();

        System.Random random = new System.Random();
        int randomNumber = random.Next(0, obstacles.Length);
        obstacles[randomNumber].SetActive(true);
    }

    public void DeactivateAllObstacles()
    {
        for (int i = 0; i < obstacles.Length; i++)
        {
            obstacles[i].SetActive(false);
        }
    }
}
  • yeni bir komut dosyası oluşturun, onu "SC_GroundGenerator" olarak adlandırın ve içine aşağıdaki kodu yapıştırın:

SC_GroundGenerator.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SC_GroundGenerator : MonoBehaviour
{
    public Camera mainCamera;
    public Transform startPoint; //Point from where ground tiles will start
    public SC_PlatformTile tilePrefab;
    public float movingSpeed = 12;
    public int tilesToPreSpawn = 15; //How many tiles should be pre-spawned
    public int tilesWithoutObstacles = 3; //How many tiles at the beginning should not have obstacles, good for warm-up

    List<SC_PlatformTile> spawnedTiles = new List<SC_PlatformTile>();
    int nextTileToActivate = -1;
    [HideInInspector]
    public bool gameOver = false;
    static bool gameStarted = false;
    float score = 0;

    public static SC_GroundGenerator instance;

    // Start is called before the first frame update
    void Start()
    {
        instance = this;

        Vector3 spawnPosition = startPoint.position;
        int tilesWithNoObstaclesTmp = tilesWithoutObstacles;
        for (int i = 0; i < tilesToPreSpawn; i++)
        {
            spawnPosition -= tilePrefab.startPoint.localPosition;
            SC_PlatformTile spawnedTile = Instantiate(tilePrefab, spawnPosition, Quaternion.identity) as SC_PlatformTile;
            if(tilesWithNoObstaclesTmp > 0)
            {
                spawnedTile.DeactivateAllObstacles();
                tilesWithNoObstaclesTmp--;
            }
            else
            {
                spawnedTile.ActivateRandomObstacle();
            }
            
            spawnPosition = spawnedTile.endPoint.position;
            spawnedTile.transform.SetParent(transform);
            spawnedTiles.Add(spawnedTile);
        }
    }

    // Update is called once per frame
    void Update()
    {
        // Move the object upward in world space x unit/second.
        //Increase speed the higher score we get
        if (!gameOver && gameStarted)
        {
            transform.Translate(-spawnedTiles[0].transform.forward * Time.deltaTime * (movingSpeed + (score/500)), Space.World);
            score += Time.deltaTime * movingSpeed;
        }

        if (mainCamera.WorldToViewportPoint(spawnedTiles[0].endPoint.position).z < 0)
        {
            //Move the tile to the front if it's behind the Camera
            SC_PlatformTile tileTmp = spawnedTiles[0];
            spawnedTiles.RemoveAt(0);
            tileTmp.transform.position = spawnedTiles[spawnedTiles.Count - 1].endPoint.position - tileTmp.startPoint.localPosition;
            tileTmp.ActivateRandomObstacle();
            spawnedTiles.Add(tileTmp);
        }

        if (gameOver || !gameStarted)
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                if (gameOver)
                {
                    //Restart current scene
                    Scene scene = SceneManager.GetActiveScene();
                    SceneManager.LoadScene(scene.name);
                }
                else
                {
                    //Start the game
                    gameStarted = true;
                }
            }
        }
    }

    void OnGUI()
    {
        if (gameOver)
        {
            GUI.color = Color.red;
            GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 100, 200, 200), "Game Over\nYour score is: " + ((int)score) + "\nPress 'Space' to restart");
        }
        else
        {
            if (!gameStarted)
            {
                GUI.color = Color.red;
                GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 100, 200, 200), "Press 'Space' to start");
            }
        }


        GUI.color = Color.green;
        GUI.Label(new Rect(5, 5, 200, 25), "Score: " + ((int)score));
    }
}
  • SC_PlatformTile betiğini "TilePrefab" nesnesine ekleyin
  • "Obstacle1", "Obstacle2" ve "Obstacle3" nesnesini Engeller dizisine atayın

Başlangıç ​​Noktası ve Bitiş Noktası için sırasıyla platformun başına ve sonuna yerleştirilmesi gereken 2 GameObject oluşturmamız gerekiyor:

  • SC_PlatformTile'da Başlangıç ​​Noktası ve Bitiş Noktası değişkenlerini atayın

  • "TilePrefab" nesnesini Prefab'a kaydedin ve Sahneden kaldırın
  • Yeni bir GameObject oluşturun ve onu çağırın "_GroundGenerator"
  • SC_GroundGenerator komut dosyasını "_GroundGenerator" nesnesine ekleyin
  • Ana Kamera konumunu (10, 1, -9) olarak değiştirin ve dönüşünü (0, -55, 0) olarak değiştirin
  • Yeni bir GameObject oluşturun, onu "StartPoint" olarak adlandırın ve konumunu (0, -2, -15) olarak değiştirin
  • "_GroundGenerator" nesnesini seçin ve SC_GroundGenerator'da Ana Kamera, Başlangıç ​​Noktası ve Döşeme Prefabrik değişkenlerini atayın

Şimdi Oynat'a basın ve platformun nasıl hareket ettiğini gözlemleyin. Platform karosu kamera görüntüsünün dışına çıktığı anda, rastgele bir engelin etkinleştirilmesiyle en sona geri taşınır ve sonsuz bir seviye yanılsaması yaratılır (0:11'e atlayın).

Kamera videoya benzer şekilde yerleştirilmelidir, böylece platformlar Kameraya doğru ve arkasına gider, aksi takdirde platformlar tekrarlanmayacaktır.

Sharp Coder Video oynatıcı

2. Adım: Oynatıcıyı Oluşturun

Oyuncu Örneği, zıplama ve çömelme yeteneğine sahip bir kontrol cihazı kullanan basit bir Küre olacaktır.

  • Yeni bir Sphere (GameObject -> 3D Object -> Sphere) oluşturun ve onun Sphere Collider bileşenini kaldırın
  • Daha önce oluşturulan "RedMaterial"'u buna atayın
  • Yeni bir GameObject oluşturun ve onu çağırın "Player"
  • Küreyi "Player" nesnesinin içine taşıyın ve konumunu (0, 0, 0) olarak değiştirin
  • Yeni bir komut dosyası oluşturun, onu "SC_IRPlayer" olarak adlandırın ve içine aşağıdaki kodu yapıştırın:

SC_IRPlayer.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]

public class SC_IRPlayer : MonoBehaviour
{
    public float gravity = 20.0f;
    public float jumpHeight = 2.5f;

    Rigidbody r;
    bool grounded = false;
    Vector3 defaultScale;
    bool crouch = false;

    // Start is called before the first frame update
    void Start()
    {
        r = GetComponent<Rigidbody>();
        r.constraints = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ;
        r.freezeRotation = true;
        r.useGravity = false;
        defaultScale = transform.localScale;
    }

    void Update()
    {
        // Jump
        if (Input.GetKeyDown(KeyCode.W) && grounded)
        {
            r.velocity = new Vector3(r.velocity.x, CalculateJumpVerticalSpeed(), r.velocity.z);
        }

        //Crouch
        crouch = Input.GetKey(KeyCode.S);
        if (crouch)
        {
            transform.localScale = Vector3.Lerp(transform.localScale, new Vector3(defaultScale.x, defaultScale.y * 0.4f, defaultScale.z), Time.deltaTime * 7);
        }
        else
        {
            transform.localScale = Vector3.Lerp(transform.localScale, defaultScale, Time.deltaTime * 7);
        }
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        // We apply gravity manually for more tuning control
        r.AddForce(new Vector3(0, -gravity * r.mass, 0));

        grounded = false;
    }

    void OnCollisionStay()
    {
        grounded = true;
    }

    float CalculateJumpVerticalSpeed()
    {
        // From the jump height and gravity we deduce the upwards speed 
        // for the character to reach at the apex.
        return Mathf.Sqrt(2 * jumpHeight * gravity);
    }

    void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.tag == "Finish")
        {
            //print("GameOver!");
            SC_GroundGenerator.instance.gameOver = true;
        }
    }
}
  • SC_IRPlayer betiğini "Player" nesnesine ekleyin (Rigidbody adında başka bir bileşen eklediğini fark edeceksiniz)
  • BoxCollider bileşenini "Player" nesnesine ekleyin

  • "Player" nesnesini "StartPoint" nesnesinin biraz üstüne, Kameranın hemen önüne yerleştirin

Oynat tuşlarına basın ve atlamak için W tuşunu, çömelmek için S tuşunu kullanın. Amaç kırmızı Engellerden kaçınmaktır:

Sharp Coder Video oynatıcı

Şunu kontrol edin Horizon Bending Shader.

Kaynak
📁EndlessRunner.unitypackage26.68 KB
Önerilen Makaleler
Unity'de 3'lü Eşleştirme Bulmaca Oyunu Eğitimi
Unity'de 2D Tuğla Kırıcı Oyunu Oluşturma
Unity'de Kayan Bulmaca Oyunu Oluşturma
Unity'de Flappy Bird'den Esinlenen Bir Oyun Nasıl Yapılır
Unity'de Mini Oyun | CUBEkaçının
Çiftlik Zombileri | Unity'de 2D Platform Oyununun Yapımı
Unity'de Mini Oyun | Flappy Küp