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());
  }
}

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