Uygulamayı aç
Moonborn — Developers

NPC'leri oyun motoruyla orkestre et

Moonborn karakter katmanını oyun motorunun sahne durum makinesine (state machine) bağla — kim hangi tarafa ait, kayıt / yükleme Moonborn oturum kimliğini nasıl taşır.

Moonborn karakter katmanını sahiplenir: persona üretimi, voice fingerprint, drift detection, ensemble ilişkileri, hafıza (memory). Oyun motorun sahne katmanını sahiplenir: hangi NPC sahnede, tur sırası, dallı anlatı (branching narrative), kayıt / yükleme (save / load), oyuncu arayüzü (player UI). Bu rehber sınırı net çizer ve iki tarafı bağlayan minimum deseni gösterir.

Bu rehberi bitirdiğinde

  • Moonborn'un ve motorun sahiplendiği şeyleri ayırt edebileceksin.
  • Bir sahnedeki NPC'leri Moonborn oturumuna bağlayabileceksin (tek + çok karakterli / ensemble).
  • Motorun kim konuşacak kararını verdiği bir orkestrasyon deseni kurabileceksin.
  • Kayıt / yükleme akışında Moonborn oturum kimliğinin nasıl saklandığını (serialize) bileceksin.
  • Drift sinyalini motor arayüzünde (örn. karakter mimiklerini — emote — tetikleme) kullanabileceksin.

Ön koşul: API anahtarı + en az iki NPC persona + bir oyun motoru veya prototip CLI'ı. Çok karakterli akış yeni bir konuysa önce Çok karakterli bir sahne kur.

Sınır — kim neyi sahipleniyor

- Persona üretimi + kalıcılığı (persistence)
- Yanıt başına voice fingerprint + drift detection
- Ensemble ilişkileri (tipli kenarlar / edges)
- Sohbet oturumu içinde uzun vadeli hafıza
- Denetim (audit) + tahrik (provocation) test hattı

Bağlama deseni

Motor sahne durum makinesini yönetir, Moonborn'a sadece "kim konuşuyor ve ne söyledi" çağrısı yapar.

// Motor tarafı — sahne tanımı
class Scene {
  constructor(
    public participants: NPC[],
    public turnOrder: 'round-robin' | 'narrative' | 'initiative',
  ) {}
 
  // Sahne durumuna göre kim konuşacak seç
  pickResponder(playerText: string): NPC {
    if (this.turnOrder === 'narrative') {
      return this.narrativePolicy(playerText);
    }
    if (this.turnOrder === 'initiative') {
      return this.highestInitiative();
    }
    return this.nextInRoundRobin();
  }
 
  async onPlayerSay(text: string) {
    const speaker = this.pickResponder(text);
 
    const reply = await client.chat.messages.create({
      sessionId: speaker.moonbornSessionId,
      speaker: speaker.personaId,
      content: text,
    });
 
    // Motor yanıtı işler — animasyon, ses, arayüz
    this.deliver(speaker, reply.content);
 
    // Drift sinyali arayüze — örn. karakterin "şaşkın" animasyonunu tetikle
    if (reply.driftAlert) {
      this.flagCharacter(speaker, 'drift', reply.driftScore);
    }
  }
}

Çoklu persona oturumları (ensemble)

Birden fazla NPC aynı sahnede konuşacaksa, tek bir paylaşılan oturum aç. ensemble dizisi ek konuşmacıları taşır; her messages.create çağrısında speaker alanı aktif NPC'yi seçer.

const session = await client.chat.sessions.create({
  personaId: merchant.id,
  ensemble: [traveler.id, tavernKeeper.id],
  metadata: { sceneId: 'tavern_arrival' },
});
 
// Tur 1 — merchant konuşuyor
await client.chat.messages.create({
  sessionId: session.id,
  speaker: merchant.id,
  content: 'Tavernci! Bana bir kase çorba ve bir ekmek...',
});
 
// Tur 2 — tavern keeper cevap veriyor
await client.chat.messages.create({
  sessionId: session.id,
  speaker: tavernKeeper.id,
  content: '(merchant\'a soğuk bir bakış) Para önce.',
});

Kayıt / yükleme

Sohbet oturum kimliği kalıcılık anahtarıdır. Oyun kayıt dosyasında sahne durumunun yanına sakla (serialize).

{
  "sceneId": "tavern_arrival",
  "turn": 14,
  "participants": ["merchant", "traveler", "tavern_keeper"],
  "moonbornSessionId": "ses_01H...",
  "questFlags": { "letter_revealed": true, "merchant_suspicious": false }
}

Yükleme akışı:

  1. Kayıt dosyasından moonbornSessionId'yi çek.
  2. Aynı sessionId ile chat.messages.create çağrıları yapmaya devam et.
  3. Kısa vadeli hafıza bozulmamış (son N tur istemde), uzun vadeli hafıza + voice fingerprint hâlâ sabitli (pinned).

Drift sinyalini motor arayüzüne bağla

Drift skorunu sahne arayüzüne bağlamak anlatı ipucu olarak kullanılabilir:

if (reply.driftAlert) {
  // Bir karakter "kendisinden çıkmış" gibi görünüyor — arayüzde bir
  // mimik (emote), müzik değişikliği veya altyazı stilinde fark
  scene.tweakEmote(speaker, 'uncertain');
}

Bu yazılı drama için işlevsel olabilir — karakter isteminde (prompt) zorlanıyorsa bunu arayüzde görünür kıl. RPG ürünleri için drift sinyali "büyü baskısı altında karakter kontrolünü kaybediyor" gibi mecazlara dönüşebilir.

Tipik bir motor entegrasyonu

MotorTipik bağlama biçimi
UnityC# sarmalayıcı (wrapper), Moonborn REST API'yi MonoBehaviour'da çağırır. Oturum kimliği sahne ScriptableObject'inde tutulur.
GodotGDScript HTTP istemcisi; Moonborn yanıtı DialogueResource dosyasına itilir.
Twine / InkÖzel fonksiyon koşum takımı (harness); ink seçeneğinden Moonborn yanıtı tetiklenir.
Özel (TS / Node)Doğrudan @moonborn/sdk; CLI prototipleme ve web tabanlı oyunlar için ideal.

Plan gereksinimi

Pro ve üstü (ensemble + uzun hafıza aktif).

İlgili

Çok karakterli bir sahne kur

Ensemble oturum + konuşmacı seçimi adım adım eğitimi.

Open →
Etkileşimli kurgu prototipleme

Motor entegrasyonu öncesi CLI prototip akışı.

Open →
Ensemble ilişkileri kavramı

Tipli kenarların istem (prompt) birleştirmesine nasıl indiği.

Open →
Oyun NPC orkestrasyonu kullanım senaryosu

Oyun ekiplerinin Moonborn'u motorla nasıl kullandığına dair kullanım senaryosu.

Open →