Merhaba arkadaşlar. İlk blogumla karşınızdayım. Bu ilk blog da, Unity için mysql score sistemi nasıl yapılır onu anlatacağım. Şunu başta söylemeliyim ki yapacağımız sistem online olacağı için mutlaka bir hosting e ihtiyacımız olacak. Deneme amaçlı WampServer ya da Xampp gibi local sunucu programlarını kullanabilirsiniz.
İlk yapacağımız şey MySql veritabanımızda tablomuzu oluşturmak. Ben phpMyAdmin kullandığım için tablo oluşturmayı onun üzerinden göstereceğim. phpMyAdmin panelimize giriş yaptıktan sonra hemen soldan kullanacağımız veritabanımızı seçip tablo oluşturuyoruz. Benim yapacağım score panelinde sadece sıra, kullanıcı adı ve score olacak. Bu yüzden Sütun sayısı kısmına 3 yazıp Git diyorum.
Şimdi karşımıza 3 satırdan oluşan bir tablo çıkıyor. Bu tablonun birinci satırın birinci sütununa(yani Adı sütunu) id yazıyoruz. Bu satırımızın ikinci sütunu yani Türü sütunumuzun INT olduğuna dikkat edelim.
MySql’in bize sunduğu AUTO_INCREMENT özelliği sayesinde tabloya veri kayıt ederken sıra numarasını biz yazmadan otomatik sıra numarası verip kayıt edebiliriz. Bu özelliği kullanmak için birinci satırımızın son sütunundan bir önceki sütun olan AUTO_INCREMENT(A_I olarak ta geçebilir)‘ı aktif ediyoruz.
Şimdi ikinci satırımıza geçtik. Adı sütununa username yazıp Türü sütunundan ise VARCHAR’ı seçiyoruz. Bunu seçmemizin sebebi bu kısma string ifadelerin gelmesidir.
Üçüncü satırımıza geçtik. Burada da Adı sütunumuza score yazıp Türü INT olarak seçiyoruz. Tablonun son hali:
(*)Bütün satırların uzunluk değeri 255 olacak.
Bilgileri doğru bir şekilde girdiyseniz Artık Git tuşuna tıklayıp tabloyu kayıt edebilirsiniz.
Şimdi geldik oyun ile veritabanı arasındaki köprüyü kuracak olan PHP ye. İlk önce neden php kullanacağız onu cevaplıyayım. Arada köprü kurmadan C# ile doğrudan veritabanına bağlanamaz mıyız? Evet tabi ki yapabiliriz. Ama bu çok güvensiz olur. Veritabanına bağlanırken “sunucumuzun ip adresini”, “kullanıcı adımızı”, “şifremizi”, “veritabanımızın adını” ve”tablomuzun adını” kaynak kodlarımızda kullanmak zorunda kalacağız. Yayınlanmış uygulamanızın/programınızın kaynak kodlarını ele geçirmek bu dönemde çok basit. Veritabanı bilgileriniz kötü kişilerin eline geçerse, istediği her veriyi ekleyebilir, güncelleyebilir ve hatta silebilir. Veritabanı ile kodlarımız arasında php köprüsü kurarsak, bilgilerimiz php sayfasında şifrelenir ve bu buyuk sorunun üstesinden geliriz.
Şimdi masaüstünde yada başka bir dizinde bir php dosyası oluşturun(Boş bir not defteri oluşturup uzantısını .txt den .php ye değiştirerek yapabilirsiniz). Tavsiyem bir klasör içinde oluşturun. Maksat dosyayı hostingimize attığımızda diğer dosyalarla karışmasın. Php dosyamızın ismini ScoreTable olarak değiştirip alttaki kodları olduğu gibi içine yapıştırın:
<?php
//Veritabanımzıa bağlanmak için boşluklara sırasıyla hostumuzu, kullanıcı adımızı, şifremizi ve veritabanı adımızı yazıyoruz
$mysqli = mysqli_connect("localhost","KullaniciAdi","Sifre","VeritabaniAdi");
//Bağlantıda hata olup olamdığını kontrol ediyoruz
if (mysqli_connect_errno())
{
//Hata varsa, hatayı ekrana basıp kodları durduruyoruz
echo "Connection error: ".mysqli_connect_error();
exit();
}
// 'action' adında bir veri postlanırsa ve bu verinin değeri 'AddScore' olursa
if ($_REQUEST['action'] == "AddScore")
{
//Post edilmiş olan 'username' verisini bu değişkene atıyoruz
$username = $_POST["username"];
//Post edilmiş olan 'score' verisini bu değişkene atıyoruz
$score = $_POST["score"];
//Oyundan post edilen kullanıcı adının veritabanında daha önce kayıtlı olup olmadığını öğrenmek için sorgu yapıyoruz
$QueryUser = $mysqli->query("SELECT * FROM ScoreTable WHERE (username = '$username')");
if (mysqli_num_rows($QueryUser) > 0)
{//Kullanıcı zaten kayıtlı, score u güncellenecek
//Veritabanında kayıtlı olan score u değişkene atıyoruz
$cur_score = intval(mysqli_fetch_assoc($QueryUser)['score']);
//Oyundan post edlien score değerin, veritabanda kayıtlı olan score dan büyükse
if($score>$cur_score)
{
if ($mysqli->query("UPDATE ScoreTable SET score = '$score' WHERE username = '$username'"))
{//Veri güncelleme başarılı, ekrana başarılı yazdır
echo "success";
}
else
{//Veri güncelleme başarısız, hatayı ekrana yazdır
echo "Error:".mysqli_error($mysqli);
}
}
else
{//Score, veritabanında kayıtlı olan score dan küçük
echo "Score is less than registered score";
}
}
else
{//Kullanıcı kayıt edilip score u eklenecek
if ($mysqli->query("INSERT INTO ScoreTable (username, score) VALUES ('$username','$score')"))
{//Veri ekleme başarılı, ekrana başarılı yaz
echo "success";
}
else
{//Veri ekleme başarısız, hatayı ekrana yazdır
echo "Error:".mysqli_error($mysqli);
}
}
}
// 'action' adında bir veri postlanırsa ve bu verinin değeri 'GetScores' olursa
else if ($_REQUEST['action'] == "GetScores")
{
//Veritbanında score u büyükten küçüğe sıralayarak ilk '100' kişiyi çek
$QueryScores= $mysqli->query("SELECT * FROM ScoreTable Order By score DESC LIMIT 100");
//Veritbanamızda daha veri kayıt edildiyse
if (mysqli_num_rows($QueryScores) > 0)
{
while ($row = mysqli_fetch_assoc($QueryScores))
{
//Verileri "," ile ayırarak parse ediyoruz ve ekrana yazdırıyoruz
echo $row['username'].",".$row['score'].",";
}
}
else
{//Kayıtlı veri bulunamadı
echo "no_data";
}
}
?>
PHP dosyanızı hostinge atma vakti. FileZilla ya da herhangi bir FTP programı kullanarak php dosyanızı hostinge bir dizine atın(Benim php min yolu: https://yudegames.com/Tutorials/ScoreTable/ScoreTable.php). Sonra ise php nizi bir tarayıcıda çalıştırın. Eğer benim gibi boş bir sayfa ile karşılaşırsanız doğru yoldasınız.
(*)PHP dosyasında veritabanı bilgilerimizi değiştirmeyi unutmuyoruz!
Geldik Unity kısmına. Şimdi Score Table adında yeni bir Unity projesi açıyoruz.
Proje açıldıktan sonra klavyeden Ctrl + S ye basarak sahneyi kayıt ediyoruz. Sonra boş bir Game Object oluşturup adını Score Manager yapıyoruz.
Bu oluşturduğumuz boş objeye, ScoreManager adında bir script oluşturup ekleyeceğiz.
Scripti oluşturduktan sonra alttaki kodları olduğu gibi içine yapıştırın:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Score_Class
{
public int _rank;
public string _username;
public int _score;
public Score_Class(int _rank, string _username, int _score)
{
this._rank = _rank;
this._username = _username;
this._score = _score;
}
}
public class ScoreManager : MonoBehaviour
{
//Score ların toplantığı liste
public List<Score_Class> Scores = new List<Score_Class>();
//Mevcut Score un tutulduğu değişken
private int score = 100;
//GUI için kullanıcı adı
private string usernameField = "Set username...";
//GUI için scroll pozisyonu
private Vector2 scrollPosition = Vector2.zero;
//GUI paneller için
private bool isMainPanel = true;
private bool isUsernamePanel = false;
private bool isScorePanel = false;
private bool isLoading = false;
// PHP nin bulunduğu yol. Burayı kendi PHP nizin yolu ile değiştireceksiniz
private string PHP_path = "https://yudegames.com/Tutorials/ScoreTable/ScoreTable.php";
private void Start()
{
//Score ların toplanacağı listeyi sıfırlama
Scores.Clear();
//Daha önce PlayerPrefs de score kayıtlıysa değişkeni kayıtlı veriye eşitle, değilse default(100)değeri kullan
score = PlayerPrefs.GetInt("score") == 0 ? score : PlayerPrefs.GetInt("score");
}
private void OnGUI()
{
//GUI style ları
var GS1 = new GUIStyle(GUI.skin.box);
var GS2 = new GUIStyle(GUI.skin.button);
var GS3 = new GUIStyle(GUI.skin.button);
GS1.fontSize = FontSizeForAllResolations(60f);
GS2.fontSize = FontSizeForAllResolations(43f);
GS3.fontSize = FontSizeForAllResolations(35f);
//Ana Panel
if (isMainPanel)
{
//Score u ekrana yazdır
GUI.Box(RectForAllResolations(new Rect(34.3f, 35f, 28.8f, 10.3f)), string.Format("Score : {0}", score), GS1);
//Score ekleme buttonu
if (GUI.Button(RectForAllResolations(new Rect(31.4f, 50.3f, 16.4f, 10.3f)), "(+)\nAdd", GS2))
{
AddScore(50);
}
//Score düşürme buttonu
if (GUI.Button(RectForAllResolations(new Rect(49.5f, 50.3f, 16.4f, 10.3f)), "(-)\nReduce", GS2))
{
AddScore(-50);
}
//Scorları al butonu
if (GUI.Button(RectForAllResolations(new Rect(31.37f, 62.3f, 35, 10.3f)), "Get Online Score Panel", GS2))
{
if (PlayerPrefs.GetString("RegisteredUsername").Length > 1)
{
//Daha önce kullanıcı adı girildiyse 'ReportScore' fonksiyonunu çağır.
//Bu fonksiyonda mevcut score veritabanına gönderiliyor
isMainPanel = false;
isUsernamePanel = false;
isScorePanel = true;
StartCoroutine(ReportScore(PlayerPrefs.GetString("RegisteredUsername")));
}
else
{
//Daha önce kullanıcı adı girilmediyse, kullanıcı adı panelini göster
isMainPanel = false;
isUsernamePanel = true;
isScorePanel = false;
}
}
}
//Kullanıcı adı paneli
if (isUsernamePanel)
{
//kullanıcı adı metin kutusu
usernameField = GUI.TextField(RectForAllResolations(new Rect(32.68f, 34.86f, 30.55f, 8.5f)), usernameField, GS2);
//Submit(Gönder) buttonu
if (GUI.Button(RectForAllResolations(new Rect(32.7f, 44.8f, 30.53f, 8.24f)), "Submit", GS2))
{
//kullanıcı adı boş değilse ve (,) içermiyorsa ve (.) içermiyorsa ve boşluk içermiyorsa
if (usernameField.Length > 0 && !usernameField.Contains(",") && !usernameField.Contains(".") && !usernameField.Contains(" "))
{
//'ReportScore' fonksiyonunu çağır. Bu fonksiyonda mevcut score veritabanına gönderiliyor
StartCoroutine(ReportScore(usernameField));
}
else
{//Aksi durumda konsolda hata verdir
Debug.LogError("Username incorrect!");
}
}
//Geri
if (GUI.Button(RectForAllResolations(new Rect(0, 0, 15, 15)), "Back", GS2))
{
isUsernamePanel = false;
isMainPanel = true;
isScorePanel = false;
}
}
//Score Paneli
if (isScorePanel)
{
//GUI için için scroll ve pozisyonu
scrollPosition = GUI.BeginScrollView(RectForAllResolations(new Rect(26.54f, 30.6f, 48.25f, 40.3f)), scrollPosition, RectForAllResolations(new Rect(0, 0, 45, 9f * (Scores.Count + 1))));
for (int i = 0; i < Scores.Count; i++)
{
//'Scores' listesinde kayıtlı olan veri sayısı kadar button oluştur ve bu buttonlara score bilgilerini yazdır
GUI.Button(RectForAllResolations(new Rect(1, i * 10, 45, 8.9f)), string.Format("{0}) {1} >>> {2}", Scores[i]._rank, Scores[i]._username, Scores[i]._score), GS3);
}
//Scroll sonu
GUI.EndScrollView();
//Geri
if (GUI.Button(RectForAllResolations(new Rect(0, 0, 15, 15)), "Back", GS2))
{
isUsernamePanel = false;
isMainPanel = true;
isScorePanel = false;
}
}
//Loading
if (isLoading)
{
GUI.Box(new Rect(0, 0, Screen.width, Screen.height), "LOADING...", GS1);
}
}
//Bu fonksiyonda mevcut score veritabanına gönderiliyor
private IEnumerator ReportScore(string _username)
{
Scores.Clear(); //Listeyi sıfırla
isLoading = true;//Loading i aktifleştir
string url = PHP_path;// PHP nin bulunduğu yol
WWWForm form = new WWWForm();//Verileri postlamak için Form
form.AddField("action", "AddScore");//Postlanacak veri
form.AddField("username", _username);//Postlanacak veri
form.AddField("score", score);//Postlanacak veri
WWW www = new WWW(url, form);//İsteği gönder
yield return www;//Cevap bekle
Debug.Log(www.text);//Cevabı konsola yazdır
PlayerPrefs.SetString("RegisteredUsername", _username);//Kullanıcının kayıt yaptığını playerprefs ile hafızada tut
//Kayıt başarılı, Score pencerisini aç
isLoading = true;
isMainPanel = false;
isUsernamePanel = false;
isScorePanel = true;
//Score ları almak için 'GetScores' fonksiyonunu çağır
StartCoroutine(GetScores());
}
//Bu fonksiyonda Veritabanından score lar çekiliyor
private IEnumerator GetScores()
{
isLoading = true;//Loading i aktifleştir
string url = PHP_path;// PHP nin bulunduğu yol
WWWForm form = new WWWForm();//Verileri postlamak için Form
form.AddField("action", "GetScores");//Postlanacak veri
WWW www = new WWW(url, form);//İsteği gönder
yield return www;//Cevap bekle
Debug.Log(www.text);//Cevabı konsola yazdır
isLoading = false;//Loading i deaktif et
string received = www.text.Substring(0, www.text.Length - 1);// PHP den gelen verinin son karakterini(',') silerek bu değişkene aktar
string[] received_array = received.Split(',');//verileri virgül(,) ile ayır
int _count = received_array.Length / 2; //PHP den gelen veriler sadece 'username' ve 'score' olduğu için gelen score sayısını bulmak için 2 ye bölüyoruz
int _index = 0;
for (int i = 0; i < _count; i++)
{
//'Scores' listesine score ekle
Scores.Add(new Score_Class(i + 1, received_array[0 + _index], int.Parse(received_array[1 + _index])));
_index += 2;
}
}
//Deneme amaçlı kendi score umuzu güncellemek için score ekleme/çıkarma fonksiyonu
private void AddScore(int _value)
{
score += _value;
PlayerPrefs.SetInt("score", score);
}
//GUI ların bütün çözünürlüklere uyması için
private Rect RectForAllResolations(Rect _rect)
{
return new Rect(_rect.x * Screen.width * 0.01f, _rect.y * Screen.height * 0.01f, _rect.width * Screen.width * 0.01f, _rect.height * Screen.height * 0.01f);
}
//GUI ların yazı büyüklüklerinin bütün çözünürlüklere uyması için
private int FontSizeForAllResolations(float _size)
{
return Mathf.RoundToInt(_size * Screen.width / (1920f));
}
}
Kodlarımız buraya kadar. Scripti olduğu gibi hiç değişiklik yapmadan derleyip çalıştırırsanız, benim kurduğum score sistemine bağlanıp, score ekleyip, güncelleyip, veritabanında kayıtlı olan bütün score ları görebilirsiniz.
Kendi veritabanınızı kullanmak için scriptte üstlerde yer alan PHP_path değişkenini, kendi PHP yolunuz ile değiştirmeyi Unutmayın.
Metin ile zor izah edileceğinden dolayı UI yerine GUI kullandım. Bunu Canvas kullanarak UI a çevirmek gayet basit. Az kodlama bilginiz varsa uydurabilirsiniz. Tek yapmanız gereken Scores listesinin içeriğini UI elementlerine ve özellikle text lere dökmek.
Bu tutorial ımızın sonuna geldik. Yaptığımız score sistemi çok basit bir sistem di. Bunu geliştirip bir Login/Register sistemine entegre edebilir hatta facebook ve google gibi API ları kullanarak score sistemini onlara uyumlu çalışabilecek hale getirebilirsiniz.
Yaşayacağınız sorunları Facebook adresimizden bana ulaşarak danışabilirsiniz. Kolay gelsin.
Ekran görüntüleri:
Sign up for our e-mail newsletter and stay informed for what’s next on the horizon.
Copyright © 2021, Yude Entertainment. All Rights Reserved.