Lingara Lingara مستندات رهنماها API کتابخانه‌ها اپلیکیشن‌ها ساختن جاسازی اپلیکیشن وب
زبان: دری

گفتگوی NPC

این صفحه از انگلیسی ترجمه شده است. اگر این دو با هم فرق داشته باشند، صفحهٔ انگلیسی درست است. صفحهٔ انگلیسی را بخوانید

یک شخصیت در بازی شما می‌تواند با بازیکن به زبانی که یاد می‌گیرد و مطابق سطح او گفتگو کند. هر جمله‌ای که بازیکن می‌گوید یک نوبت است: کیت بازیکن آن را می‌فرستد و پاسخ شخصیت تکه‌تکه به شکل جریانی برمی‌گردد.

یک نوبت چه چیزی را انتقال می‌دهد

هر نوبت همهٔ آنچه را شخصیت لازم دارد می‌فرستد، زیرا Lingara هیچ گفتگویی را بین نوبت‌ها نگه نمی‌دارد:

  • npc: چه کسی صحبت می‌کند. name آن 1 تا 32 حرف است و persona اختیاری آن یک سطر توصیف، 1 تا 120 حرف، مانند «یک منتوفروش».
  • scene: اختیاری، جایی که گفتگو در آن صورت می‌گیرد، 1 تا 160 حرف.
  • source_lang و target_lang: زبان خود بازیکن و زبانی که یاد می‌گیرد. این دو باید متفاوت باشند و شخصیت تنها به target_lang صحبت می‌کند.
  • level: سطح بازیکن، از 1 تا 9. رهنمای Lingara با عنوان «یک سطح چه معنایی دارد» این مقیاس را توضیح می‌دهد.
  • line: آنچه بازیکن همین حالا گفت، 1 تا 500 حرف.
  • history: گفتگو تا این لحظه، قدیمی‌ترین در اول، حداکثر 12 سطر. هر سطر یک speaker دارد، یا player یا npc، و text آن، 1 تا 500 حرف.

هر متن یک سطر است. بازی شما گفتگو را نگه می‌دارد: کیت بازیکن پنجرهٔ هر گفتگویی را که باز می‌کنید نگه می‌دارد، هر نوبت تکمیل‌شده را به آن اضافه می‌کند، هر پاسخ را به 500 حرف اول آن کوتاه می‌کند و قدیمی‌ترین سطرهای بیشتر از 12 را کنار می‌گذارد.

Lingara توصیف شخصیت و صحنه را متنی غیرقابل اعتماد از طرف بازی شما در نظر می‌گیرد. این دو شیوهٔ صحبت شخصیت را شکل می‌دهند، اما هرگز تعیین نمی‌کنند که شخصیت اجازهٔ انجام چه کاری را دارد.

پاسخ چگونه می‌رسد

پاسخ به شکل جریانی و در قالب تکه‌های متن می‌رسد که بازی شما با رسیدن آن‌ها، آن‌ها را به هم وصل می‌کند. ممکن است در میان آن‌ها اطلاعیه‌ای بیاید، مثلاً اطلاعیه‌ای که می‌گوید پاسخ نیمه‌کاره قطع شد. نوبت با done وقتی پاسخ کامل است، یا با error وقتی ناکام شده است، ختم می‌شود. نوبت قابل ادامه نیست: اگر اتصال قطع شود، بازیکن جمله را دوباره می‌گوید.

به هر شخصیت هر بار یک جمله بگویید. جمله‌ای که در حالی گفته شود که شخصیت هنوز در حال پاسخ دادن است، به جای قرار گرفتن در صف رد می‌شود، زیرا هزینهٔ هر نوبت حساب می‌شود.

چه کسی پرداخت می‌کند

تنها بازیکنان یک کلاینت با پلان مبتنی بر مصرف می‌توانند گفتگو کنند، و هزینهٔ هر نوبت از همان کلاینت گرفته می‌شود. توکن بازیکن به embed:play ضرورت دارد.

زبان نمونهٔ کود

Bevy

fn spawn_seller(mut commands: Commands) {
    let mei = NpcDialogue::new("Mei", "zh", 2)
        .and_then(|npc| npc.with_persona("a dumpling seller"))
        .and_then(|npc| npc.with_scene("the night market"))
        .expect("within Lingara's bounds");
    commands.spawn(mei);
    commands.spawn(Player);
}

/// One turn at a time: a line said while the NPC is replying is a `Busy` error.
fn talk(keys: Res<ButtonInput<KeyCode>>, npcs: Query<Entity, With<NpcDialogue>>, mut say: MessageWriter<NpcSay>) {
    if keys.just_pressed(KeyCode::Digit1) {
        for entity in &npcs {
            say.write(NpcSay { entity, line: "饺子多少钱?".into() });
        }
    }
}

/// `streaming` grows as the reply arrives; `turns` holds the finished ones.
fn show_reply(transcripts: Query<&NpcTranscript, Changed<NpcTranscript>>) {
    for transcript in &transcripts {
        if let Some(partial) = &transcript.streaming {
            info!("…{partial}");
        }
    }
}

Unity

public DialogueId OpenDialogue(string npc, string sourceLang, string targetLang, byte level) =>
    Client.DialogueOpen(new DialogueConfig { Npc = new Npc { Name = npc }, SourceLang = sourceLang, TargetLang = targetLang, Level = level });

// The reply streams back as NpcTurn events: append each Fragment's text to your label.
public RequestId Say(DialogueId dialogue, string line) => Client.DialogueSay(dialogue, line);

Godot C#

public long OpenDialogue(string npc, string sourceLang, string targetLang, byte level) =>
    Client.DialogueOpen(new DialogueConfig { Npc = new Npc { Name = npc }, SourceLang = sourceLang, TargetLang = targetLang, Level = level }).Value;

// The reply streams back as NpcTurnFragment signals, then one NpcTurnFinished.
public long Say(long dialogue, string line) => Client.DialogueSay(new DialogueId(dialogue), line).Value;

GDScript

# A LingaraNpc child per character: npc_name, target_lang and level in the
# inspector. say() returns false while a turn is in flight (turns are never
# queued, because each one is billed).
func talk_to_mei(line: String) -> void:
	if mei.say(line):
		bubble.text = "…"


func _on_mei_replied(text: String) -> void:
	bubble.text = text

Unreal C++

void ALingaraEmbedSnippetActor::Say(const FString& Line)
{
	ELingaraCallResult Result;
	FLingaraEmbedError Error;
	if (Dialogue == 0)
	{
		FLingaraDialogueConfig Config;
		Config.Npc.Name = TEXT("Mei");
		Config.Npc.Persona = TEXT("a tea seller at the night market");
		Config.SourceLang = TEXT("en");
		Config.TargetLang = TEXT("zh");
		Config.Level = 2;
		Dialogue = Lingara()->DialogueOpen(Config, Result, Error);
	}
	Reply.Reset();
	Lingara()->DialogueSay(Dialogue, Line, Result, Error);
}

// The reply streams back as npc_turn events: append each fragment.
void ALingaraEmbedSnippetActor::HandleNpcTurn(const FLingaraNpcTurn& Turn)
{
	if (Turn.Dialogue == Dialogue && Turn.Update.Type == ELingaraNpcTurnUpdateType::Fragment)
	{
		Reply += Turn.Update.Text;
	}
}

Kotlin

fun talkToMei(line: String) {
    val dialogue = npc ?: lingara.dialogueOpen(DialogueConfig(Npc("Mei", "a tea seller"), "the tea house", "en", "zh", 2, emptyList()))
    npc = dialogue
    lingara.dialogueSay(dialogue, line)
}

private fun onNpcTurn(update: NpcTurnUpdate) {
    when (update) {
        is NpcTurnUpdate.Opened -> bubble = ""
        is NpcTurnUpdate.Fragment -> bubble += update.text
        is NpcTurnUpdate.Finished -> bubble = update.text
        else -> Unit
    }
}

Java

void talkToMei(String line) {
  if (npc < 0) {
    Npc mei = new Npc("Mei", "a tea seller");
    npc =
        lingara.dialogueOpen(new DialogueConfig(mei, "the tea house", "en", "zh", 2, List.of()));
  }
  lingara.dialogueSay(npc, line);
}

void onNpcTurn(EmbedEvent.NpcTurn turn) {
  if (turn.getUpdate() instanceof NpcTurnUpdate.Fragment fragment) {
    bubble.append(fragment.getText());
  } else if (turn.getUpdate() instanceof NpcTurnUpdate.Finished finished) {
    bubble.setLength(0);
    bubble.append(finished.getText());
  }
}

همچنین ببینید