C # gibi yönetilen bir Dil ile oyun yazarken tipik tuzaklar nelerdir? [kapalı]


66

PC için C # gibi yönetilen bir dil ile oyun yazarken hangi zorluklarla karşılaştınız ve bunları nasıl çözdünüz?


Bu soruya, oyunlara özgü çok az olduğu için Stack Overflow'ta daha iyi sorulur.
Chris Garrett,

31
@Chris: Kesinlikle katılmıyorum: Soru özellikle oyunlardan bahsediyor! Her 16ms'de bir güncelleme yapmanız gerektiğinde karşılaştığınız sorunlar, çoğu masaüstü uygulamasında elde ettiğinizden çok farklıdır.
Andrew Russell,

Soru oldukça net değil. Java ve C #, her ikisi için de yalnızca çok genel tavsiye için yeterlidir. Şimdiye kadarki tüm cevaplar C # oldu. Ayrıca söz edilmeyen hedef platform - cihaza bağlı olarak iyi tavsiyeler farklılık gösterebilir (örneğin, bir cep telefonu için programlama, zune, xbox, bir pc için programlamadan farklı). Hatta birisinin yönetilen dillerin kendilerinin "tuzak" olduğunu yanıtladığı yeterince geniş bir soru bile oldu.
paulecoyote

@ paulecoyote: Sadece C # hakkında soru sormak için soruyu değiştirdim. Ayrıca, belirtilen belirli bir platform olmadığı için, PC ile ilgili.
Michael Klement,

@Michael platformun uygulamada çok farklı oldukları için tehlikeli bir varsayım olduğunu varsayıyor, özellikle Windows'tan bahsetmek ve "gibi" ve "Java" yı tamamen bırakmak iyi olurdu.
paulecoyote

Yanıtlar:


69

Java hakkında pek bir şey bilmiyorum, bu yüzden bir .net dev.

Şimdiye kadar en büyüğü çöp. .net çöp toplayıcıları pencerelerde harika bir iş çıkarır ve çoğunlukla oturan bebek olmadan kurtulabilirsiniz. Xbox / winPhone7'de bu farklı bir konu. Her birkaç çerçevede bir tezgah varsa, çöp toplama işlemi sorunlara neden olabilir. Şu anda her 1mb tahsisi sonrasında tetiklenir.

Heres çöp ile başa çıkmak için bazı ipuçları. Gerçekte bunların çoğu için endişelenmenize gerek olmamalı, ancak bir gün kullanışlı olabilirler.

  • İçeriğini GC.GetTotalMemory()ekrana çizin . Bu size oyununuzun kullandığı tahsis edilmiş bayt miktarının yaklaşık bir değerini verir. Neredeyse hareket ederse, tamam yapıyorsunuz. Hızlı gidiyorsa, sorunların var.
  • tüm öbek nesnelerinizi ön tarafa ayırmaya çalışın . Oyun başlamadan önce her şeyi tahsis edemezseniz, her defasında bir miktar tahsis edersiniz, durur. Tahsis yok, koleksiyon yok. Kadar basit.
  • Yüklemeden sonra GC.Collect () öğesini arayın. Büyük tahsisatlarınızın çoğunun yolun dışında olduğunu biliyorsanız, yalnızca sistemi bilmeniz güzel olur.
  • GC.Collect()Her kareyi ARAYMAYIN . Çöpün ve her şeyin üstünde tutmak iyi bir fikir gibi görünebilir, ancak çöp toplamanın bittiğinden daha kötüsü olanları sadece unutma.
  • Çöpünüzün nereden geldiğine bakın. Kullanmak yerine dizeleri birleştirmek gibi bazı ortak nedenler vardır StringBuilder(dikkat, StringBuildersihirli bir mermi değildir ve yine de tahsislere neden olabilir! ) kullanarak foreachkullanmak koleksiyonları üzerinde döngüler IEnumerableda bilmeden çöp oluşturabilir arabirimini (örneğin, foreach (EffectPass pass in effect.CurrentTechnique.Passes)ortak bir tanesidir)
  • Belleğin nerede tahsis edildiğini bulmak için CLR bellek profili oluşturucu gibi araçlar kullanın . Bu aracın nasıl kullanılacağına dair bir sürü ders var.
  • Oyun sırasındaki tahsisatınızın nerede olduğunu biliyorsanız, bu tahsisat sayısını düşürmek için nesneleri birleştirmek gibi hileler kullanıp kullanamayacağınıza bakın.
  • Her şey başarısız olursa, koleksiyonlarınızı daha hızlı çalıştırın! Kompakt çerçeve üzerindeki GC, hangi nesnelerin kullanılmadığını anlamak için kodunuzdaki tüm referansları takip eder. Refactor kodunuzu daha az referans kullanın!
  • IDisposableYönetilmeyen kaynaklar içeren sınıflarda kullanmayı unutmayın . Bunları, GC'yi kendi kendine bırakamayan belleği temizlemek için kullanabilirsiniz.

Düşünülmesi gereken bir diğer şey ise kayan nokta performansı. Net JITer, işlemciye özgü optimizasyonları adil bir miktarda yaparken, kayan nokta matematiğinizi hızlandırmak için SSE veya başka bir SIMD komut setini kullanamaz. Bu, oyunlar için C ++ ve C # arasında oldukça büyük bir hız farkına neden olabilir. Mono kullanıyorsanız, yararlanabileceğiniz bazı özel SIMD matematik kütüphaneleri vardır.


Tamamen katılıyorum. Çöp toplayıcı "daha küçük" platformlarda uygulamaları tamamen çöp gibi görünüyor.
Krisc

İyi posta, ancak "öndeki yığın nesnelerin tahsis edilmesi" ile ilgili ifadenizle ilgili olarak, Değer Türleri Hakkında Gerçekler'i
Justin

Harika nokta, kodu optimize ettiğinizde, optimize etmeye çalıştığınız platformu gerçekten anlamaya değer. Bu değer türleri / referans türleri hakkında gerçekten bir yorum değildi, uzun ömürlü herhangi bir nesnenin yığında olması muhtemel değildir. Gerçekten de, yükleme süresinde mümkün olan en fazla tahsisatınızı aldığınızdan emin olmanız, oyun sırasında bu sihirli 1mb engeline çarpmamanızdır. Xna'nın hedeflediği tüm .net uygulamaları düzgün bir garantiye sahiptir, zaman içinde birbirine yakın tahsis edilen nesneler uzaya yakın olacak ve bu da perf için güzel olabilir.
Cubed2D

Ayrıca, xbox'daki mevcut kompakt çerçevenin satır içi yöntem çağrılarına alerjisi olduğunu belirtmeyi unuttum. Bunu en kötü vaka senaryolarınız için saklayın, ancak matematik yöntemlerinin ref sürümlerini kullanmak yeterince çirkin görünüyor!
Cubed2D

10

Tipik bir performans düşüşü, çöp toplayıcıyı oyunun tasarımında / geliştirilmesinde dikkate almaz. Çok fazla çöp üretmek, GC uzun bir süre çalıştığında gerçekleşen oyunda "hıçkırık" a yol açabilir.

C # için değer nesnelerini ve "using" ifadesini kullanmak, GC'deki basıncı hafifletebilir.


3
Ek olarak, bir tahsisat / serbest ağır döngüyü yeni bitirdiyseniz veya yedek çevrimleriniz olduğunu tespit ederseniz, Çöp Toplayıcıya açıkça çalışmasını söyleyebilirsiniz.
BarrettJ

16
usingDeyim çöp toplama ile ilgisi yoktur! Bu içindir IDisposablenesneler - yönetilmeyen kaynakları serbest bırakmak için hangi (yani: o hangi çöp toplayıcı tarafından işlenmez ).
Andrew Russell

9

C # 'da oyun yazarken karşılaştığım en büyük problemin düzgün kütüphanelerin eksikliği olduğunu söyleyebilirim. Bulduğum çoğu, doğrudan bağlantı noktaları, ancak tamamlanmamış ya da bir C ++ kitaplığı üzerindeki sarmalayıcılar, marshalling için ağır bir performans cezası gerektiren. (OGRE kütüphanesi için özellikle MOgre ve Axiom ve Bullet fizik kütüphanesi için BulletSharp hakkında konuşuyorum)

Yönetilen diller (Yorumlananlardan farklı olarak - ne Java ne de C # artık yorumlanmıyor), gerçekte neyin yavaşladığını (marshaling, çöp toplama) iyi bir şekilde anladıysanız, yerel diller kadar hızlı olabilir. Bence asıl sorun, kütüphane geliştiricilerin henüz bunu anlamadığıdır.


Bu C # ve Java'nın yorumlanmak yerine yönetilmekle ilgili iyi bir nokta ... daha doğru hale getirmek için sorumu düzenledi :)
Michael Klement

2
Genel olarak marşaling bir performans darboğazıdır, ancak çok fazla performans etkisi olmadan doğrudan yönetilmeyen belleğe eşlenebilen, çeşitlendirilebilir türlerin de farkında olmamak için yardımcı olur. msdn.microsoft.com/en-us/library/75dwhxf7.aspx
Sean Edwards


4

C # ve Java yorumlanmadı. Onlar sonra, bir ara baytkoduna derlenmiş ediyoruz JIT , yerli kod (veya önemsiz olacak kadar yakın) kadar hızlı olur

Bulduğum en büyük sorun, kullanıcı deneyimini doğrudan etkileyen kaynakları serbest bırakmak. Bu diller C ++ gibi deterministik sonlandırmayı otomatik olarak desteklememektedir , eğer beklemiyorsanız, tahrip olduklarını düşündükten sonra sahnede kayan kafesler gibi şeylere yol açabilir. (C #, IDisposable ile deterministic sonlandırmayı gerçekleştirir , Java'nın ne yaptığından emin değilim.)

Bunun dışında, yönetilen diller, oyunların kredi alacağından daha fazla performans gösterme yeteneğine sahipler. İyi yazılmış yönetilen kod, kötü yazılmış yerel koddan çok daha hızlıdır.


Evet, not için teşekkürler, zaten yorumlanmış / yönetilen şeyi düzeltti;) Ayrıca, sahne etrafında kayan kafeslerle iyi bir nokta. GC problemlerini düşünürken bunu düşünmedim ...
Michael Klement

1
IDisposablezaman kritik ve yönetilmeyen kaynakların deterministik bir şekilde temizlenmesini sağlar, ancak sonlandırmayı veya çöp toplayıcıyı doğrudan etkilemez.
Sam Harwell

4

Ne Java ne de C # yorumlanmaz. İkisi de yerel makine kodunda derlendi.

Hem oyunlarda hem de oyunlarda ortaya çıkan en büyük sorun, oyun sırasında hiçbir zaman çöp toplamayacak şekilde kodlamak zorunda kalmaktır. Bunu başarmak için atlamanız gereken halka sayısı, ilk etapta bunları kullanmanın yararlarından neredeyse ağır basar. Bu dili uygulama veya sunucu programlaması için kullanmayı eğlenceli kılan özelliklerin çoğunun oyun programlaması için kullanılması önlenmelidir, aksi halde oyun oynama sırasında gider ve çöp topladıkça uzun duraklamalar alırsınız.


Çöp toplama, en azından C # ile oldukça iyi bir şekilde ele alınabilir, bu yüzden bunun bir dağıtıcı olduğunu söyleyemem. Düzgün diş açma ve program durumu bilinci ile performans sorunlarından kaçınabilirsiniz. Yine de düşünmeniz gereken başka bir şey var ve yönetilen dili biraz daha az yönetilen yapıyor.
Karantza

4
.NET 4'te, çöp toplayıcının, üç neslin tümü için arka plan koleksiyonunu desteklediğini belirtmek gerekir. Bu, oyunlarda çöp toplamanın performans etkisini etkili bir şekilde en aza indirmelidir. İlgili Bağlantı: geekswithblogs.net/sdorman/archive/2008/11/07/…
Mike Strobel

Çöp toplayıcıları evrimleşmektedir ve Mike Strobel tarafından belirtildiği gibi, bazıları zaten bu düşüşü ortadan kaldıran üretimdedir.
Sam Harwell

2
Ne C # ne de Java, yerel makine koduna göre derlenmedi. C # MSIL ve Java'ya bytecode derler. Çöp toplama işlemi herhangi bir "uzun" duraksamaya neden olmaz, ancak "hıçkırık" verebilir.
Cloudanger

2

Bunun gibi dillerle (ya da XNA, TorqueX motoru, vb. Araçlarla) oyun oynayarak gördüğüm büyük bir tuzak, neye eşdeğer bir oyun oluşturmak için gerekli uzmanlığa sahip iyi bir insan ekibi bulmak için zorlanmanız. C ++ ve OpenGL / DirectX'te insanları bulmak oldukça kolay olurdu.

Oyun endüstrisi, C ++ 'ta büyük ve sadece iyi cilalanmış küçük oyunları itmek için kullanılan araçların ve boru hatlarının çoğu C ++' ta yazıldığı için hala çok ağır bir biçimde sarsıldı. XBox, PS3 ve Wii için yalnızca C ++ ile uyumlulukla yayınlandı (XBox araç takımı bugünlerde daha iyi yönetilebilir, herkes daha fazlasını biliyor mu?)

Şu anda konsollar için oyunlar geliştirmek istiyorsanız, hemen hemen XBox'ta XNA ve C # ve ardından yalnızca XBox Live Indie Games adlı oyun kütüphanesinin bir tarafında olsun. Yarışmalar vb. Kazananları, oyunlarını gerçek XBox Live Arcade'e taşımak için seçildi. PC için bir oyun yapma planından başka.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.