Fix #1168 deregister registered actors on "OnDestroyed" event

This commit is contained in:
nsubiron 2019-01-27 19:13:36 +01:00
parent 67c2d900e5
commit 7cb8e00135
5 changed files with 54 additions and 32 deletions

View File

@ -12,7 +12,7 @@
#include "GameFramework/Controller.h"
void FActorDispatcher::Bind(FActorDefinition Definition, SpawnFunctionType Functor)
void UActorDispatcher::Bind(FActorDefinition Definition, SpawnFunctionType Functor)
{
if (UActorBlueprintFunctionLibrary::CheckActorDefinition(Definition))
{
@ -27,7 +27,7 @@ void FActorDispatcher::Bind(FActorDefinition Definition, SpawnFunctionType Funct
}
}
void FActorDispatcher::Bind(ACarlaActorFactory &ActorFactory)
void UActorDispatcher::Bind(ACarlaActorFactory &ActorFactory)
{
for (const auto &Definition : ActorFactory.GetDefinitions())
{
@ -37,7 +37,7 @@ void FActorDispatcher::Bind(ACarlaActorFactory &ActorFactory)
}
}
TPair<EActorSpawnResultStatus, FActorView> FActorDispatcher::SpawnActor(
TPair<EActorSpawnResultStatus, FActorView> UActorDispatcher::SpawnActor(
const FTransform &Transform,
FActorDescription Description)
{
@ -59,7 +59,7 @@ TPair<EActorSpawnResultStatus, FActorView> FActorDispatcher::SpawnActor(
Result.Status = EActorSpawnResultStatus::UnknownError;
}
auto View = Result.IsValid() ? Registry.Register(*Result.Actor, std::move(Description)) : FActorView();
auto View = Result.IsValid() ? RegisterActor(*Result.Actor, std::move(Description)) : FActorView();
if (!View.IsValid())
{
@ -70,7 +70,7 @@ TPair<EActorSpawnResultStatus, FActorView> FActorDispatcher::SpawnActor(
return MakeTuple(Result.Status, View);
}
bool FActorDispatcher::DestroyActor(AActor *Actor)
bool UActorDispatcher::DestroyActor(AActor *Actor)
{
if (Actor == nullptr) {
UE_LOG(LogCarla, Error, TEXT("Trying to destroy nullptr actor"));
@ -102,9 +102,18 @@ bool FActorDispatcher::DestroyActor(AActor *Actor)
UE_LOG(LogCarla, Log, TEXT("Destroying actor: '%s'"), *Id);
if (Actor->Destroy())
{
Registry.Deregister(Actor);
return true;
}
UE_LOG(LogCarla, Error, TEXT("Failed to destroy actor: '%s'"), *Id);
return false;
}
FActorView UActorDispatcher::RegisterActor(AActor &Actor, FActorDescription Description)
{
auto View = Registry.Register(Actor, std::move(Description));
if (View.IsValid())
{
Actor.OnDestroyed.AddDynamic(this, &UActorDispatcher::OnActorDestroyed);
}
return View;
}

View File

@ -14,12 +14,17 @@
#include "Containers/Array.h"
#include "Templates/Function.h"
#include "ActorDispatcher.generated.h"
class ACarlaActorFactory;
/// Actor in charge of binding ActorDefinitions to spawn functions, as well as
/// Object in charge of binding ActorDefinitions to spawn functions, as well as
/// keeping the registry of all the actors spawned.
class FActorDispatcher
UCLASS()
class CARLA_API UActorDispatcher : public UObject
{
GENERATED_BODY()
public:
using SpawnFunctionType = TFunction<FActorSpawnResult(const FTransform &, const FActorDescription &)>;
@ -51,16 +56,15 @@ public:
/// destruction, false if indestructible or nullptr.
bool DestroyActor(AActor *Actor);
/// Register an actor that was not created using "SpawnActor" function but
/// that should be kept in the registry.
FActorView RegisterActor(AActor &Actor, FActorDescription ActorDescription);
const TArray<FActorDefinition> &GetActorDefinitions() const
{
return Definitions;
}
FActorRegistry &GetActorRegistry()
{
return Registry;
}
const FActorRegistry &GetActorRegistry() const
{
return Registry;
@ -68,6 +72,12 @@ public:
private:
UFUNCTION()
void OnActorDestroyed(AActor *Actor)
{
Registry.Deregister(Actor);
}
TArray<FActorDefinition> Definitions;
TArray<SpawnFunctionType> SpawnFunctions;

View File

@ -38,7 +38,9 @@ UCarlaEpisode::UCarlaEpisode(const FObjectInitializer &ObjectInitializer)
Id([]() {
static uint32 COUNTER = 0u;
return ++COUNTER;
}()) {}
}()) {
ActorDispatcher = CreateDefaultSubobject<UActorDispatcher>(TEXT("ActorDispatcher"));
}
TArray<FTransform> UCarlaEpisode::GetRecommendedSpawnPoints() const
{
@ -90,7 +92,7 @@ void UCarlaEpisode::InitializeAtBeginPlay()
FActorDescription Description;
Description.Id = TEXT("spectator");
Description.Class = Spectator->GetClass();
ActorDispatcher.GetActorRegistry().Register(*Spectator, Description);
ActorDispatcher->RegisterActor(*Spectator, Description);
}
else
{
@ -104,6 +106,6 @@ void UCarlaEpisode::InitializeAtBeginPlay()
FActorDescription Description;
Description.Id = UCarlaEpisode_GetTrafficSignId(Actor->GetTrafficSignState());
Description.Class = Actor->GetClass();
ActorDispatcher.GetActorRegistry().Register(*Actor, Description);
ActorDispatcher->RegisterActor(*Actor, Description);
}
}

View File

@ -58,7 +58,7 @@ public:
UFUNCTION(BlueprintCallable)
const TArray<FActorDefinition> &GetActorDefinitions() const
{
return ActorDispatcher.GetActorDefinitions();
return ActorDispatcher->GetActorDefinitions();
}
/// Return the list of recommended spawn points for vehicles.
@ -90,7 +90,7 @@ public:
const FActorRegistry &GetActorRegistry() const
{
return ActorDispatcher.GetActorRegistry();
return ActorDispatcher->GetActorRegistry();
}
// ===========================================================================
@ -105,7 +105,7 @@ public:
/// invalid.
FActorView FindActor(FActorView::IdType ActorId) const
{
return ActorDispatcher.GetActorRegistry().Find(ActorId);
return ActorDispatcher->GetActorRegistry().Find(ActorId);
}
/// Find the actor view of @a Actor.
@ -114,7 +114,7 @@ public:
/// invalid.
FActorView FindActor(AActor *Actor) const
{
return ActorDispatcher.GetActorRegistry().Find(Actor);
return ActorDispatcher->GetActorRegistry().Find(Actor);
}
/// Find the actor view of @a Actor. If the actor is not found, a "fake" view
@ -124,7 +124,7 @@ public:
/// If the actor is pending kill, the returned view is invalid.
FActorView FindOrFakeActor(AActor *Actor) const
{
return ActorDispatcher.GetActorRegistry().FindOrFake(Actor);
return ActorDispatcher->GetActorRegistry().FindOrFake(Actor);
}
// ===========================================================================
@ -143,7 +143,7 @@ public:
const FTransform &Transform,
FActorDescription ActorDescription)
{
return ActorDispatcher.SpawnActor(Transform, std::move(ActorDescription));
return ActorDispatcher->SpawnActor(Transform, std::move(ActorDescription));
}
/// Spawns an actor based on @a ActorDescription at @a Transform. To properly
@ -170,7 +170,7 @@ public:
UFUNCTION(BlueprintCallable)
bool DestroyActor(AActor *Actor)
{
return ActorDispatcher.DestroyActor(Actor);
return ActorDispatcher->DestroyActor(Actor);
}
// ===========================================================================
@ -194,7 +194,7 @@ private:
void RegisterActorFactory(ACarlaActorFactory &ActorFactory)
{
ActorDispatcher.Bind(ActorFactory);
ActorDispatcher->Bind(ActorFactory);
}
const uint32 Id = 0u;
@ -202,7 +202,8 @@ private:
UPROPERTY(VisibleAnywhere)
FString MapName;
FActorDispatcher ActorDispatcher;
UPROPERTY(VisibleAnywhere)
UActorDispatcher *ActorDispatcher = nullptr;
UPROPERTY(VisibleAnywhere)
APawn *Spectator = nullptr;

View File

@ -75,21 +75,21 @@ static carla::Buffer AWorldObserver_Serialize(
write_data(header);
// Write every actor.
for (auto &&actor_view : Registry) {
check(actor_view.GetActor() != nullptr);
for (auto &&View : Registry) {
check(View.IsValid());
constexpr float TO_METERS = 1e-2;
const auto velocity = TO_METERS * actor_view.GetActor()->GetVelocity();
const auto velocity = TO_METERS * View.GetActor()->GetVelocity();
// get the angular velocity
const auto RootComponent = Cast<UPrimitiveComponent>(actor_view.GetActor()->GetRootComponent());
const auto RootComponent = Cast<UPrimitiveComponent>(View.GetActor()->GetRootComponent());
FVector angularVelocity { 0.0f, 0.0f, 0.0f };
if (RootComponent != nullptr)
angularVelocity = RootComponent->GetPhysicsAngularVelocityInDegrees();
ActorDynamicState info = {
actor_view.GetActorId(),
actor_view.GetActor()->GetActorTransform(),
View.GetActorId(),
View.GetActor()->GetActorTransform(),
carla::geom::Vector3D{velocity.X, velocity.Y, velocity.Z},
carla::geom::Vector3D{angularVelocity.X, angularVelocity.Y, angularVelocity.Z},
AWorldObserver_GetActorState(actor_view)
AWorldObserver_GetActorState(View)
};
write_data(info);
}