Learning etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Learning etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

23 Ocak 2017 Pazartesi

Learning uGaMa: Usage of Commands - Part2


Command:

Yapmak istediğiniz bazı işlemleri ayrı bir scrip içerisinde gerçekleştirebilirsiniz. Bu sayede Scriptler'i işlevlerine göre guruplandırabilirsiniz. Hangi işlevin nerede yapıldığını ve bu işlevlerde bir değişiklik yapılacağı zaman tek bir yerde değişiklik yapmış olmanızı sağlar. Bu işlevin farklı farklı çağıracağınız yerlerde (farklı scene, faklı med, hatta farklı commandlar gibi) bu işleve tekbir satırlar ulaşıp gerçekleştirilmesi sağlanır. Command'ları Context sınıfları içerisinde tanımlayabilirsiniz. İsteseniz Command'larla birlikte parametre gönderebilirsiniz. Commandlar içerisine gönderdiğiniz parametreleri yaratmış olduğunuz command içerisinde kullanabilirsiniz. Command'larda yapılan işlem tamamlandığında bu Command'ı çağırdığınız key ile mediatörler içerisinde dinleyebilirsiniz. Bu sayede bir çeşit event gibi kullanmış olursunuz.

Bu videoda anlattığım kodları aşağıda paylaşıyorum. Ayrıca unity package olarak şu link üzerinden indirip yaratmış olduğunuz boş bir projeye bu package'ı import edebilirsiniz.

https://github.com/CengizKuscu/LearningUGaMa/blob/master/part1%26part2.unitypackage

uGaMa için Link: https://github.com/CengizKuscu/uGaMa-v2.0/blob/master/uGaMa-v2.0.unitypackage



public enum AppEvent
{
    LOAD_SCENE,
    QUIT
}

using uGaMa.Context;

public class MainMenuContext : Context
{

 public override void Bindings()
 {
        mediatorMap.Bind<MainMenuView>().To<MainMenuMED>();

        commandMap.Bind(AppEvent.LOAD_SCENE).To<LoadSceneCMD>();
        commandMap.Bind(AppEvent.QUIT).To<QuitGameCMD>();
 }

 public override void UnBindings()
 {

 }
}

using uGaMa.Mediate;
using UnityEngine.UI;

public class MainMenuView : View
{
    public Button PlayBtn;
    public Button QuitBtn;
}

using UnityEngine;
using uGaMa.Mediate;

public class MainMenuMED : Mediator
{
    MainMenuView _view;

 // Use this for initialization
 public override void OnRegister()
 {
        _view = GetView() as MainMenuView;

        _view.PlayBtn.onClick.AddListener(PlayGameBtn);
        _view.QuitBtn.onClick.AddListener(QuitGameBtn);
 }

    private void QuitGameBtn()
    {
        Debug.Log("QuitGame");
        dispatcher.Dispatch(AppEvent.QUIT);
    }

    private void PlayGameBtn()
    {
        Debug.Log("PlayGame");
        dispatcher.Dispatch(AppEvent.LOAD_SCENE, AppScenes.LEVEL_1);
    }

    public override void OnRemove()
 {

 }
}

public class AppScenes
{
    public const string MAIN_MENU = "MainMenu";
    public const string CONTINUE_MENU = "ContinueMenu";
    public const string LEVEL_1 = "Level1";
}

using uGaMa.Command;
using UnityEngine;
using UnityEngine.SceneManagement;

public class LoadSceneCMD : Command
{
 public override void Execute(NotifyParam notify)
 {
        string param = notify.data as string;
        Debug.Log("LoadSceneCMD Execute : "+param);
        SceneManager.LoadScene(param);
    }
}

using uGaMa.Command;
using UnityEngine;

public class QuitGameCMD : Command
{

 public override void Execute(NotifyParam notify)
 {
        Debug.Log("QUIT CMD Execute");
        Application.Quit();
 }
}

14 Ocak 2017 Cumartesi

Learning uGaMa: Hello World - Part1

uGaMa (Unity Game Manager) Nedir?

uGaMa, Unity Game Manager'ın kısaltmasıdır. Unity3D'e çalışırken, örnek projeleri, kodları incelerken yapılan projelerde C#'ın kullanım şeklinin proje büyüdükçe karmaşaya sebep olabileceğini, kullanılan yapıların bir biri içine girdiğini. Yeni bir şeyler ekleyeceğim zaman bunun kontrolünü kaybedebileceğimi farkettim. Bu nedenle Unity3D için geliştirilmiş MVC kütüphaneleri üzerine araştırma yapmaya başladım. Bir kaç tane buldum. Kimisinin kullanım şekli hoşuma gitmedi. İstediğim yapıyı tam olarak sağlayamacağını farkettim. Biri tam istediğim gibiydi fakat mobil cihazlara build alırken hatalar oluşuyordu. Bunun üzerine kendi MVC framework'üm üzerinde çalışmaya başladım ve ortaya uGaMa çıktı.

uGaMa sayesinde projenizi modül modül geliştirebilirsiniz. Bu sayede bir projede birden fazla developer birbirini en az etkileyerek birbirinden bağımsız çalışma imkanına sahip olur. Yapmak istediğiniz değişiklikle ilgili nereye bakmanız gerektiğini bilip hızlı çözümler üretebilirsiniz. Birden fazla developerın çalıştığı projelerde developerları aynı standartlar içerisinde development yapmaya zorlayacağı için kodların okunabilirliğini arttırır.

uGaMa hakkında bu genel bilgileri verdikten sonra artık örnek bir proje üzerinde çalışabiliriz. Birlikte yapacağımız bu oyun, markete çıkma amacı gütmekten ziyade uGaMa ile nasıl programlama yapabileceğimizi öğrenme üzerine olacak.



Oyun Hakkında

Oyun için yeni bir proje dosyası oluşturmadan önce nasıl bir oyun olacağından bahsedeyim.

  • Oyun ekranında kullanıcının tıklayabileceği şekiller olacak. 
  • Oyun başladığında ilk olarak sistem kullanıcıya hangi şekillere hangi sırayla tıklayacağını gösterecek ve kullanıcının bu hareketleri tekrarlamasını isteyecek.
  • Kullanıcı bu hareketleri doğru yaparsa sistem yeni hareketler belirleyip bunu tekrarlamasını isteyecek.
  • Kullanıcı bu hareketleri yanlış yaparsa kullanıcının canı bir azalacak ve sistem yeni hareketler üretip bunları tekrarlamasını isteyecek. 
Oyun içi ekranların akış şeması aşağıdaki gibi olacak. Bu durumda 4 tane yeni Screen yaratacağız.
Bunlar:
1) SplashScreen
2) MainMenu
3) Level01
4) ContinueMenu
İleride farklı şekiller için yeni bir level dizaynı yapacağımız zaman bu dizaynlar ile ilgili Screenleri bu listeye ekleriz. Şimdilik tek bir Level Dizaynı üzerinden gidelim.

Hazırlık:

1. Projeye başlamadan önce uGaMa için hazırladığım unitypackage dosyasını indirelim. Bu pakete şu link üzerinden ulaşabilirsiniz:
https://github.com/CengizKuscu/uGaMa-v2.0/blob/master/uGaMa-v2.0.unitypackage  

2. Yeni bir Unity projesi (2D) açalım.

3. Bu paketi Assets 'e sağ tıklayım. Açılan Context Menu den Import Package > Custom Package... ı seçelim.

4. İndirmiş olduğumuz uGaMa-v2.0.unitypackage 'ını seçip package 'ı projemize import edelim.

Context:

Context'i, uGaMa'nın yapısının kurulduğu bir zemin, temel olarak tanımlayabiliriz. Contex içerisinde MVC bileşenlerimizin (Model, View, Controller) validation'larını yani tanımlamalarını yaparız. Bu tanımlamalar sayesinde birbirleri ile haberleşmeleri sağlanır, MVC'nin çalışması bu tanımlamalar etrafında gerçekleşir.
Context içerisinde, kullanacağımız Command'ları (Controller), Mediator - View ilişkisini (View), ve kullnacağımız Veri yapılarını (Model) tanımlarız.
Her Scene için mutlaka bir Context olmalıdır.
uGaMa da uygulama ilk kez çalıştırıldığında ilk olarak Bindings methodu çalışır. Bindings methodu içerisinde yukarıda bahsettim tanımlamalar yapılır.



 
using uGaMa.Context;
using UnityEngine;

public class SplashScreenContext : Context
{

 public override void Bindings()
 {
        Debug.Log("CONTEXT Bindings");
        mediatorMap.Bind<SplashScreenView>().To<SplashScreenMED>();
 }

 public override void UnBindings()
 {
        Debug.Log("CONTEXT UnBindings");
    }
}

View & Mediator:

View, kullanıcının uygulma/oyun içerisinde gördüğü, etkileşime girebildiği veya giremediği, değişimlerini gözlemleyebildiği nesnelerdir. Her View için bir tane Mediator yaratılır. Hangi View'in hangi Mediator ile ilişkilendiği Context içerisindeki Bindings Methodu içerisinde mutlaka tanımlanmalıdır.
Uygulama/Oyun ilk çalıştığında, View ait olduğu GameObject'e, ilişkilendirildiği Mediatorü ekler. Mediator'de ilk olarak OnRegister methodu çalışır. Bu methodu Awake veya Start methodları gibi düşünebilirsiniz. Burada GameObject ile ilgili ilk tanımlamaları (Initialize) yapabilirsiniz.
Mediator'ün eklenmiş olduğu GameObject Destroy edildiğinde Mediator içerisindeki OnRemove methodu çalışır.

using uGaMa.Mediate;
using UnityEngine.UI;

public class SplashScreenView : View
{
    public Text Message; 
}

using UnityEngine;
using uGaMa.Mediate;

public class SplashScreenMED : Mediator
{

    SplashScreenView _view;

 // Use this for initialization
 public override void OnRegister()
 {
        Debug.Log("MED OnRegister");
        _view = GetView() as SplashScreenView;

        _view.Message.text = "Hello World!";
 }

 public override void OnRemove()
 {
        Debug.Log("MED OnRemove");
    }
}

Learning uGaMa: Usage of Commands - Part2

9 Kasım 2016 Çarşamba

Unity3D: Save / Load Data(JSON)



Başlangıç

Unity3D de oyun/uygulama içinde veri kaydetmek istediğimizde Unity bize PlayerPrefs gibi bir seçenek sunuyor. Ben bundan farklı olarak .json dosyası oluşturmak ve buradan verileri okumakla ilgili bir örnek paylaşacağım.

Bu şekilde daha organize bir data yapısı kullanabilirsiniz.

Gereksinimler

NewtonSoft.Json : Bu linkden indireceğiniz dll dosyasını Assets>Plugins içine atınız. Yada ReadAndWriteJson.unitypackage linkinden indireceğiniz unitypackage dosyasını açmış olduğunuz boş bir projeye import edip oradan alabilir ve yapmış olduğum örneği inceleyebilirsiniz.


Yaptığım örnekde Scene'e, 2 tane InputField, 2 tane Button, 1 tane Text ekledim. Bir tane boş GameObject ekledim. GameObject için FileOperations adında bir tane script oluşturdum.


FileOperations.cs içinde UI elementleri için field ları oluşturalım.

using UnityEngine;
using System;
using System.Collections.Generic;
using UnityEngine.UI;
using System.IO;
using Newtonsoft.Json;

public class FileOperations : MonoBehaviour
{

    public Button LoadBtn;
    public Button SaveBtn;
    public Text text;

    
    private SaveData saveData;

    public InputField IdText;
    public InputField NameText;
}

Scene içerisinde bulunan ilgili UI elementlerini Hierarchy de FileOperations.cs da bulunan ilgili yerlere sürükleyip bırakalım. UI butonlar için ilgili event listenerları ekleyelim.

public void Awake()
{
    LoadBtn.onClick.AddListener(LoadGameBtnListener);
    SaveBtn.onClick.AddListener(SaveGameBtnListener);        
}

private void LoadGameBtnListener()
{
}

private void SaveGameBtnListener()
{
}

Save ve Read işlemlerini yapmak için Application.persistentDataPath kullanıyoruz. Kullanacağımız data dosyasının ismi SaveData.json olsun. Bu durumda dosya adresimiz aşağıdaki gibi olacak ve bunu Awake içine ekleyelim.

private string fileName;

public void Awake()
{
    .......
    fileName = Application.persistentDataPath + "/SaveData.json";
}

Application.persistentDataPath adresi PC için C:\Users\[UserName]\AppData\LocalLow\[CompanyName]\[ProductName] şeklindedir. Bu adresi kendi PC nizde  Debug.Log(Application.persistentDataPath) yazarak görebilirsiniz.

Şimdi SaveData.json dosyasının önceden yaratılıp yaratılmadığına bakmak için Awake içine ChechDataFile metodu nu çağıralım. Bu metod json dosyanız oyununuz/uygulamanız ilk çalıştırıldığında yaratılmadığı için yaratacak ve sonraki çalıştırmalarda yeni bir dosya yaratılmasını önleyecek.

public void Awake()
{
    .......
    ChechDataFile();
}

private void ChechDataFile()
{
    try
    {
        if(!File.Exists(fileName))
        {
            FileStream fs = File.Create(fileName);
            fs.Close();
        }
    }
    catch (Exception e)
    {
        Debug.Log("Exeption: " + e);
    }
}


Şimdi saklayacağımız veri ile ilgili scriptimiz için SaveData.cs yaratalım. Bu Script'i aşağıdaki gibi yazalım. Json Dosyamız bu scriptler üzerinde Serialize/Deserialize edilecek. Yani içeride kullanacağımız veri yapılarına dönüştürülecek. Burada InventoryItemlar'ı listeleyeceğiz. Her item'ın bir ID ve Name değeri olacak. Bu itemlar bir liste içerisinde tutulacak.

using System.Collections.Generic;

public class SaveData
{
    public List<InventoryItem> Items { get; set; }
}

public class InventoryItem
{
    public int ID { get; set; }
    public string Name { get; set; }
}


FileOperations.cs içerisine yaratılacak json dosyasını okuyup string değerini alacağımız Metodu ekleyelim.

private string saveDataJson;

private void ReadDataFile()
{
    saveDataJson = string.Empty;
    
    try
    {
        if(File.Exists(fileName))
        {
            saveDataJson = File.ReadAllText(fileName);
        }
    }
    catch (Exception e)
    {
        Debug.Log("Exeption: " + e);
    }
}


Load butonuna basıldığı zaman aşağıdaki işlemleri yapsın ve ekrana json dosyamızın içeriğini yazdırsın.
private void LoadGameBtnListener()
{
    ReadDataFile();

    text.text = saveDataJson;
}


Ekran üzerinde ID kısmına rakam ve Name kısmına isim yazdığımızda Save butonuna basacağız ve bu verileri json dosyamıza kaydedeceğiz. Aynı zamanda json dosyamızın son halini ekrana yazdıracağız.

private void SaveGameBtnListener()
{
    ReadDataFile();

    if(IdText.text == string.Empty || NameText.text ==string.Empty)
    {
        return;
    }

    int x = 0;

    if (Int32.TryParse(IdText.text, out x) == false)
    {
        return;
    }

    if (saveDataJson != string.Empty)
    {
        saveData = JsonConvert.DeserializeObject<SaveData>(saveDataJson);
    }
    else
    {
        saveData = new SaveData();
        saveData.Items = new List<InventoryItem>();
    }

    InventoryItem inventoryItem;

    inventoryItem = saveData.Items.Find(item =< item.ID == Int32.Parse(IdText.text));

    if(inventoryItem == null)
    {
        inventoryItem = new InventoryItem();
        inventoryItem.ID = Int32.Parse(IdText.text);
        inventoryItem.Name = NameText.text;
        saveData.Items.Add(inventoryItem);
    }
    else
    {
        //Update Data
        inventoryItem.Name = NameText.text;
    }
        
    saveDataJson = JsonConvert.SerializeObject(saveData);

    try
    {
        File.WriteAllText(fileName, saveDataJson);
    }
    catch (Exception e)
    {
        Debug.Log("Exeption: " + e);
    }

    LoadGameBtnListener();
}

Bu projenin çalışır halini ReadAndWriteJson.unitypackage linkinden indireceğiniz unitypackage dosyasını boş bir Unity projesi içine import edip inceleyebilirsiniz.

28 Ağustos 2016 Pazar

Design Patterns in Unity3D MVC



Merhabalar.

Unity3D içerisinde development yaparken karşımıza çıkabilecek sorunları ve bu sorunların çözüm yollarını MVC içerisinde nasıl çözebileceğimizi kısaca anlatmaya çalıştım. Bu bilgiler yine bir miktar ileri programlama bilgisi ve terminoloji hakkında bilgi sahibi olmayı gerektiriyor. Bu konuları dilimin döndüğünce sizlere anlatmaya çalıştım. Hatam olduysa affola. Umarım sizlere faydası olacak bilgilerdir. Zaman ayırdığınız için teşekkürler.

Aşağıda faydalı olabileceğini düşündüğüm linleri paylaşıyorum.

Observer Pattern
Unity Design Pattern
Design Pattern
Singleton Pattern
Observer Pattern 2

27 Ağustos 2016 Cumartesi

MVC Nedir?



Unity3D projelerinde ileri programlama yapmak için bir dizi eğitim videosu oluşturmaya karar verdim. vakit buldukça bu eğitimleri hazırlayıp buradan paylaşacağım.
İleride paylaşacağım eğitimlerde Unity3D için kendi geliştirmiş olduğum MVC Framework'ü uGaMa'yı ve uGaMa ile nasıl oyun programlayacağınız örnek kodlarla anlatmaya, kaynak kodları buradan paylaşmaya çalışağım.
Hazırlayacağım bu seri Unity3D de veya C# da ileri programlama bilgisinesahip olanlara hitap etmektedir.

uGaMa hakkında daha detaylı bilgiye buradan ulaşabilirsiniz.
Ayrıca MVC için burayıda incelebilirsiniz. Güzel anlatılmış.