Selamlar, ben Oğuz.
30 yaşımdan sonra oyun geliştirmeye başladığım serüvenimde ilk oyunum tipik Roll a Ball oyunu oldu. Roll a Ball’u seçmemim sebebi tamamıyla tipik bir başlangıç projesi olması. Hem yapması kolay, hem de kattığı şeyler oldukça hoş. Gelin projeye birlikte bakalım.
🎯Oyunun Amacı
Ana objemiz bir küre ve amacımız sahnede bulunan ve kendi etraflarında dönen küplerin tamamını toplayıp oyunu tamamlamak. Küplerin hepsini topladığımızda ekrana “Tebrikler, oyunu tamamladın! Tekrar başlamak için “R” tuşuna bas!” yazısı çıkar. Oyuncu isterse R tuşuna basarak oyunu tekrardan oynayabilir.
🛠️Sahne Kurulumu
Zemin için ekrana bir adet plane ekledim. Daha sonrasında transform komponenti üzerinden scale ayarlarıyla oynayarak zemini büyüttüm. Zeminin duvarlarını yapmaya başladım. Burada sahneye bir cube ekleyerek şekillendirip duvar haline getirdim ve zeminin 4 tarafına monta ettim.
Sıra geldi ana objemize yani küremize. Sahneye bir adet sphere yani küre ekleyerek kontrol edeceğimiz objeyi tanımladım. Sahneye cube ekledim ve bu objeyi de hedef obje olarak tanımladım. Bütün objeleri ekledikten sonra bu objelere yeni materyaller ekleyerek onları renklendirdim.
👨💻İşin Kod Tarafı
⚽Oyuncumuzu Hareket Ettirme
public class playerScript : MonoBehaviour
{
float horizontal, vertical;
[SerializeField] float speed;
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
playerMov();
}
void playerMov()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
Vector3 move=new Vector3 (horizontal, 0, vertical);
rb.AddForce (move*speed,ForceMode.VelocityChange);
}
Burada adından da anladığınız üzere playerMov isminde bir fonksiyon oluşturup (burada şimdi çıkıp ” C#’da fonksiyon değil onlar” diyenler olacak) oyuncu hareketlerini burada tanımladım. Direkt void Update içerisinde de tanımlayabilirdim, ama böylesi hem daha düzenli hem de düzenleme yapmak istediğimde bulması ve çözmesi kolay. Burada şimdi her satır ne anlama geldiğini anlatmak istemiyorum. Belki o tür içerikleri Youtube’da yaparız.
📹Takip Kamerası
public class followCamera : MonoBehaviour
{
public Transform ball;
public Vector3 offset;
// Update is called once per frame
void Update()
{
transform.position = ball.position + offset;
}
}
İstediğim şey oyuncu hareket ederken onu belli bir mesafeden kontrol eden bir kamera. Bunu da mini bir script ile çözdüm. offset isimli Vector3 değişkene aradaki mesafeyi verdim ve bunu ball‘un mesafesine ekleyerek kameranın takip etmesi gereken mesafeyi ayarladım. Update içerisine de yazdığım için bunu her frame’de yaptı. Buraya LateUpdate‘de konulabilirdi, ama olsun ilk proje. Büyük resme bakmak lazım.
🔁Küplerin Dönmesi
public class pickableScript : MonoBehaviour
{
void Update()
{
transform.Rotate(new Vector3(15,30,45)*Time.deltaTime);
}
}
Burada amacımız sadece küplerin kendi etrafında sonsuz bir şekilde dönmelerini sağlamak olduğundan bunu 1 satırla çözebiliyoruz. İhtiyacımız olan tek şey transform.Rotate.
💥Küpleri Toplama ve UI Puan Sistemi
public class gameManagerScript : MonoBehaviour
{
public Text scoreText;
public int Score=0;
AudioSource audioSource;
public AudioClip pickSound;
public Text endGameText;
bool gameEnded = false;
void Start()
{
audioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
if (gameEnded && Input.GetKeyDown(KeyCode.R))
{
Debug.Log("pressed R");
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
public void addScore()
{
Score++;
scoreText.text = "Score: " + Score.ToString();
audioSource.PlayOneShot(pickSound);
if(Score==10)
{
endGameText.enabled = true;
gameEnded = true;
}
}
}
Bu script’in sadece mantığını açıklamak istiyorum. İstediğimiz şu: oyuncu küplere temas edince 1 puan kazanacak ve her küp temasında toplama sesi gelecek. Oyuncumuzun toplam skoru 10’u ulaştığında ekrana “You won! If you want to play again press ‘R'” yazısını çıkacak ve oyuncu isterse “R tuşuna basarak oyuna yeniden başlayabilecek. Bu script tam olarak bu işe yarıyor.
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag=="pickable")
{
Destroy(other.gameObject);
gameManager.GetComponent<gameManagerScript>().addScore();
}
}
Burada da gameManagerScript’te yaptığımız işlemleri playerScript kısmına aktarıp orada bir temas tetiklemesi işlemi sağlamak. Zaten bu işlemi yaptıktan sonra da oyunumuz tamamlanmış ve build almaya hazır hale gelmiş oluyor.
🎯Bu Projede Öğrendiklerim
- Rigidbody ayarlarını
- Collider temas tetikleme mantığını
- Objeleri ve scriptleri tag ile kontrol etme ve çağırmayı
- UI sistemini ve kontrol etmeyi
- Sahne yönetimini
💬Proje İçin Son Sözlerim
30 yaşımdan sonra başladığım oyun geliştirme sürecinin ilk projesi oldu. Belki minik bir proje olabilir, ama bu şekilde büyük projelere minik adımlar atabiliriz. Hep birlikte ilerlemeye devam edelim dostlar.
Projeyi hem Github‘a hem de Itch.io’ya yükledim. GitHub’da oyunun hem sahne dosyalarına ve kodlarına hem de tamamlanmış haline ulaşabilirsiniz. Itch.io’da ise sadece tamamlanmış hali mevcut. Hangisiniz isterseniz brolar, tercih sizin.
Github Bağlantı Linki: https://github.com/ogzrealm/Roll-a-Ball
Itch.io Bağlantı Linki: https://ogzrealm.itch.io/roll-a-ball
