Kayıt Sistemi (Bölüm 1)
Genelde biraz daha ilginç veyaz az anlatılan konular hakkında yazmayı tercih ediyorum. Ancak oyun kaydı konusu sık sık sorulduğu için hakkında bir ders yazayım dedim. Bu başlangıç seviyesi bir ders olacak. O yüzden çılgın programlama teknikleri veya sistem tasarımları beklemeyin.
Her şeyden önce kayıt sitemi yapmanın birden fazla yolu olduğunu belirteyim. Her oyun farklıdır. İkinci önemli nokta her şeyi kaydedemezsiniz (her seferinde RAM’deki birkaç GB veriyi kaydetmek isterseniz orası ayrı). Seviye, can, oyuncunun adı gibi önemli verileri seçip kaydetmeniz lazım. Tabii bu verileri nasıl yükleyeceğinizi ve oyunda nasıl kullanacağınız da önceden düşünmeniz lazım.
Player isimli bir sınıfımızın (class) olduğunu varsayalım. Player’ın kayıt için kullanacağımız iki metodu, ve kaydetmek istediğimiz iki değişkeni olduğunu varsayaılm: SaveData(), LoadData(), playerName ve playerHealth.
using UnityEngine; public class Player : MonoBehaviour { public string playerName = "Assign a name in the inspector"; public float playerHealth = 100f; private void Start() { // Oyun başladığında verileri yükler LoadData(); } private void OnDisable() { // Oyun kapandığında verileri kaydeder SaveData(); } private void SaveData() { // playerName ve playerHealth değerlerini kaydedecek } private void LoadData() { // playerName ve playerHealth değerlerini yükler } }
Bu sınıfı sahnedeki bir objeye atayalım, ismi ve canı değiştirelim.
PlayerPrefs
Eğer daha önce Unity’de veri kayıt yöntemlerini araştırdıysanız muhtemelen bu metoda denk gelmişsinizdir. Bu metodu kullanarak verilerimizi şöyle kaydedebiliriz:
private void SaveData() { // Oyuncunun ismini kaydet PlayerPrefs.SetString("playerName", playerName); // Oyuncunun canını kaydet PlayerPrefs.SetFloat("playerHealth", playerHealth); // Değişiklikleri veritabanına kaydetmek için bu metodu çağırmamız lazım PlayerPrefs.Save(); }
Ve şu şekilde yükleyebiliriz:
private void LoadData() { // playerName diye bir değişkenin olup olmadığını kontrol et if (PlayerPrefs.HasKey("playerName")) { // Kayıtlı değeri okuyup playerName'e ata playerName = PlayerPrefs.GetString("playerName"); } // playerHealth diye bir değişkenin olup olmadığını kontrol et if (PlayerPrefs.HasKey("playerHealth")) { // Kayıtlı değeri okuyup playerHealth'e ata playerHealth = PlayerPrefs.GetFloat("playerHealth"); } }
Unity’de oyunu başlatın, playerName ve playerHealth değişkenlerini değiştirin ve oyunu durdurun. Oyunu bir daha başlatırsanız verilerin yüklediğini göreceksiniz.
Bu yöntem çalışıyor ve birkaç değişkeni kaydetmek için kullanışlı olabilir. Ancak kaydetmeniz gereken değişken sayısı arttıkça işiniz zorlaşacaktır. Buraya sadece int, float ve string değerlerini kaydedebilirsiniz. Ayrıca Windows’ta bu şekilde kaydedilen veriler registry denilen bir sistem veritabanında duruyor. Oyun dosyalarınızı sistemin derinliklerinde tutmak pek iyi bir pratik değil. Üstelik bu verileri kolay bir şekilde modifiye etmenin bir yolu da yok.
Kendi kayıt dosyamızı oluşturmak
Peki nasıl bir alternatifimiz var? Tabii ki de kendi kayıt dosyalarımızı oluşturmak! Burada korkulacak bir şey yok. Yapmamız gereken tek şey verilerimizi string değerine çevirip bir C# metodu çağırmak. playerName bir string olduğuna göre işe onunla başlayalım.
private void SaveData() { // Application.persistentDataPath oyununuz için yaratılan özel bir klasör // Daha fazla bilgi için: https://docs.unity3d.com/2021.3/Documentation/ScriptReference/Application-persistentDataPath.html string savePath = $"{Application.persistentDataPath}/Save.txt"; System.IO.File.WriteAllText(savePath, playerName); } private void LoadData() { string savePath = $"{Application.persistentDataPath}/Save.txt"; // Böyle bir dosyanın olup olmadığını kontrol et if (System.IO.File.Exists(savePath)) { // Dosyayı oku ve playerName'e ata playerName = System.IO.File.ReadAllText(savePath); } }
Application.persistentDataPath uygulamanız için ayrılmış özel bir klasör. Tam yeri her işletim sisteminde değişiklik gösterir. Sizinkinin yerini bulmak için dokümentasyona bakabilirsiniz. Dilerseniz onun yerine bilgisayarınızdaki herhangi bir klasörü kullanabilirsiniz.
Şimdi oyunu açıp kapattıktan sonra ilgili klasörde Save.txt isimli bir dosya göreceksiniz. Bu dosyayı istediğiniz bir metin editöründe açıp değiştirebilirsiniz.
Peki ya canı nasıl kaydedeceğiz? Her değişken için Save_playerName.txt, Save_playerHealth.txt gibi dosyalar mı oluşturacağız? Böyle bir şey yapabilirsiniz tabii ama çok iyi bir yöntem olmayacaktır. En mantıklısı bütün değişkenleri tek bir dosyaya kaydetmek olacaktır.
Bunun için yapmamız gereken tek şey bütün değişkenleri bir string’e çevirmek:
private void SaveData() { string data = playerName + "," + playerHealth.ToString(); string savePath = $"{Application.persistentDataPath}/Save.txt"; System.IO.File.WriteAllText(savePath, data); }
Şimdi Save.txt dosyası şöyle olacaktır:
Anton,32
Devam etmeden önce string dosyasını oluşturduğumuz satırı elden geçirelim.
string data = $"{playerName},{playerHealth.ToString()}";
Bu hali çok daha iyi. Teknik sebebini merak ediyorsanız dokümentasyonunu okuyabilirsiniz.
Peki yükleme işini nasıl yapacağız? Devam etmeden önce oyunu çalıştırmayı deneyin. Gördüğünüz gibi playerName hem ismi hem de yaşı almış. Bu beklenen bir sonuç. Ne de olsa bütün txt dosyasını okuyup playerName’e atıyoruz. Şimdi gelelim bu dersin en karmaşık kısmına…
Veriyi çözümlemek
Burada yapmamız gereken dosyayı okumak ve virgülün sağı ve solu olmak üzere ikiye ayırmak. Neyse ki C#’ın string.Split() diye bir metodu var:
// Dosyayı oku string text = System.IO.File.ReadAllText(savePath); // Veriyi ayır string[] dataParts = text.Split(","); // Değişkenleri ata playerName = dataParts[0];
Gördüğünüz gibi Split(“,”) metodu string’i virgülden ayırıp iki elemanlı bir dizi (array) şeklinde bize geri veriyor. Virgül yerine hernangi bir karakteri ya da karakter dizisini kullanabilirsiniz. Bu metod hakkında daha fazla bilgiye dokümentasyonundan ulaşabilirsiniz.
Virgülden önceki değişkenin isim, sonraki değişkenin ise can olduğunu biliyoruz. O yüzden dizideki ilk elemanın isim, ikincisinin ise can olduğunu varsayabiliriz. Bu durumda ismi atamak kolay çünkü elimizde bir string var ve isim zaten string. Ancak playerHealth bir float. Bu durumda string’i float’a çevirmemiz lazım. Ve yine imdadımıza hali hazırda olan bir metod yetişiyor: float.Parse().
playerHealth = float.Parse(dataParts[1]);
Benzer metodlar int, bool ve diğer temel veri tipleri için mevcut. Hepsi aşağı yukarı aynı şekilde çalışıyor.
Ve bu kadar. Bitti. Bütün kayıt ve yükleme olayı bundan ibaret. Player sınıfımızın son hali tam olarak şöyle:
using UnityEngine; public class Player : MonoBehaviour { public string playerName = "Assign a name in the inspector"; public float playerHealth = 100f; private void Start() { // Oyun başladığında verileri yükler LoadData(); } private void OnDisable() { // Oyun kapandığında verileri kaydeder SaveData(); } private void SaveData() { var data = $"{playerName},{playerHealth.ToString()}"; var savePath = $"{Application.persistentDataPath}/Save.txt"; System.IO.File.WriteAllText(savePath, data); } private void LoadData() { var savePath = $"{Application.persistentDataPath}/Save.txt"; // Böyle bir dosyanın olup olmadığını kontrol et if (System.IO.File.Exists(savePath)) { // Dosyayı oku var text = System.IO.File.ReadAllText(savePath); // Veriyi ayır var dataParts = text.Split(','); // Değişkenleri ata playerName = dataParts[0]; playerHealth = float.Parse(dataParts[1]); } } }
Dersi bitirmeden önce bir ipucu vereyim: dosya uzantıları tek başına bir anlam ifade etmezler. Sadece dosyanın ne olduğu konusunda bir ipucu verirler. Dolayısı ile dilersek .txt uzantısından kurtulabiliriz. Veya kendimizce bir dosya uzantısı ekleyebiliriz. Save.txt yerine Save.cso (cso – çok süper oyun) yazabiliriz. Tamamen yaratıcılığınıza kalmış bir şey.
Bu yöntem çoğu kayıt sisteminin temeli olsa da veri sayısı arttıkça aynı PlayerPrefs gibi can sıkıcı bir hale gelebilir. Her bir değişkeni elle çözümlemek ve atamak sıkıntılı bir süreç. Neyse ki bunu bizler için otomatik olarak yapan birçok farklı metod var. Bu metodlardan ikinci derste bahsedeceğim!
Filed under: Programlama,Unity - @ August 13, 2022 6:34 pm
Tags: Unity, Programlama, Kayıt Sistemi