Нереальный сбой при вызове AI MoveToLocation

#c #unreal-engine4

Вопрос:

Сначала я протестировал следующий код в Blueprint и хотел перевести его на C . Я пытаюсь создать npc с триггерной сферой, которая активирует onOverlap и позволяет Npc уйти в противоположном направлении, откуда пришел игрок. Когда я играю в нереальный редактор и приближаюсь к Npc, он вылетает. Проблема в перемещении из AiController, но я не уверен, почему.

Вот схема (sry, если качество плохое) введите описание изображения здесь

Вот файлы AiController файла Npc .h:

 #include "CoreMinimal.h"
#include "AIController.h"
#include "SpiderAIController.generated.h"

/**
 * 
 */
UCLASS()
class SPIDERPROJECT0710_API ASpiderAIController : public AAIController
{
    GENERATED_BODY()

protected:
    virtual void BeginPlay() override;
    
    

public:
    UFUNCTION()
    void WalkAway(FVector Location, float Var); 
};
 

в .cpp

 #include "SpiderAIController.h"

void ASpiderAIController::BeginPlay()
 {
    Super::BeginPlay();   
 }

 void ASpiderAIController::WalkAway(FVector Location, float Var)
 {
    
    MoveToLocation(Location, Var);
 }
 

Вот файлы Npc:

необходимая часть файла .h

 private:
    UPROPERTY(VisibleAnywhere, Category = "Switch Components")         class USphereComponent* TriggerSphere;

    UPROPERTY()
    class ASpiderAIController* AIController;
     
    UFUNCTION()
    void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResultamp; SweepResult);

    
    //UFUNCTION()
    //void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

};
 

The cpp file:

 #include "SpiderCharacter.h"
#include "Components/SphereComponent.h"
#include "SpiderAIController.h"

// Sets default values
ASpiderCharacter::ASpiderCharacter()
{
    // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    TriggerSphere = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger Sphere"));
    TriggerSphere->InitSphereRadius(105.0f);
    TriggerSphere->SetCollisionProfileName(TEXT("Trigger"));
    TriggerSphere->SetupAttachment(RootComponent);

    TriggerSphere->OnComponentBeginOverlap.AddDynamic(this, amp;ASpiderCharacter::OnOverlapBegin); 
    AIController = Cast<ASpiderAIController>(GetController());

    
}

void ASpiderCharacter::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResultamp; SweepResult)
{
    if (OtherActor amp;amp; (OtherActor != this) amp;amp; OtherComp) 
    {
        //get Location and Roation of PlayerCharacter
        FVector PlayerPosition = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation();
        FRotator PlayerRotation = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorRotation();
        FVector NewLocation = FVector(PlayerPosition.X -500.f,PlayerPosition.Y - 500.f, PlayerPosition.Z);
        float Var = 100.f;

        SetActorRotation(PlayerRotation);
        AIController->WalkAway(NewLocation, Var);
        //SetActorLocation(NewLocation);

        
        UE_LOG(LogTemp,Warning,TEXT("MyCharacter's Location is %s"),  *OtherActor->GetName());
    }
} 
 

Сообщение об ошибке от Unreal:

 LoginId:c4c2e10f47cd9a4f6992fd821aae5406 EpicAccountId:92760ac7ea0e4f249688fd7737d3a55d

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000000000003b0

UE4Editor_AIModule UE4Editor_SpiderProject0710_4739!ASpiderAIController::WalkAway() [C:UsersalexaOneDriveDesktopUdemyUnreal EngineSpiderProject0710SourceSpiderProject0710SpiderAIController.cpp:19] 
UE4Editor_SpiderProject0710_4739!ASpiderCharacter::OnOverlapBegin() [C:UsersalexaOneDriveDesktopUdemyUnreal EngineSpiderProject0710SourceSpiderProject0710SpiderCharacter.cpp:62] 
UE4Editor_SpiderProject0710_4739!ASpiderCharacter::execOnOverlapBegin() [C:UsersalexaOneDriveDesktopUdemyUnreal EngineSpiderProject0710IntermediateBuildWin64UE4EditorIncSpiderProject0710SpiderCharacter.gen.cpp:38] 
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Core
UE4Editor_Core
UE4Editor_Core
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_UnrealEd
UE4Editor_UnrealEd
UE4Editor
UE4Editor
UE4Editor
UE4Editor
UE4Editor
kernel32
ntdll
 

Комментарии:

1. Вероятно, здесь GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation(); один из объектов не инициализирован, и вы получаете значение null.

2. Я тоже так думал, но я могу распечатать местоположение, не получая нулевого значения.

3. Проблема, похоже, в этой строке: AIController->WalkAway(NewLocation, Var); . Похоже, это исключение незаконного доступа к памяти, которое, короче говоря, вызывает ошибку сегментации. Происходит доступ к чему-то нулевому. Пожалуйста , проверьте, равно ли AIController NewLocation или Var равно нулю.

Ответ №1:

Я нашел проблему. Мне нужно было получить PlayerPawn и AiController в BeginPlay, а не в конструкторе класса. Я также переработал код.

npc .h:

 #pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SpiderCharacter.generated.h"

UCLASS()
class SPIDERPROJECT0710_API ASpiderCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    // Sets default values for this character's properties
    ASpiderCharacter();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    // Called to bind functionality to input
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;


private:
    UPROPERTY(VisibleAnywhere, Category = "Switch Components")         class USphereComponent* TriggerSphere;

    UPROPERTY()
    class ASpiderAIController* AIController;

    UPROPERTY()
    class APawn* PlayerPawn;
     
    UFUNCTION()
    void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResultamp; SweepResult);

    
    //UFUNCTION()
    //void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

};
 

и cpp:

 #include "SpiderCharacter.h"
#include "Components/SphereComponent.h"
#include "SpiderAIController.h"
#include "Kismet/GameplayStatics.h"

// Sets default values
ASpiderCharacter::ASpiderCharacter()
{
    // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    TriggerSphere = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger Sphere"));
    TriggerSphere->InitSphereRadius(105.0f);
    TriggerSphere->SetCollisionProfileName(TEXT("Trigger"));
    TriggerSphere->SetupAttachment(RootComponent);

    TriggerSphere->OnComponentBeginOverlap.AddDynamic(this, amp;ASpiderCharacter::OnOverlapBegin); 
    


    
}

// Called when the game starts or when spawned
void ASpiderCharacter::BeginPlay()
{
    Super::BeginPlay();
    AIController = Cast<ASpiderAIController>(GetController());
    PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
    //UE_LOG(LogTemp,Warning,TEXT("MyCharacter is %s"),  *PlayerPawn->GetName());
    
}

// Called every frame
void ASpiderCharacter::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void ASpiderCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

}

//Overlap Function
void ASpiderCharacter::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResultamp; SweepResult)
{
    if (OtherActor amp;amp; (OtherActor != this) amp;amp; OtherComp) 
    {
        //get Location and Roation of PlayerCharacter
        //FVector PlayerPosition = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation();
        //FRotator PlayerRotation = GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorRotation();
        FVector PlayerPosition = PlayerPawn->GetActorLocation();
        FRotator PlayerRotation = PlayerPawn->GetActorRotation();

        FVector NewLocation = FVector(PlayerPosition.X -500.f,PlayerPosition.Y - 500.f, PlayerPosition.Z);
        float Var = 100.f;

        SetActorRotation(PlayerRotation);
        AIController->WalkAway(NewLocation, Var);
        //SetActorLocation(NewLocation);

        
        UE_LOG(LogTemp,Warning,TEXT("MyCharacter's Location is %s"),  *OtherActor->GetName());
    }
}