Thema: AI, CanSeePlayer?

  • Hallo, wie geht ihr da vor?

    1. Frage:

    ich habe diese Funktion:


    void PerceptionUpdated(const TArray<AActor*>& UpdatedActors);


    //In "UpdatedActors" werden alle Actoren gesammelt, die von der AI erblickt werden. Ist vielleicht eine Grundlegende Frage, aber ich frage mich gerade, da ich diese Funktion im AIController erstellt habe, woher weiß diese Funktion, dass sie in ihrem "UpdatedActors" Actoren sammeln soll? Es ist ja meine frisch erstellte Funktion.


    2. Frage:

    sobald die AI jemanden sieht in ihrer Sichtweite, kann ich zum Beispiel die Location des Gesichteten in ihr Blackboard speichern. Wie gehe ich nun vor, dass die AI auch merkt, wenn der Gesichtete wieder weg ist?

  • Hallo


    Der Perceptioncomponent hat Multicast Delegates die die nutzen kannst. Hier der Sourcecode davon.

    Code
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPerceptionUpdatedDelegate, const TArray<AActor*>&, UpdatedActors);
    FPerceptionUpdatedDelegate OnPerceptionUpdated;


    Dieses Deleagte wird im ProcessStimuli vom PerceptionComponent broadcasted. Vereinfacht dann, wenn sich etwas relevantes im Sichtfeld verändert.


    Du musst also deine Update methode dem Delegate hinzufügen.

    Code
    PerceptionComponent->OnPerceptionUpdated.AddDynamic(this, &AMyCharacter::PerceptionUpdated);

    Wenn sich nun etwas im Sichtfeld verändert, wird deine PerceptionUpdates Methode aufgerufen. Das heisst, du weisst immer, was du gerade siehst.


    Gruss

  • ah vielen dank, jetzt geschnallt.

    Zu meiner zweiten Frage, das raffe ich einfach nicht, wie merken eure AI's, dass kein Gegner mehr in Sicht ist?

    Ich checke nämlich mein Array, ob Gegner in Sicht sind, sobald etwas in Sicht ist, löst die Funktion aus, alles prima. Aber wie oder was löst aus, wenn dieses etwas das Sichtfeld wieder verlässt, was löst dann aus?

    Ich finde einfach auch im Netz keine vernünftige Antwort.

  • OnPerceptionUpdated wird nicht nur dann aufgerufen, wenn etwas neues wahrgenommen wird, sondern auch dann, wenn etwas, das wahrgenommen wurde nicht mehr wahrgenommen wird.


    Also vereinfacht, es wird aufgerufen, wenn es ins Sichtfeld tritt und erneut wenn es das Sichtfeld wieder verlässt.

    Du kannst in deiner Update Methode alle wahrgenommenen Actor ausgeben lassen.


    • Hilfreich

    Welcher Teil?

    Code
        TArray<AActor*> OutActors;
        PerceptionComponent->GetCurrentlyPerceivedActors(Sight->GetSenseImplementation(), OutActors);

    Das snippet speichert dir alle aktuell wahrgenommene Actors im OutActorts Array. Das sind alle Actoren aktuell im Sichtfeld.


    Dann können wir über diese im Sichtfeld befindenen Actoren durch loopen, dann printe ich jeden einzelenen Name davon auf den Screen.

    Code
        for (AActor* OutActor : OutActors)
        {
            GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red,
                                             FString::Printf(TEXT("I can see you %s"), *OutActor->GetName()));
        }

    Das war auch schon.

  • ich verstehe dieses Wahrnehmungssystem einfach nicht, ich mache folgendes:


    void AEnemyController::PerceptionUpdated(const TArray<AActor*>& UpdatedActors)

    {

    int32 Anzahl = UpdatedActors.Num();


    UE_LOG(LogTemp, Warning, TEXT("Ich sehe soviele %d"), Anzahl);

    }


    und er spuckt mir ständig nur 1 aus.

    Das Array müsste doch größer oder kleiner werden, je nachdem ob einer in Sichtweite kommt oder die Sichtweite verlässt.

    Kann mir das einer erklären???

  • und er spuckt mir ständig nur 1 aus.

    Das Array müsste doch größer oder kleiner werden, je nachdem ob einer in Sichtweite kommt oder die Sichtweite verlässt.

    Kann mir das einer erklären???

    Nein, UpdatedActors sind nur die Actors die ein Update erhalten haben. Das ist unabhängig davon ob in Sichtweite oder nicht.


    Gruss

  • hm, ok,


    Ich hab ein Array voller erfasster Gegnern, die aber aus dem Array nicht mehr verschwinden?


    Alles was ich will, ist ein Boolean "bCanSeePlayer" zu haben, das erfasst, wann ein Gegner sichtbar wird und wann es wieder außer Sichtweite ist.

    Im zweiten Schritt hätte ich gerne, dass er immer den am nächsten gelegenen nimmt.


    Kannst du mir bitte, oder jemand, ein ganz einfaches Beispiel aufschreiben?

    Auf Grundlage dieser Funktion:


    void AEnemyController::PerceptionUpdated(const TArray<AActor*>& UpdatedActors)

    {


    }

  • Schreib doch das Array der UpdatedActors in ne Variable in deinem Blueprint. Nennste die z.B. ArrayMyCurrentSensedActors oder so.


    Dann machst du ne Funktion CanAISeePlayer und alles was du da machst ist mit nem for loop durch das array zu gehen und wenn der Player unter den Actors ist halt das bool auf true ansonsten false.