Download

Spawning Actor problems

Whenever I spawn a new actor the old actor that last spawned main mesh becomes unhidden even though it is hidden causing and overlap of two actors. Thank you for the help.

Player.h

	/**PLAYER INFO**/

	// Player Target class
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target")
	TSubclassOf<class ATarget> TargetClass;

	// Player Equipped Target
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target")
	ATarget* EquippedTarget;

	// Does player have a equiped weapon
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target")
	bool IsTargetEquipped;

	/**PLAYER FUNCTIONS**/

	// Player Action Functions //

	// Spawns Equipped Target
	UFUNCTION(BlueprintCallable)
	void SpawnTarget();

};

Player.cpp

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

	IsTargetEquipped = false;

}

// Called when the game starts or when spawned
void ATWTPlayer::BeginPlay()
{
	Super::BeginPlay();
	
	SpawnWeapon();
	SpawnTarget();
}

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

	if (IsWeaponEquipped == false && EquippedWeapon->bIsOnTarget == true)
	{
		SpawnWeapon();
	}

	if (IsTargetEquipped == false && EquippedTarget->bHasBroke == true)
	{
		SpawnTarget();
	}

}

void ATWTPlayer::SpawnTarget()
{
	UE_LOG(LogTemp, Warning, TEXT("SpawnedTarget"));
	IsTargetEquipped = true;

	const FVector Location = TargetSpawnPoint->GetComponentLocation();
	const FRotator Rotation = TargetSpawnPoint->GetComponentRotation();
	ATarget* TempTarget = GetWorld()->SpawnActor<ATarget>(TargetClass, Location, Rotation);
	EquippedTarget = TempTarget;
	
}

Target.h

UCLASS()
class TWT_API ATarget : public AActor
{
	GENERATED_BODY()
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
	TArray<UStaticMeshComponent*> BreakableComponents;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
	TArray<AWeapon*> WeaponComponents;

	/**VARIABLES**/
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
	bool bDestroyed;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
	FName BreakableTag;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
	FName WeaponTag;

	bool bHasBroke;

	FTimerHandle ForceSleepTimerHandle;
	FTimerHandle DestroyAfterBreakTimerHandle;
	FTimerHandle DestroyWeaponTimerHandle;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Timer")
	float ForceSleepDelay;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Timer")
	float DestroyActorDelay;

	/**FUNCTIONS**/
	UFUNCTION()
	TArray<AWeapon*> GetWeaponComponents();
	UFUNCTION()
	void WeaponsOnBreak(FVector DealerLocation);

	// Actor Destruction
	UFUNCTION()
	void ConfigureBreakableOnStart();
	UFUNCTION()
	TArray<UStaticMeshComponent*> GetBreakableComponents();
	UFUNCTION()
	void ShowBreakables(FVector DealerLocation);
	UFUNCTION()
	void Break(AActor* BreakingActor);
	UFUNCTION()
	void OnPartPutToSleep(UPrimitiveComponent* Comp);
	UFUNCTION()
	void ForceSleep();
	UFUNCTION()
	void DestroyAfterBreaking();

	// OnEvents
	UFUNCTION()
	void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION()
	void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

	UFUNCTION(BlueprintImplementableEvent)
	void OnPartHitBP(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);


};

Target.cpp

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

	// Components
	RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootComp"));
	RootScene->SetMobility(EComponentMobility::Movable);
	RootComponent = RootScene;

	Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BaseMeshComp"));
	Mesh->SetMobility(EComponentMobility::Movable);
	Mesh->SetupAttachment(RootScene);

	ImpactCollision = CreateDefaultSubobject<USphereComponent>(TEXT("ImpactCollisionComp"));
	ImpactCollision->SetMobility(EComponentMobility::Movable);
	ImpactCollision->SetupAttachment(Mesh);

	WeakPointCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("WeakPointCollisionComp"));
	WeakPointCollision->SetMobility(EComponentMobility::Movable);
	WeakPointCollision->SetupAttachment(Mesh);

	Force = CreateDefaultSubobject<URadialForceComponent>(TEXT("RadialForceComp"));
	Force->SetMobility(EComponentMobility::Movable);
	Force->SetupAttachment(RootScene);
	Force->Radius = 200.f;
	Force->bImpulseVelChange = true;
	Force->AddCollisionChannelToAffect(ECC_WorldDynamic);

	/* set collisions */
	Mesh->SetCollisionObjectType(ECC_WorldDynamic);
	Mesh->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	Mesh->SetCollisionResponseToAllChannels(ECR_Ignore);
	Mesh->SetCanEverAffectNavigation(false); // we don't want to change our navigation 

	ImpactCollision->SetSphereRadius(75.f);
	ImpactCollision->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	ImpactCollision->SetCollisionObjectType(ECC_WorldDynamic);
	ImpactCollision->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
	ImpactCollision->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Ignore);
	ImpactCollision->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
	ImpactCollision->SetCanEverAffectNavigation(true);

	WeakPointCollision->SetBoxExtent(FVector(16.f, 16.f, 3.f));
	WeakPointCollision->SetRelativeLocation(FVector(0.f, 0.f, 100.f));
	WeakPointCollision->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	WeakPointCollision->SetCollisionObjectType(ECC_WorldDynamic);
	WeakPointCollision->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
	WeakPointCollision->SetCanEverAffectNavigation(true);

	// Variables
	Points = 5.0f;
	RotationSpeed = 50.0f;
	IsAllOff = false;
	bRotate = true;
	BreakableTag = "Part";
	WeaponTag = "Weapon";
	ImpulseStrength = -1;
	ForceSleepDelay = 3;
	DestroyActorDelay = 6;
	bHasBroke = false;
}

// Called when the game starts or when spawned
void ATarget::BeginPlay()
{
	Super::BeginPlay();

	ConfigureBreakableOnStart();

	WeakPointCollision->OnComponentBeginOverlap.AddDynamic(this, &ATarget::OnOverlapBegin);
}

TArray<AWeapon*> ATarget::GetWeaponComponents()
{
	if (WeaponComponents.Num() == 0) // do we have cached data?
	{
		TArray<AWeapon*> Weapons;
		AWeapon* CurrentWeapon;

		TArray<AActor*> AttachedActors;
		GetAttachedActors(AttachedActors); // Get all the attached actors to target

		Weapons.Reserve(AttachedActors.Num()); // reserve size
		for (auto* Attached : AttachedActors)
		{
			if (Attached->ActorHasTag(WeaponTag))
			{
				CurrentWeapon = Cast<AWeapon>(Attached);
				Weapons.Push(CurrentWeapon); // Get the attached weapons
			}
		}
		WeaponComponents = Weapons; // cache data for later use
	}
	return WeaponComponents;
}

void ATarget::WeaponsOnBreak(FVector DealerLocation)
{
	for (AWeapon* Weapon : GetWeaponComponents()) // get all Weapons 
	{
		Weapon->Mesh->SetMobility(EComponentMobility::Movable);
		FBodyInstance* RootBI = Weapon->Mesh->GetBodyInstance(NAME_None, false); // check if we have body instance
		if (RootBI)
		{
			RootBI->bGenerateWakeEvents = true; // we do want to have physics events on parts 
			RootBI->bNotifyRigidBodyCollision = true; // make sure we get OnComponentHit event 
		}

		Weapon->Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); // enable collision
		Weapon->Mesh->SetSimulatePhysics(true); // enable physics
	}
}

void ATarget::ConfigureBreakableOnStart()
{

	for (UStaticMeshComponent* Comp : GetBreakableComponents()) // get all parts 
	{
		Comp->SetCollisionEnabled(ECollisionEnabled::NoCollision); // disable collision
		Comp->SetCollisionResponseToAllChannels(ECR_Ignore); // ignore everything
		Comp->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); // parts should block only static (eg. world)
		Comp->SetMobility(EComponentMobility::Static); // always remember to set static if something isn't moving
		Comp->SetHiddenInGame(true); // hide parts on start, we have base mesh to show whole mesh
	}
}

TArray<UStaticMeshComponent*> ATarget::GetBreakableComponents()
{
	if (BreakableComponents.Num() == 0) // do we have cached data?
	{
		TInlineComponentArray<UStaticMeshComponent*> ComponentsByClass; //store all static mesh components 
		GetComponents(ComponentsByClass);

		TArray<UStaticMeshComponent*> ComponentsByTag; // store all static mesh components with "part" tag which are our parts
		ComponentsByTag.Reserve(ComponentsByClass.Num()); // reserve size
		for (UStaticMeshComponent* Component : ComponentsByClass)
		{
			if (Component->ComponentHasTag(BreakableTag))
			{
				ComponentsByTag.Push(Component);
			}
		}
		BreakableComponents = ComponentsByTag; // cache data for later use
	}
	return BreakableComponents;
}

void ATarget::ShowBreakables(FVector DealerLocation)
{
	FVector Impulse = (DealerLocation - GetActorLocation()).GetSafeNormal() * ImpulseStrength; // setup impulse vector based on dealer location
	for (UStaticMeshComponent* Comp : GetBreakableComponents()) // get all parts 
	{
		Comp->SetMobility(EComponentMobility::Movable); //we will enable physics so they need to be movable from now
		FBodyInstance* RootBI = Comp->GetBodyInstance(NAME_None, false); // check if we have body instance
		if (RootBI)
		{
			RootBI->bGenerateWakeEvents = true; // we do want to have physics events on parts 
			RootBI->bNotifyRigidBodyCollision = true; // make sure we get OnComponentHit event 

			Comp->OnComponentHit.AddDynamic(this, &ATarget::OnHit); // If Comp hits it plays effects
		}

		Comp->SetHiddenInGame(false); // show part 
		Comp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); // enable collision
		Comp->SetSimulatePhysics(true); // enable physics
		Comp->AddImpulse(Impulse, NAME_None, true); // fire impulse 
	}
}

void ATarget::Break(AActor* BreakingActor)
{
	if (bDestroyed) // if Target destroyed
		return;

	bDestroyed = true;
	TWTPlayer->IsTargetEquipped = false;

	Mesh->SetHiddenInGame(true); // hide base mesh as it isn't needed from now
	Mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision); // disable collision on base mesh
	ImpactCollision->SetCollisionEnabled(ECollisionEnabled::NoCollision); // disable collision 
	ShowBreakables(BreakingActor->GetActorLocation()); // show parts 
	WeaponsOnBreak(BreakingActor->GetActorLocation());
	Force->bImpulseVelChange = true; 
	Force->FireImpulse(); // fire out radial force

	GetWorld()->GetTimerManager().SetTimer(ForceSleepTimerHandle, this, &ATarget::ForceSleep, ForceSleepDelay, false); // force sleep if we don't get event from physics
	
	GetWorld()->GetTimerManager().SetTimer(DestroyAfterBreakTimerHandle, this, &ATarget::DestroyAfterBreaking, DestroyActorDelay, false); // setup timer to check if we can destroy whole actor
}

void ATarget::OnPartPutToSleep(UPrimitiveComponent* Comp)
{
	Comp->SetSimulatePhysics(false); // disable physics 
	Comp->SetCollisionEnabled(ECollisionEnabled::NoCollision); // disable collision 
	Comp->SetMobility(EComponentMobility::Static); // mark part as static from now
	/* at this point part is static and won't interact with world */

}

void ATarget::ForceSleep()
{
	bHasBroke = true;
	
	for (UStaticMeshComponent* Comp : GetBreakableComponents()) // get all parts 
	{
		if (Comp->RigidBodyIsAwake())
		{
			// check if physics is running
			OnPartPutToSleep(Comp); // put part to sleep
		
		}
			
	}

	GetWorld()->GetTimerManager().ClearTimer(ForceSleepTimerHandle); // clear forcing to sleep timer 
	
}

void ATarget::DestroyAfterBreaking()
{

	Destroy(); // finally destroy actor

	for (AWeapon* Weapon : GetWeaponComponents()) // Destroy all weapons
	{
		Weapon->Destroy();
	}

	GetWorld()->GetTimerManager().ClearTimer(DestroyAfterBreakTimerHandle); // clear timer
}

void ATarget::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{

	// Check if weapon overlapped if it did break the target
	if (OtherActor)
	{
		AWeapon* Weapon = Cast<AWeapon>(OtherActor);

		if (Weapon) 
		{
			GetWorld()->GetTimerManager().SetTimer(DestroyWeaponTimerHandle, Weapon, &AWeapon::DestroyOverlappedWeapon, 6.f, false);
			Weapon->bWeaponHasHitWeakPoint = true;
			Weapon->Mesh->SetMobility(EComponentMobility::Movable);
			Weapon->Mesh->SetHiddenInGame(false); // show part 
			Weapon->Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); // enable collision
			Weapon->Mesh->SetSimulatePhysics(true); // enable physics
			Weapon->bIsOnTarget = true;
			
			Break(this);
			Mesh->DestroyComponent();
		}
	}
}

Hi there - Welcome to the Unreal forums!

In order for us to better answer your questions, can you please format your code with three backticks around the top and bottom (`)

so that the code appears like this

Secondly, could you please trim your post to show less irrelevant code - I can’t see a reference to main mesh in the code, so I’m unsure as to where your problem lies.

HI, didn’t realize there was a format thank you.

No worries, everybody learns sometime. Could you do the above next please?

The main mesh that I’m referring to would be the ATarget EquippedTarget Staticmeshcomp named Mesh. I just trimmed the code a bit I hope its bit less chaotic, but recently I’ve received an error after running my game in the editor and this is what has popped up. I don’t know if could this could be why it’s not working how it should be?

AttachTo: '/Game/TWT/Maps/UEDPIE_0_PlayMap.PlayMap:PersistentLevel.BP_Target_C_2.RootComp' is not static  (in blueprint "BP_Target"), cannot attach '/Game/TWT/Maps/UEDPIE_0_PlayMap.PlayMap:PersistentLevel.BP_Target_C_2.Target01_Sphere_cell_082' which is static to it. Aborting.

That won’t be part of your problem.

Now I see more of your situation - Have you tried putting a breakpoint on all the lines that change the visibility of Mesh to true, then inspecting the call stack to see where the execution came from?

I did exactly what you told me to do but I didn’t receive any good results so I decided to remake it on another project using blueprints to make a fast prototype and it does exactly what I was wanting so I don’t understand where It went wrong? I did not add in certain parts of my code to this project so I’m coming to a conclusion it could be something I have left out of the blueprints.

I found the problem and its quite embarrassing lol It was actually working exactly how it should be its just I forgot to hide the decal my target class had in its blueprint when the target breaks and it made me think it respawned when the decal was just actually projecting on to the new target. But anyways thanks for the help.