Unity Log Manager Sistemi Oluşturma | I: Temel Log Gönderme ve UI

Bir süredir devam etmediğim, üç ay önce başlamış olduğum Trace’e bir Log Manager yazmaya başladım. Trace bir text-based olmasından dolayı bu oldukça mühim bir konu idi. Alt yapısını mimari olarak eksiksiz yapmaya çalışıyorum. Bu yüzden UI’ından, Log’larına kadar her şeyini yapmaya karar verdim. Unity’nin kendi UI sistemine bağlı kalmamaya kararlıyım. Her neyse, işe koyulalım. Öncelikle…

Bir süredir devam etmediğim, üç ay önce başlamış olduğum Trace’e bir Log Manager yazmaya başladım. Trace bir text-based olmasından dolayı bu oldukça mühim bir konu idi. Alt yapısını mimari olarak eksiksiz yapmaya çalışıyorum. Bu yüzden UI’ından, Log’larına kadar her şeyini yapmaya karar verdim. Unity’nin kendi UI sistemine bağlı kalmamaya kararlıyım.

Her neyse, işe koyulalım.

Öncelikle bir LogManager sınıfı oluşturmakla başladım. Ve elbette içerisinde Log’ları tuttuğum bir liste tutmalıydı. Sınırlı sayıda log tutacağım bu yüzden aslında bir stack de kullanabilirdim ancak elim çok List’e alışmış. Generic List’i yapıştırdım.

using UnityEngine;
using System.Collections.Generic;

class LogManager : ILog
{

    //TODO: Singleton Log Manager??
    //TODO: Add set log and use console.
    public static string log = "main log manager";
    public string staticLog = @" 
Font: OCR-A   Reflection: no   Adjustment: left   Stretch: no
                                               _____ ____    _      ____ _____ 
                                              |____ |___ \  / \    / _  |_   _|
                                                |_  |   | |/ _ \  | (_| | | |  
                                               ___| |___| / ___ \  > _  | | |  
                                              |_____|____/_/   \_\/_/ |_| |_|  
                                                                              ";
    [SerializeField]
    List<Log> logs = new List<Log>();

    public void sendLog(string text)
    {
        Log newLog = new Log();
        newLog.message = text;
        logs.Add(newLog);
    }


}

Yukarıdaki static log denemelerim aklınızı karıştırmasın. Onlar tamamen şov amaçlı yazdığım şeyler, konu ile alakasız. Log listesini şimdilik private tuttum ama Serialize olduğu için bu herhangi bir sıkıntı yaratmayacaktır.

Şimdi peki bu sendLog metodu nerden geliyor?

Yukarıda gördüğünüz gibi, ILog adında bir interface’im var. Bu interface içerisinde sendLog tanımlı. Metodun ise ne yaptığı aşikar. Gelen mesajları log olarak bastırmaya yarıyor.

Aaa evet bir de Log sınıfımız var tabi. Olmazsa olmaz.

using UnityEngine;

[System.Serializable]
public class Log
{
    public string message;

}

Log sınıfı yalnızca bundan ibaret. Şimdilik.

Evet şimdi, elimizde log var, bu logları yönetebileceğimiz bir manager da var. Peki biz bunları nasıl görücez? UI kısmına geliyoruz burda.

Benim yazmaya başlamış olduğum bir UIManager sınıfı var. Aslında oldukça dallandırıp budaklandırmak istiyordum bu sınıfı. Text’ler için ayrı olsun vs falan diye. Ancak şu an bu sınıf aşağıdaki gibidir.

using BaseKit;
using UnityEngine;
using UnityEngine.UI;

class UIManager: BaseObject
{
    [SerializeField]
    private Text textPrefab;
    [SerializeField]
    private Text staticTextPrefab;

    [SerializeField]
    private LogManager logManager = new LogManager();


    public override void onAwakeBaseObject()
    {
        Debug.Log("UI Manager awake");
    }

    public override void onUpdateBaseObject()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            logManager.sendLog("You pressed space key");
        }

    }
}

Deneme amacıyla öncelikle, input bağımlı bir şekilde yazdım.

Burada küçük bir parantez açmak istiyorum. Unity dışında kendi Update ve Start metotlarımızı yazmak çok sevdiğim, kodluyoruz sayesinde tanışma fırsatı bulduğum Halil hocamızın tavsiyesiydi. Ben de kullandıkça oldukça faydalı bulduğum için her projemde yer vermeye başladım. BaseKit tamamen ona aittir. O yüzden teşekkürlerimi sunuyorum. Teşekkürler Halil Coşgun. 🙂

Şimdi her space’e bastığımda sonsuz bir şekilde Log oluşturmaya başlayacak ki bu istenmeyen ve zamanla List şişeceği için muhtemelen (kesin) bir stackoverflow hatasıyla karşılaşma ihtimalimizin olduğu durum. Hata atmasa bile oyun oldukça yavaş olacaktır. Sıfıra yakın grafiği olan bir oyunun yavaş olması saçmalıktan başka bir şey değil. Bu yüzden bir List kısıtlaması yapmam şart.

Basit bir koşul ekliyorum esasında. Aşağıdaki gibi bir kod şimdilik işimi görür.

 [SerializeField]
    List<Log> logs = new List<Log>();
    public int maxMessages = 25;

    public void sendLog(string text)
    {
        if (logs.Count >= maxMessages)
            logs.Remove(logs[0]);

        Log newLog = new Log();
        newLog.message = text;
        logs.Add(newLog);
    }

Maximum mesaj sayısını 25 belirledim. Bunu ekran size’ını düşünüp belirlemedim ama sonrası için bir TODO olarak ekleniyor. Çünkü ekranda logların devamlı akmasını istiyorum. Boş bir ekran görmek değil.

Unity’e döndüğümde ilk yaptığım şey ekrana bir Scroll View eklemek oluyor aşağıdaki gibi.

Ben genelde tek Canvas içerisinde çalışıyorum ama dilenirse elbette ayrı bir Canvas içerisine alınabilir. Aslında bence en doğrusu Canvas’ın da bir GameObject içerisine sarılmış olması ancak henüz bir düzenleme orda yapmadım.

Her neyse, ScrollView’u ekranda yerleştiriyorum ve bir kaç tasarımla birleştirmek için küçük uğraşlar veriyorum. Neticesi aşağıdaki gibi.

Scroll Image

Benim için son görünüm bu şekilde. Ben ScrollView’un altına bir de Text Input ekledim ve onu ekranıma göre renklendirdim. Şimdi Bu ScrollView’ın içerisinde Log’larımızın akması için bir Layout koyuyorum.

Context içerisine bir adet Vertical Layout Group ekleyip, Aligment’ını Lower Left yapıyorum. Pivot ve Anchor’ını Bottom Left seçiyorum. Böylelikle şimdi içine ekleyeceğim Item’lar en altta belirip yukarıya doğru ilerlemeli.

Şimdi bunu kodda kontrol edilebilmek için UI Manager sınıfına dönüp, İkisinin referansını oluşturuyorum.

    public GameObject logPanel, textObject;

Bu şekilde UIManager sınıfına ekledim. Bunları Inspector yardımıyla assign edeceğim. (Muhtemelen iyi bir yol değil, şimdilik okey)

Text objesi için bir adet prefab oluşturmam lazım. Rengini yeşile fix edip bir text oluşturuyorum ve prefab’ini UIManager’a assign ediyorum.

UI hazır, Log kısmı da tamamdır. Sonraki aşamada bunları nasıl Display edeceğime bakacağım.

Okuduğunuz için teşekkürler. 🙂

 

KAYNAK: ÖZGE KOCAOĞLU