Di RecastNavigation, bagaimana saya bisa membuat agen menganggur setelah mencapai tujuannya?

8

Pertanyaan ini secara khusus tentang berurusan dengan perpustakaan Navigasi Recast.

Saya telah menambahkan agen dengan addAgentdan menetapkan target dengan requestMoveTarget. Ketika agen mencapai tujuannya, itu berhenti, tetapi ketika didorong keluar dari jalan (oleh agen lain) ia akan mencoba untuk kembali ke targetnya. Sebaliknya, ingin berhenti dan menjadi menganggur, sehingga ketika agen lain berjalan dengan mendorongnya ke samping dan itu tidak akan kembali.

Saya telah mencoba menelepon resetMoveTargetpada agent.nposyang dekat dengan agent.targetPos(seolah-olah agen telah mencapai tujuan), tapi itu tampaknya mematahkan logika bagian dalam simulasi kerumunan - agen akan terus berjalan ke arah tua, tidak pernah berhenti.

Bagaimana cara saya memberi tahu agen dengan benar untuk berhenti dan menjadi idle (belum dapat didorong) di RecastNavigation?

Kromster
sumber

Jawaban:

2

Perbaikan dibuat di hulu terkait dengan solusi Anda yang mengatur ulang kecepatan yang diinginkan di resetMoveTarget.

bool dtCrowd::resetMoveTarget(const int idx)
 {
    if (idx < 0 || idx >= m_maxAgents)
        return false;

    dtCrowdAgent* ag = &m_agents[idx];

    // Initialize request.
    ag->targetRef = 0;
    dtVset(ag->targetPos, 0,0,0);
    dtVset(ag->dvel, 0,0,0); // <<-- This line added
    ag->targetPathqRef = DT_PATHQ_INVALID;
    ag->targetReplan = false;
    ag->targetState = DT_CROWDAGENT_TARGET_NONE;

    return true;
 }
Leif Gruenwoldt
sumber
Sejauh yang saya ingat ini adalah jawaban yang tidak lengkap. Saya bingung. Apakah ini jawaban atau komentar untuk jawaban saya di bawah? Karena Anda juga perlu mengatur ulang koridor agen, sehingga agen menjadi benar-benar idle (pushable).
Kromster
OK saya sudah lupa tentang masalah Anda dengan agen menjadi tidak dapat disentuh. Saya akan mencoba mereproduksi.
Leif Gruenwoldt
@ KromStern Hmm Saya kesulitan mereproduksi ini. Tanpa pengaturan ulang cooridor, agen saya dapat ditekan oleh agen lain. Apakah itu perlu?
Leif Gruenwoldt
Saya mencoba menambahkan ini ke resetMoveTargetlokal tetapi saya tidak melihat perbedaan. ag->corridor.reset(ag->corridor.getFirstPoly(), agent->npos);
Leif Gruenwoldt
1
Untuk beberapa alasan aneh saya tidak dapat mereproduksinya sekarang juga. Sepertinya sesuatu yang lain telah berubah sejak saat itu. Bagaimanapun, terima kasih atas partisipasi Anda! :)
Kromster
0

Saya tidak yakin tetapi dugaan saya akan memanggil "requestMoveVelocity" dengan nol-vektor juga pada agen itu. Cobalah.

Rokannon
sumber
0

Catatan: Solusi ini tampaknya berlebihan, tetapi saya membiarkannya jika masalah muncul kembali.

Setelah banyak decoding, coba-coba saya ambil dtCrowd.resetMoveTargetsebagai basis dan menemukan cara untuk memodifikasinya:

procedure TKMTerrainNavigation.AgentTargetClear(aIdx: Integer);
var
  ag: PdtCrowdAgent;
begin
  ag := fRecastCrowd.getAgent(aIdx);

  ag.targetRef := 0;
  dtVset(@ag.targetPos[0], 0, 0, 0);
  ag.targetPathqRef := DT_PATHQ_INVALID;
  ag.targetReplan := False;
  ag.targetState := DT_CROWDAGENT_TARGET_NONE;

  // Reset desired velocity
  dtVset(@ag.dvel[0], 0, 0, 0); 

  // Reset agents corridor so that agent won't try to walk back to his last corner
  ag.ncorners := 0;
end;

PS Di atas kode dalam Delphi, tetapi harus bekerja dengan baik di C ++.

Penulis Recast Navigation berkomentar:

Alih-alih mengatur ulang sudut, Anda harus mengatur ulang koridor ke posisi agen saat ini dan poligon pertama.

Menetapkan posisi target ke posisi agen saat ini umumnya lebih disukai, daripada mengaturnya ke 0,0,0. Tapi Anda mengatur ulang semuanya juga, saya pikir tidak masalah.

Kromster
sumber