MVC ile Unity: Oyun Geliştirmenizin Seviyesini Nasıl Yükseltebilirsiniz?

Yayınlanan: 2022-03-11

İlk kez programcılar genellikle klasik Hello World programıyla ticareti öğrenmeye başlar. Oradan, daha büyük ve daha büyük görevler takip etmek zorunda. Her yeni zorluk, eve önemli bir ders verir:

Proje ne kadar büyükse, spagetti o kadar büyük olur.

Yakında, büyük veya küçük ekiplerde, kişinin pervasızca istediği gibi yapamayacağını görmek kolaydır. Kod korunmalıdır ve uzun süre dayanabilir. Çalıştığınız şirketler, iletişim bilgilerinizi arayarak kod tabanını her düzeltmek veya geliştirmek istediklerinde (ve siz de onlardan bunu istemezsiniz) size soramazlar.

Bu nedenle yazılım tasarım kalıpları mevcuttur; bir yazılım projesinin genel yapısını dikte etmek için basit kurallar empoze ederler. Bir veya daha fazla programcının büyük bir projenin temel parçalarını ayırmasına ve bunları standart bir şekilde düzenlemesine yardımcı olarak, kod tabanının bilinmeyen bir kısmıyla karşılaşıldığında kafa karışıklığını ortadan kaldırır.

Bu kurallar, herkes tarafından takip edildiğinde, eski kodun daha iyi korunmasını ve gezinmesini ve yeni kodun daha hızlı eklenmesini sağlar. Geliştirme metodolojisini planlamak için daha az zaman harcanır. Sorunlar tek bir şekilde gelmediğinden, gümüş kurşun tasarım deseni yoktur. Kişi her kalıbın güçlü ve zayıf noktalarını dikkatlice düşünmeli ve eldeki zorluk için en uygun olanı bulmalıdır.

Bu eğitimde, popüler Unity oyun geliştirme platformuyla ve oyun geliştirme için Model-View-Controller (MVC) modeliyle olan deneyimimi ilişkilendireceğim. Yedi yıllık geliştirme sürecimde, oyun geliştirme spagettisinden aldığım adil payla boğuştuktan sonra, bu tasarım modelini kullanarak harika bir kod yapısı ve geliştirme hızı elde ettim.

Unity'nin temel mimarisini, Entity-Component modelini biraz açıklayarak başlayacağım. Sonra MVC'nin bunun üzerine nasıl oturduğunu açıklamaya devam edeceğim ve örnek olarak küçük bir sahte proje kullanacağım.

Motivasyon

Yazılım literatüründe çok sayıda tasarım modeli bulacağız. Bir dizi kuralları olsa da, geliştiriciler, kalıbı kendi özel sorunlarına daha iyi uyarlamak için genellikle biraz kural esnemesi yapacaklardır.

Bu "programlama özgürlüğü", yazılım tasarlamak için henüz tek ve kesin bir yöntem bulamadığımızın kanıtıdır. Bu nedenle, bu makale sorununuz için nihai çözüm olmayı değil, daha çok iki iyi bilinen kalıbın faydalarını ve olanaklarını göstermeyi amaçlamaktadır: Varlık-Bileşen ve Model-Görünüm-Denetleyici.

Varlık-Bileşen Kalıbı

Varlık-Bileşen (EC), önce uygulamayı oluşturan öğelerin hiyerarşisini (Varlıklar) tanımladığımız ve daha sonra her birinin içereceği özellikleri ve verileri (Bileşenler) tanımladığımız bir tasarım modelidir. Daha "programcı" terimleriyle, bir Varlık, 0 veya daha fazla Bileşen dizisine sahip bir nesne olabilir. Bir Varlığı şöyle tasvir edelim:

 some-entity [component0, component1, ...]

İşte basit bir EC ağacı örneği.

 - app [Application] - game [Game] - player [KeyboardInput, Renderer] - enemies - spider [SpiderAI, Renderer] - ogre [OgreAI, Renderer] - ui [UI] - hud [HUD, MouseInput, Renderer] - pause-menu [PauseMenu, MouseInput, Renderer] - victory-modal [VictoryModal, MouseInput, Renderer] - defeat-modal [DefeatModal, MouseInput, Renderer]

EC, çoklu kalıtım problemlerini hafifletmek için iyi bir modeldir; burada karmaşık bir sınıf yapısı, aynı temel A sınıfına sahip iki sınıf B ve C'yi miras alan bir D sınıfının çakışmalara neden olabileceği elmas problemi gibi problemler ortaya çıkarabilir. B ve C, A'nın özelliklerini farklı şekilde değiştirir.

GÖRÜNTÜ: ELMAS SORUNU

Bu tür sorunlar, kalıtımın sıklıkla yoğun olarak kullanıldığı oyun geliştirmede yaygın olabilir.

Özellikleri ve veri işleyicileri daha küçük Bileşenlere bölerek, birden fazla mirasa dayanmadan farklı Varlıklara eklenebilir ve yeniden kullanılabilirler (bu arada, Unity tarafından kullanılan ana diller olan C# veya Javascript'in bir özelliği bile değildir) ).

Varlık Bileşeninin Yetersiz Kaldığı Yer

OOP'nin bir seviye üzerinde olan EC, kod mimarinizi birleştirmenize ve daha iyi düzenlemenize yardımcı olur. Ancak büyük projelerde hala “fazla özgürüz” ve kendimizi bir “özellik okyanusu” içinde bulabilir, doğru Varlıkları ve Bileşenleri bulmakta veya nasıl etkileşime girmeleri gerektiğini bulmakta zorlanabiliriz. Belirli bir görev için Varlıkları ve Bileşenleri birleştirmenin sonsuz yolu vardır.

GÖRÜNTÜ: EC ÖZELLİK OCEAN

Bir karışıklığı önlemenin bir yolu, Varlık-Bileşeninin üstüne bazı ek yönergeler uygulamaktır. Örneğin, yazılım hakkında düşünmeyi sevdiğim bir yol, onu üç farklı kategoriye ayırmaktır:

  • Bazıları ham verileri işler, yaratılmasına, okunmasına, güncellenmesine, silinmesine veya aranmasına izin verir (yani, CRUD kavramı).
  • Diğerleri, diğer öğelerin etkileşime girmesi için arabirimi uygular, kapsamlarıyla ilgili olayları algılar ve meydana geldiklerinde bildirimleri tetikler.
  • Son olarak, bu bildirimleri almaktan, iş mantığı kararları vermekten ve verilerin nasıl manipüle edilmesi gerektiğine karar vermekten bazı unsurlar sorumludur.

Neyse ki, zaten tam olarak bu şekilde davranan bir modelimiz var.

Model-Görünüm-Denetleyici (MVC) Modeli

Model-View-Controller modeli (MVC) yazılımı üç ana bileşene ayırır: Modeller (Veri CRUD), Görünümler (Arayüz/Algılama) ve Kontrolörler (Karar/Eylem). MVC, ECS veya OOP üzerinde bile uygulanabilecek kadar esnektir.

Oyun ve UI geliştirme, bir kullanıcının girdisini veya diğer tetikleyici koşulları beklemek, bu olaylarla ilgili bildirimi uygun bir yere göndermek, yanıt olarak ne yapılacağına karar vermek ve verileri buna göre güncellemek gibi olağan bir iş akışına sahiptir. Bu eylemler, bu uygulamaların MVC ile uyumluluğunu açıkça göstermektedir.

Bu metodoloji, yazılım planlamasına yardımcı olacak ve yeni programcıların daha büyük bir kod tabanında bile gezinmesine izin verecek başka bir soyutlama katmanı sunar. Geliştiriciler, düşünme sürecini veri, arayüz ve kararlara bölerek, işlevsellik eklemek veya düzeltmek için aranması gereken kaynak dosyalarının sayısını azaltabilir.

Birlik ve EC

Önce Unity'nin bize sunduğu şeylere daha yakından bakalım.

Unity, tüm Varlıkların GameObject örnekleri olduğu ve onları "görünür", "hareketli", "etkileşimli" vb. kılan özelliklerin Component öğesini genişleten sınıflar tarafından sağlandığı EC tabanlı bir geliştirme platformudur.

Unity editörünün Hiyerarşi Paneli ve Denetçi Paneli , uygulamanızı bir araya getirmek, Bileşenleri eklemek, başlangıç ​​durumlarını yapılandırmak ve oyununuzu normalden çok daha az kaynak koduyla önyüklemek için güçlü bir yol sağlar.

EKRAN GÖRÜNTÜSÜ: HİYERAŞİ PANELİ
Sağda dört GameObject içeren Hiyerarşi Paneli

EKRAN GÖRÜNTÜSÜ: DENETÇİ PANELİ
GameObject bileşenlerine sahip Denetçi Paneli

Yine de, tartıştığımız gibi, "çok fazla özellik" sorununa çarpabilir ve kendimizi devasa bir hiyerarşi içinde bulabiliriz, özelliklerin her yere dağılmış olması, bir geliştiricinin hayatını çok daha zor hale getirir.

MVC tarzında düşünürsek, bunun yerine, nesneleri işlevlerine göre bölerek, uygulamamızı aşağıdaki örnekte olduğu gibi yapılandırarak başlayabiliriz:

EKRAN GÖRÜNTÜSÜ: UNITY MVC ÖRNEK YAPISI

MVC'yi Oyun Geliştirme Ortamına Uyarlama

Şimdi, MVC ile Unity projeleri oluştururken karşılaştığım benzersiz durumlara uyarlamaya yardımcı olan genel MVC modeline iki küçük değişiklik sunmak istiyorum:

  1. MVC sınıfı referansları, kod boyunca kolayca dağılır. - Unity içinde, geliştiricilerin genellikle örnekleri erişilebilir kılmak için etrafa sürükleyip bırakmaları veya GetComponent( ... ) gibi hantal bulma ifadeleriyle onlara ulaşmaları gerekir. - Unity çökerse veya bir hata tüm sürüklenen referansları ortadan kaldırırsa, kayıp referans cehennemi ortaya çıkacaktır. - Bu, Uygulamadaki tüm örneklere ulaşılabileceği ve kurtarılabileceği tek bir kök referans nesnesine sahip olmayı gerekli kılar.
  2. Bazı öğeler, yüksek oranda yeniden kullanılabilir olması gereken ve doğal olarak üç ana Model, Görünüm veya Denetleyici kategorisinden birine girmeyen genel işlevleri kapsar. Bunlara basitçe Components demeyi seviyorum. Bunlar ayrıca Varlık-Bileşen anlamında “Bileşenlerdir” ancak MVC çerçevesinde yalnızca yardımcı olarak hareket ederler. - Örneğin, nesneleri yalnızca belirli bir açısal hızla döndüren ve hiçbir şey bildirmeyen, depolamayan veya karar vermeyen bir Rotator Bileşen.

Bu iki sorunu hafifletmeye yardımcı olmak için AMVCC veya Application-Model-View-Controller-Component adını verdiğim değiştirilmiş bir model buldum.

GÖRÜNTÜ: AMVCC ŞEMA

  • Uygulama - Uygulamanıza tek giriş noktası ve tüm kritik örneklerin ve uygulamayla ilgili verilerin bulunduğu kapsayıcı.
  • MVC - Bunu şimdiye kadar biliyor olmalısınız. :)
  • Bileşen - Yeniden kullanılabilen küçük, kapsamlı komut dosyası.

Bu iki değişiklik, onları kullandığım tüm projeler için ihtiyaçlarımı karşıladı.

Örnek: 10 Sıçrama

Basit bir örnek olarak, AMVCC modelinin temel öğelerini kullanacağım 10 Bounces adlı küçük bir oyuna bakalım.

Oyun kurulumu basittir: SphereCollider ve Rigidbody ("Play"den sonra düşmeye başlayacak olan bir Ball ), zemin olarak bir Cube ve AMVCC'yi oluşturmak için 5 komut dosyası.

hiyerarşi

Komut dosyası oluşturmadan önce, genellikle hiyerarşiden başlarım ve sınıfımın ve varlıklarımın bir taslağını oluştururum. Daima bu yeni AMVCC stilini takip ediyoruz.

EKRAN GÖRÜNTÜSÜ: HİYERARŞİ OLUŞTURMA

Gördüğümüz gibi, GameObject view tüm görsel öğeleri ve ayrıca diğer View komut dosyalarına sahip olanları içerir. Küçük projeler için model ve controller GameObjects, genellikle yalnızca ilgili komut dosyalarını içerir. Daha büyük projeler için, daha spesifik komut dosyalarına sahip GameObjects içereceklerdir.

Projenizde gezinen biri aşağıdakilere erişmek istediğinde:

  • Veri: application > model > ...
  • Mantık/İş Akışı: application > controller > ...
  • Oluşturma/Arayüz/Algılama: application > view > ...

Tüm ekipler bu basit kuralları takip ederse, eski projeler bir sorun haline gelmemelidir.

Component kapsayıcısı olmadığını unutmayın, çünkü tartıştığımız gibi, bunlar daha esnektir ve geliştiricinin boş zamanlarında farklı öğelere eklenebilir.

komut dosyası

Not: Aşağıda gösterilen komut dosyaları, gerçek dünya uygulamalarının soyut versiyonlarıdır. Ayrıntılı bir uygulama okuyucuya pek fayda sağlamaz. Ancak, daha fazlasını keşfetmek isterseniz, Unity, Unity MVC için kişisel MVC çerçevemin bağlantısı burada. Çoğu uygulama için gereken AMVCC yapısal çerçevesini uygulayan çekirdek sınıfları bulacaksınız.

10 Bounces için scriptlerin yapısına bir göz atalım.

Başlamadan önce, Unity'nin iş akışına aşina olmayanlar için, betiklerin ve GameObject'lerin birlikte nasıl çalıştığını kısaca açıklayalım. Unity'de, Varlık-Bileşen anlamında "Bileşenler", MonoBehaviour sınıfı tarafından temsil edilir. Birinin çalışma zamanı sırasında var olması için, geliştiricinin kaynak dosyasını bir GameObject'e (Entity-Component modelinin "Varlığı" olan) sürükleyip bırakması veya AddComponent<YourMonobehaviour>() komutunu kullanması gerekir. Bundan sonra, komut dosyası somutlaştırılacak ve yürütme sırasında kullanıma hazır olacaktır.

Başlamak için, tüm somutlaştırılmış oyun öğelerine referansları içeren ana sınıf olacak Application sınıfını (AMVCC'deki "A") tanımlıyoruz. Ayrıca, Uygulama örneğine ve alt MVC örneklerine erişmemizi sağlayan Element adlı bir yardımcı temel sınıf oluşturacağız.

Bunu akılda tutarak, benzersiz bir örneğe sahip olacak Application sınıfını (AMVCC'deki “A”) tanımlayalım. İçinde üç değişken, model , view ve controller , çalışma zamanı boyunca tüm MVC örnekleri için bize erişim noktaları sağlayacaktır. Bu değişkenler, istenen komut dosyalarına public referanslar içeren MonoBehaviour s olmalıdır.

Ardından, Uygulama örneğine erişmemizi sağlayan Element adlı bir yardımcı temel sınıf da oluşturacağız. Bu erişim, her MVC sınıfının birbirine ulaşmasına izin verecektir.

Her iki sınıfın da MonoBehaviour genişlettiğini unutmayın. Bunlar, GameObject “Varlıklarına” eklenecek “Bileşenler”dir.

 // BounceApplication.cs // Base class for all elements in this application. public class BounceElement : MonoBehaviour { // Gives access to the application and all instances. public BounceApplication app { get { return GameObject.FindObjectOfType<BounceApplication>(); }} } // 10 Bounces Entry Point. public class BounceApplication : MonoBehaviour { // Reference to the root instances of the MVC. public BounceModel model; public BounceView view; public BounceController controller; // Init things here void Start() { } }

BounceElement MVC çekirdek sınıflarını oluşturabiliriz. BounceModel , BounceView ve BounceController komut dosyaları genellikle daha özel örnekler için kapsayıcı görevi görür, ancak bu basit bir örnek olduğundan yalnızca Görünüm iç içe geçmiş bir yapıya sahip olacaktır. Model ve Denetleyici, her biri için tek bir komut dosyasında yapılabilir:

 // BounceModel.cs // Contains all data related to the app. public class BounceModel : BounceElement { // Data public int bounces; public int winCondition; }
 // BounceView .cs // Contains all views related to the app. public class BounceView : BounceElement { // Reference to the ball public BallView ball; }
 // BallView.cs // Describes the Ball view and its features. public class BallView : BounceElement { // Only this is necessary. Physics is doing the rest of work. // Callback called upon collision. void OnCollisionEnter() { app.controller.OnBallGroundHit(); } }
 // BounceController.cs // Controls the app workflow. public class BounceController : BounceElement { // Handles the ball hit event public void OnBallGroundHit() { app.model.bounces++; Debug.Log(“Bounce ”+app.model.bounce); if(app.model.bounces >= app.model.winCondition) { app.view.ball.enabled = false; app.view.ball.GetComponent<RigidBody>().isKinematic=true; // stops the ball OnGameComplete(); } } // Handles the win condition public void OnGameComplete() { Debug.Log(“Victory!!”); } }

Oluşturulan tüm komut dosyaları ile bunları eklemeye ve yapılandırmaya devam edebiliriz.

Hiyerarşi düzeni şöyle olmalıdır:

 - application [BounceApplication] - model [BounceModel] - controller [BounceController] - view [BounceView] - ... - ball [BallView] - ...

Örnek olarak BounceModel kullanarak Unity'nin editöründe nasıl göründüğünü görebiliriz:

EKRAN GÖRÜNTÜSÜ: DENETÇİDE BounceModel
BounceModel ve winCondition alanları ile bounces .

Tüm komut dosyaları ayarlanmış ve oyun çalışırken, bu çıktıyı Konsol Panelinde almalıyız.

EKRAN GÖRÜNTÜSÜ: KONSOL ÇIKIŞI

Bildirimler

Yukarıdaki örnekte gösterildiği gibi, top yere çarptığında görünümü, bir yöntem olan app.controller.OnBallGroundHit() 'i çalıştırır. Uygulamadaki tüm bildirimler için bunu yapmak hiçbir şekilde “yanlış” değildir. Ancak deneyimlerime göre, AMVCC Uygulama sınıfında uygulanan basit bir bildirim sistemi kullanarak daha iyi sonuçlar elde ettim.

Bunu uygulamak için, BounceApplication düzenini şu şekilde güncelleyelim:

 // BounceApplication.cs class BounceApplication { // Iterates all Controllers and delegates the notification data // This method can easily be found because every class is “BounceElement” and has an “app” // instance. public void Notify(string p_event_path, Object p_target, params object[] p_data) { BounceController[] controller_list = GetAllControllers(); foreach(BounceController c in controller_list) { c.OnNotification(p_event_path,p_target,p_data); } } // Fetches all scene Controllers. public BounceController[] GetAllControllers() { /* ... */ } }

Ardından, tüm geliştiricilerin, yürütme sırasında gönderilebilecek bildirim olayının adlarını ekleyeceği yeni bir komut dosyasına ihtiyacımız var.

 // BounceNotifications.cs // This class will give static access to the events strings. class BounceNotification { static public string BallHitGround = “ball.hit.ground”; static public string GameComplete = “game.complete”; /* ... */ static public string GameStart = “game.start”; static public string SceneLoad = “scene.load”; /* ... */ }

Geliştiricilerin, yürütme sırasında ne tür eylemlerin gerçekleşebileceğini anlamak için controller.OnSomethingComplexName yöntemlerini kaynak kodun her yerinde aramasına gerek olmadığından, bu şekilde kodun okunabilirliğinin iyileştirildiğini görmek kolaydır. Yalnızca bir dosyayı kontrol ederek uygulamanın genel davranışını anlamak mümkündür.

Şimdi, bu yeni sistemi işlemek için sadece BallView ve BounceController uyarlamamız gerekiyor.

 // BallView.cs // Describes the Ball view and its features. public class BallView : BounceElement { // Only this is necessary. Physics is doing the rest of work. // Callback called upon collision. void OnCollisionEnter() { app.Notify(BounceNotification.BallHitGround,this); } }
 // BounceController.cs // Controls the app workflow. public class BounceController : BounceElement { // Handles the ball hit event public void OnNotification(string p_event_path,Object p_target,params object[] p_data) { switch(p_event_path) { case BounceNotification.BallHitGround: app.model.bounces++; Debug.Log(“Bounce ”+app.model.bounce); if(app.model.bounces >= app.model.winCondition) { app.view.ball.enabled = false; app.view.ball.GetComponent<RigidBody>().isKinematic=true; // stops the ball // Notify itself and other controllers possibly interested in the event app.Notify(BounceNotification.GameComplete,this); } break; case BounceNotification.GameComplete: Debug.Log(“Victory!!”); break; } } }

Daha büyük projelerde çok sayıda bildirim olacaktır. Bu nedenle, büyük bir switch-case yapısından kaçınmak için, farklı denetleyiciler oluşturmanız ve farklı bildirim kapsamlarını işlemelerini sağlamanız önerilir.

Gerçek Dünyada AMVCC

Bu örnek, AMVCC modeli için basit bir kullanım durumu göstermiştir. MVC'nin üç unsuru açısından düşünme şeklinizi ayarlamak ve varlıkları düzenli bir hiyerarşi olarak görselleştirmeyi öğrenmek, cilalanması gereken becerilerdir.

Daha büyük projelerde, geliştiriciler daha karmaşık senaryolarla ve bir şeyin Görünüm mü yoksa Denetleyici mi olması gerektiği veya belirli bir sınıfın daha küçük olanlarda daha kapsamlı bir şekilde ayrılması gerekip gerekmediği konusunda şüphelerle karşı karşıya kalacaklardır.

Başparmak Kuralları (Eduardo tarafından)

Hiçbir yerde “MVC sıralama için Evrensel Kılavuz” yoktur. Ancak, bir şeyi Model, Görünüm veya Denetleyici olarak mı tanımlayacağımı ve ayrıca belirli bir sınıfı ne zaman daha küçük parçalara böleceğimi belirlememe yardımcı olması için tipik olarak izlediğim bazı basit kurallar var.

Genellikle bu, yazılım mimarisini düşünürken veya komut dosyası oluşturma sırasında organik olarak olur.

Sınıf Sıralaması

Modeller

  • Uygulamanın oyuncu health veya silah ammo gibi temel verilerini ve durumunu tutun.
  • Türler arasında seri hale getirin, seri durumdan çıkarın ve/veya dönüştürün.
  • Verileri yükleyin/kaydedin (yerel veya web üzerinde).
  • Operasyonların ilerleyişi hakkında Kontrolörleri bilgilendirin.
  • Oyunun Sonlu Durum Makinesi için Oyun Durumunu saklayın.
  • Görünümlere asla erişmeyin.

Görüntüleme

  • Kullanıcıya güncel oyun durumunu temsil etmek için Modellerden veri alabilir. Örneğin, bir View yöntemi player.Run() , oyuncu yeteneklerini göstermek için dahili olarak model.speed kullanabilir.
  • Modelleri asla mutasyona uğratmamalıdır.
  • Sınıfının işlevlerini kesinlikle uygular. Örneğin:
    • Bir PlayerView , giriş algılamayı uygulamamalı veya Oyun Durumunu değiştirmemelidir.
    • Bir Görünüm, bir arayüze sahip olan ve önemli olayları bildiren bir kara kutu görevi görmelidir.
    • Çekirdek verileri saklamaz (hız, sağlık, yaşam,… gibi).

Kontrolörler

  • Çekirdek verileri saklamayın.
  • Bazen istenmeyen Görünümlerden gelen bildirimleri filtreleyebilir.
  • Modelin verilerini güncelleyin ve kullanın.
  • Unity'nin sahne iş akışını yönetir.

Sınıf Hiyerarşisi

Bu durumda, izlediğim çok fazla adım yok. Genellikle, değişkenler çok fazla "ön ek" göstermeye başladığında veya aynı öğenin çok fazla varyantı görünmeye başladığında (bir MMO'daki Player sınıfları veya bir FPS'deki Gun türleri gibi) bazı sınıfların bölünmesi gerektiğini algılarım.

Örneğin, Player verilerini içeren tek bir Model çok sayıda playerDataA, playerDataB,... veya Player bildirimlerini işleyen bir Controller OnPlayerDidA,OnPlayerDidB,... . Komut dosyası boyutunu küçültmek ve player ve OnPlayer öneklerinden kurtulmak istiyoruz.

Yalnızca verileri kullanarak anlamak daha kolay olduğu için bir Model sınıfı kullanmayı göstermeme izin verin.

Programlama sırasında genellikle oyun için tüm verileri tutan tek bir Model sınıfıyla başlarım.

 // Model.cs class Model { public float playerHealth; public int playerLives; public GameObject playerGunPrefabA; public int playerGunAmmoA; public GameObject playerGunPrefabB; public int playerGunAmmoB; // Ops Gun[CDE ...] will appear... /* ... */ public float gameSpeed; public int gameLevel; }

Oyun ne kadar karmaşıksa, o kadar çok değişken olacağını görmek kolaydır. Yeterince karmaşıklıkla, model.playerABCDFoo değişkenlerini içeren dev bir sınıf elde edebiliriz. Yuvalama öğeleri, kodun tamamlanmasını basitleştirecek ve ayrıca veri çeşitleri arasında geçiş yapmak için yer açacaktır.

 // Model.cs class Model { public PlayerModel player; // Container of the Player data. public GameModel game; // Container of the Game data. }
 // GameModel.cs class GameModel { public float speed; // Game running speed (influencing the difficulty) public int level; // Current game level/stage loaded }
 // PlayerModel.cs class PlayerModel { public float health; // Player health from 0.0 to 1.0. public int lives; // Player “retry” count after he dies. public GunModel[] guns; // Now a Player can have an array of guns to switch ingame. }
 // GunModel.cs class GunModel { public GunType type; // Enumeration of Gun types. public GameObject prefab; // Template of the 3D Asset of the weapon. public int ammo; // Current number of bullets public int clips; // Number of reloads possible }

Bu sınıf konfigürasyonu ile geliştiriciler, kaynak kodda her seferinde bir kavramda sezgisel olarak gezinebilir. Silahların ve konfigürasyonlarının gerçekten çok sayıda olabileceği bir birinci şahıs nişancı oyunu düşünelim. GunModel bir sınıfta yer alması, her kategori için bir Hazır Prefabs (önceden yapılandırılmış GameObject'ler hızla çoğaltılacak ve oyun içinde yeniden kullanılacak) listesinin oluşturulmasına ve daha sonra kullanılmak üzere saklanmasına izin verir.

Buna karşılık, Gun bilgilerinin tümü tek GunModel sınıfında, gun0Ammo , gun1Ammo , gun0Clips vb. İstenmeyen Player verilerini içeren Model . Bu durumda, yeni bir GunModel sınıfının daha iyi olacağı açıktır.

GÖRÜNTÜ: SINIF HİYERARŞİSİ
Sınıf hiyerarşisini geliştirmek.

Her şeyde olduğu gibi, madalyonun iki yüzü var. Bazen biri gereksiz yere aşırı bölümlere ayırabilir ve kod karmaşıklığını artırabilir. Sadece deneyim, projeniz için en iyi MVC sıralamasını bulmak için becerilerinizi geliştirebilir.

Yeni oyun geliştirme Özel Yetenek kilidi açıldı: MVC desenli Unity oyunları.
Cıvıldamak

Çözüm

Orada tonlarca yazılım modeli var. Bu yazıda, geçmiş projelerde bana en çok yardımcı olanı göstermeye çalıştım. Geliştiriciler her zaman yeni bilgileri özümsemeli, ancak her zaman sorgulamalıdır. Umarım bu eğitim yeni bir şeyler öğrenmenize yardımcı olur ve aynı zamanda kendi tarzınızı geliştirirken bir basamak görevi görür.

Ayrıca, diğer kalıpları araştırmanızı ve size en uygun olanı bulmanızı gerçekten tavsiye ederim. İyi bir başlangıç ​​noktası, mükemmel kalıp listesi ve özellikleri ile bu Wikipedia makalesidir.

AMVCC modelini beğendiyseniz ve test etmek istiyorsanız, bir AMVCC uygulamasını başlatmak için gerekli tüm temel sınıfları içeren kitaplığım Unity MVC'yi denemeyi unutmayın.


Toptal Mühendislik Blogunda Daha Fazla Okuma:

  • Unity AI Geliştirme: Sonlu Durumlu Makine Eğitimi