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