Diyalog ağaçlarını oyunuma nasıl uygulayabilirim?


51

Oyunumda bir iletişim ağacı sistemi uygulamanın en iyi yolu nedir? Bir NPC'nin, oyuncuya yalnızca bir öğeye sahip olduğu veya önceki bir etkinlik gerçekleştiği zaman ortaya çıkabilecek farklı yanıt gruplarını vermesini istiyorum.


2
BOUNTY, özellikle tetikleyici öbeklerin ve NPC metinlerinin çevirilerinin nasıl ele alınacağına ilişkin iyi fikirler içindir. Böylece NPC konuşmayı başlatan oyuncuya bağlı olarak farklı dilleri anlayabilir ve konuşabilir. Gamedev.stackexchange.com/questions/31/… ' de yer alan yapı yaklaşımı ile bile , metin depolarında mantık sahibi olmak iyi bir fikir gibi görünmemektedir. Ancak onları bölmek, kodu anlamayı çok daha zorlaştırır.
Hendrik Brummermann

Yanıtlar:


17

Diyalog Ağaçları XML kullanılarak yapılmalıdır. Daha karmaşık bir şey yapmanız gerekirse yanıtların koşullarını ve iç içe geçmiş ağaçlardaki yanıtı bir komut dosyasına referans olarak saklarsınız.

Senaryoları ve diyalogu ayrı tutmalısın, özellikle de tonlarca konuşmaya değer bir RPG hazırlıyorsan. XML dosyasını okumak için simpleXML gibi bir kütüphane kullanabilirsiniz.

SO ile benzer bir soruya bir örnek daha var: https://stackoverflow.com/questions/372915/game-logic-in-xml-files


XML için +1. Kodun içine gömülmekten çok daha iyidir, kodu yeniden derlemeden değişiklik yapılmasına izin verir ve bazı güçlü editörler tarafından okunabilen standart bir formattır.
AttackHobo

34
XML yalnızca bir biçimdir (ve IMO, kötü bir biçimdir). Gerçekten bu cevabın söylediği şey, "Temel mantığı ve akışları içeren, ancak öncelikle diyaloğunuzu içeren küçük bir etki alanı dili oluşturun ve ayrıştırın." Bu şekilde, bu cevaba katılıyorum.
Ipsquiggle

5
Tam olarak, XML sadece bir konteynırdır, bunu Lua veya diğer betik dillerini kullanarak da uygulayabilirsiniz (ve kesinlikle daha fazla okunabilir ve insan tarafından düzenlenebilir).
LearnCocos2D

4
XML'in ayrıştırılması pahalıdır ve bir LOT belleği kaplar. Depolama biçimi olarak kullanmak iyidir, ancak iletişim ağaçlarını çalışma zamanında kullanılan ikili biçime dönüştüren bir yardımcı program yazarım. Bir PC'niz varsa ve bellek kullanımınızı umursamıyorsanız, sorun olabilir, ancak başka herhangi bir platformda bellek maliyeti sizi hortumlayacaktır.
BigSandwich

1
XML için -1. @Ipsquiggle ve @BigSandwich
o0 '

20

Lua ya da yakut gibi bir betik dili eklemeye ve buradaki diyalog etkileşimlerini kodlamaya çalışırdım.

Böylece bir iletişim komut dosyası gibi görünebilir:

switch showDialog "Why don't you just leave me along!", "Okay", "But I found your dog!"
    case 1:
        showDialog "And stay gone!"
    case 2:
        if playerHasObject "dog"
            showDialog "Thank you!"
        else
            showDialog "Liar!"

Bu aynı zamanda AI kodunu ve çalışma süresi boyunca ince ayar yapabileceğiniz diğer basit şeyleri kodlamak için de işe yarar. Hata ayıklama modunda (veya bir Paskalya Yumurtası olarak) çalıştırırken çağrılabilecek, uygulamanızın içinde yerleşik bir düzenleyici bile ekleyebilirsiniz.


1
Mantık ekleyebildiğiniz için bunu düz XML olarak tercih ediyorum. Ancak, metnin kendisinin koddan ziyade XML biçiminde olması gerektiğini söyleyebilirim. (düzenlemek, diğer dillere yerelleştirmek vb. daha kolaydır).
Iain

Yerelleştirmeye / daha kolay düzenlemeye ihtiyacınız varsa, metni, eklenmiş metni Qt içindeki tr (QString) işlevi / makro gibi ayrı bir dosyaya yazan bir fonksiyona sarabilirsiniz. pepper.troll.no/s60prereleases/doc/linguist-hellotr.html
Nailer

mantığı burada simüle etmek için xml'deki öznitelikleri veya fazladan etiketleri kullanmanızı engellemek nedir?
lathomas64 13:10

16

Oyunda Stendhal, NPC'leri uygulamak için sonlu bir durum makinesi kullanıyoruz.

Aşağıdaki diyagramda görevler öğreticinin nasıl yazılacağına ilişkin küçük bir örnek gösterilmektedir .

IDLE, ATTENDING ve QUEST_OFFERED durumlarını içeren FSM

Başlangıçta, NPC bir IDLE durumundadır ve dolaşıyor olabilir. Bir oyuncu "merhaba" diyerek sohbete başlayabilir ve NPC ATTENDING durumuna geçecektir. Bu durumda “işi” ile ilgili sorulara cevap verir ve bazı oyunlarda “yardım” sunar. Oyuncu bir görev isteyebilir ve NPC, oyuncunun kabul etmesini ("evet") veya reddetmesini ("hayır") bekleyerek QUEST_OFFERED durumuna geçecektir.

Geçişlere eklenebilecek bir dizi koşul tanımladık . Örneğin, bir görevi tamamlamak yalnızca bir PlayerHasItemWithHimCondition ile karşılaşıldığında mümkün olabilir .

Bir geçiş yapıldıktan sonra NPC bir miktar metin söyleyebilir ve / veya bir eylem yürütebilir. Koşullara benzer olarak, oyuncuya bir görev ödülü vermek için kullanılan EquipItemAction gibi tekrar kullanılabilir bir eylemler kümesi tanımladık .

AndCondition , OrCondition ve NotCondition kullanılarak birden fazla koşul birleştirilebilir . Genellikle, görev tamamlandığında yapılması gereken çok sayıda eylem vardır, bu yüzden bir MultipleActions sınıfı da vardır.

Stendhal'daki gerçek uygulama diğer (insan) dillerde kolayca çevrilememekle sıkıntı çekse de, genel kavramın iyi olduğunu düşünüyorum.



5

Bence çeviriler eklemek için hala yukarıda belirtildiği gibi mantık için XML kullanabilirsiniz . Bu tür bir karmaşıklığa girerken, kendi diyalog aracınızı yazmalısınız. Diyalog metniniz, görüntülemek istediğiniz dile bağlı olarak değiştirebileceğiniz bir veritabanının anahtarı olarak saklanır.

Örneğin şunları yapabilirdiniz:

<dialogue id="101" condition="!npc.carsFixed">
  <message>Localize.FixMyCar</message>
  <choices>
    <choice condition="hero.carFixingSkill > 5" priority="7" id="Localize.Sure">
      <command>hero.carFixingSkills += 1</command>
      <command>npc.carFixed = true</command>
      <command>hero.playSmokeAnimation()</command>
      <command>nextDialogue = 104</command>
    </choice>
    <choice condition="hero.carFixingSkill <= 5" id="Localize.CantFix">
      <command>nextDialogue = 105</command>
    </choice>
    <choice id="Localize.FixYourself">
      <command>npc.likesHero -= 1</command>
    </choice>
  </choices>
</dialogue>

Daha sonra görev metin oluşturucusunun "Localize.FixMyCar" yerine uygun bir şekilde çevrilmiş olan metni değiştirmesini istersiniz.

Aracınız, oynatıcının düzenlenebilir ham XML ile birlikte seçilebilir bir dilde ne göreceğini gösterir.

Benzer şekilde, başvurduğunuz örnekten böyle bir şey kullanabilirsiniz :

npc.add(ConversationStates.ATTENDING,
        ConversationPhrases.QUEST_MESSAGES, 
        null,
        ConversationStates.QUEST_OFFERED, 
        Localization[ "BringMeABeer" ],
        null);

Anahtarlarınız yeterince açıklayıcıysa, metnin tamamının olmaması bir sorun olmamalıdır.

Böyle bir şey de yararlı olabilir:

Localization[ "<Location>.<NPC_name>.<Dialogue_text_key>" ];

4

Veri, karakterlerinizi LUA komut dosyaları ve hatta XML dosyaları ile yönlendirir. Bir NPC ile etkileşime geçtiğinde, ona bağlı olan dosyayı al, oku, tetiği olabilecek oyun değişkenlerini ayarla ve geçerli cevabı ver.

Bu şekilde yapmanın en büyük kazancı, kolayca içeri girip diyaloğu değiştirebilir, yeni karakterler ekleyebilir, vb. Ayrıca, her bir durumu ele alırken kod tabanınızı özel bir mantıkla karıştırmaktan kaçınırsınız.


1
Bu Lua, LUA değil. :)
RCIX 16:10

2
Sadece senin için yaptım dostum. ;)
David McGraw

4

XML kullanıyorsanız, XML dosyasını düzenlemek için küçük bir araç oluşturduğunuzdan emin olun. Aksi takdirde delirirsiniz.


Zaten düzenlemek için bir araç yoksa, o zaman ilk etapta kullanmak anlamsız: kendi biçiminizi de yaratın!
'.

3

Çok derin bir iletişim ağacı kümeniz varsa , ChatMapper'ı kullanın . Tam özellikli bir ücretsiz sürümü var ve araç, iletişim ağaçlarınızı XML'e aktarmanıza olanak tanır. Kullanıyorum ve karmaşık diyalog ağaçlarını görselleştirmek ve organize etmek için mükemmel bir yol.


1

Diyaloglarınız herhangi bir karmaşıklığa sahipse, diyalog uygulaması için ihtiyaç duyacağınız en önemli şey, etkileşimin karmaşıklığını anlamanın bir yoludur. Bunu önermek için iyi bir açık sistemim olmasa da, bunu görselleştirmek için bir tür Düğüm editörü öneririm.


1

Bence bu senaryoyu yönlendirmek için kendi senaryo dilinizi kullanıyorsunuz (olmasanız da gerekir). Daha sonra komut dosyalarınızı da işlemek için genişletin.
Diyalog mantığı oluşturma sırasında diğer oyun değişkenleriyle çalışabilirsiniz. Oyun motorları Lego'ya benziyor. Sadece tuğlaları programladınız ve script bunları kullanıyor. Bazı script tercüman veya derleyici yapmak farketmez. Ancak script her zaman yararlıdır.


0

Basit otomat şunları yapabilir:

(dialogueline_id, condition) -> (next_id, response)

Böyle bir şeye benzeyebilir:

(1, troll is hungry?) -> (2, say "troll be hungry")
(2, player has bananas?) -> (3, say "hey, you have bananas!")
(3, ) -> (-1, (say "i like bananas, i take them and eat, you may pass, bye", remove bananas, feed the troll))
(2, player does not have bananas?) -> (-1, say "go away!!!")

Oyunda sen kimliği bulmak ve kimliği ve koşulu eşleştirmeyi deneyin.

Koşulları ve eylemleri modellemeniz gerekir. Nesnelere göre, işaretçiler, XML ...

İyi bir diyalog düzenleyicisi de kullanışlı olacaktır.

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.