x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Resetting objects in a level

Hello,

I'm trying to implement functionality to restart the round. This includes restoring all of the objects in the current level to their original state. I would like to accomplish this without having to call ServerTravel, or anything that requires the engine to reload the entire map. That, in my opinion, is a bad solution.

I'm using version 4.7.6.

Here's what I have so far:

-In my GameMode header, I keep an array of AActors:

 UPROPERTY()
 TArray<AActor *> currentRoundActors;

These are the actors that are present at the beginning of the round.

-When the BeginPlay is called, I populate the array:

 void ANimModGameMode::BeginPlay()
 {
     Super::BeginPlay();
 
     for (FActorIterator It(GetWorld()); It; ++It)
     {
         AActor* A = *It;
         if (A && A != this && !A->IsA<AController>() && ShouldReset(A))
         {
             currentRoundActors.Add(A);
         }
     }
 }
 

  • have a trigger volume that, when triggered by a certain player, will: -freeze all of the players in the game. -start a timer

-When the timer expires, it will call "RestartRound" on the current GameMode:

 #define ISSERVER (GEngine->GetNetMode(GetWorld()) < NM_Client)

 void ANimModGameMode::RestartRound()
 {
     if (!ISSERVER)
         return;
     //Players should already be frozen
     //FreezePlayers();
 
     // Reset all actors (except controllers, the GameMode, and any other actors specified by ShouldReset())
     //TODO: This doesn't handle actors that are in currentRoundActors that have been destroyed before this point.
     //We need to find a way to respawn those, as well.
     TArray<AActor *> destroyActors;
     TArray<AActor *> respawnActors;
     for (FActorIterator It(GetWorld()); It; ++It)
     {
         AActor* A = *It;
         if (A && A != this && !A->IsA<AController>() && ShouldReset(A))
         {
             if (currentRoundActors.Contains(A))
             {
                 respawnActors.Add(A);
                 currentRoundActors.Remove(A);
             }
             else
                 destroyActors.Add(A);
         }
     }
 
     //Whatever is left is something that is pending being deleted, or is deleted.
     //Respawn what we can.
     for (AActor *A : currentRoundActors)
     {
         if (A == nullptr)
         {
             destroyActors.Add(A);
             continue;
         }
 
         if (ShouldReset(A))
         {
             respawnActors.Add(A);
         }
     }
 
     //Respawn the ones that we do want.
     while (respawnActors.Num() > 0)
     {
         AActor *A = respawnActors[0];
         if (A == nullptr)
                 {
                         respawnActors.RemoveAt(0);
             continue;
                 }
 
         //Add a new actor as a copy of the 'reloaded' one, since the reloaded one is disappearing.
         FActorSpawnParameters spawnParams;
         spawnParams.Template = A;
         /*spawnParams.bNoFail = true;
         spawnParams.bNoCollisionFail = true;
         spawnParams.Name = NAME_None;*/
         //A->SetReplicates(true);
         FVector orig = A->GetActorLocation();
         FRotator rot = A->GetActorRotation();
         AActor *newActor = GetWorld()->SpawnActor
         (
             A->GetClass(),
             &orig,
             &rot,
             spawnParams
         );
         if (newActor == nullptr)
             continue;
 
         //newActor->SetOwner(A->GetOwner());
 
         //Add the new one
         currentRoundActors.Add(newActor);
         if (currentRoundActors.Contains(A))
             currentRoundActors.Remove(A);
         //Remove the old one
         destroyActors.Add(A);
 
         respawnActors.RemoveAt(0);
     }
 
     //Destroy all of the actors we don't want.
     while (destroyActors.Num() > 0)
     {
         AActor *actor = destroyActors[0];
         destroyActors.RemoveAt(0);
         //This can (theoretically happen) if we added something that has already been deleted.
         if (actor == nullptr)
             continue;
 
         actor->Destroy(true, true);
         actor = nullptr;
     }
 
     //GetWorld()->ForceGarbageCollection(true); //...Maybe?
 
     // reset the GameMode...Which does ****-all.
     //Reset();
 
     // Notify the level script that the level has been reset
     ALevelScriptActor* LevelScript = GetWorld()->GetLevelScriptActor();
     if (LevelScript)
     {
         LevelScript->LevelReset();
     }
 
     //'Respawn' the players
     for (FConstControllerIterator Iterator = GetWorld()->GetControllerIterator(); Iterator; ++Iterator)
     {
         AController* Controller = *Iterator;
         ANimModPlayerController* PlayerController = Cast<ANimModPlayerController>(Controller);
         if (PlayerController)
         {
             RestartPlayer(PlayerController);
             //PlayerController->ClientRestartRound();
             //PlayerController->ServerRestartPlayer();
         }
         else
             Controller->Reset();
     }
 
     //Unfreeze the players.
     UnfreezePlayers();
 }

Just in case someone wants to see what my "ShouldReset" looks like:

 bool ANimModGameMode::ShouldReset(AActor* ActorToReset)
 {
     UClass *actorClass = ActorToReset->GetActorClass();
     AGameNetworkManager *networkManager = Cast<AGameNetworkManager>(ActorToReset);
     //AParticleEventManager *particleEventManager = Cast<AParticleEventManager>(ActorToReset);
     if
     (
         actorClass->IsChildOf(UWorld::StaticClass()) ||
         actorClass->IsChildOf(APlayerController::StaticClass()) ||
         actorClass->IsChildOf(ACharacter::StaticClass()) ||
         actorClass->IsChildOf(AGameMode::StaticClass()) ||
         actorClass->IsChildOf(APlayerCameraManager::StaticClass()) ||
         actorClass->IsChildOf(APlayerStart::StaticClass()) ||
         actorClass->IsChildOf(AHUD::StaticClass()) ||
         actorClass->IsChildOf(UGameViewportClient::StaticClass()) ||
         actorClass->IsChildOf(AGameSession::StaticClass()) ||
         /*actorClass->IsChildOf(AGameNetworkManager::StaticClass()) ||*/
         actorClass->IsChildOf(APlayerState::StaticClass()) ||
         actorClass->IsChildOf(AWorldSettings::StaticClass()) ||
         actorClass->IsChildOf(AGameState::StaticClass()) ||
         actorClass->IsChildOf(AVIPTrigger::StaticClass()) ||
         actorClass->IsChildOf(ULevel::StaticClass()) ||
         actorClass->IsChildOf(ALight::StaticClass()) ||
         actorClass->IsChildOf(ALevelScriptActor::StaticClass()) ||
         actorClass->IsChildOf(ALightmassImportanceVolume::StaticClass()) ||
         actorClass->IsChildOf(APostProcessVolume::StaticClass()) ||
         actorClass->IsChildOf(ANavigationData::StaticClass()) ||
         actorClass->IsChildOf(AAtmosphericFog::StaticClass()) ||
         actorClass->IsChildOf(ASpectatorPawn::StaticClass()) ||
 /*#ifdef DEBUG*/
         actorClass->IsChildOf(AGameplayDebuggingReplicator::StaticClass()) ||
 /*#endif*/
         /*particleEventManager != nullptr ||*/
         (AActor *)GetWorld()->MyParticleEventManager == ActorToReset ||
         networkManager != nullptr
     )
         return false;
 
     if (currentRoundActors.Contains(ActorToReset) && ActorToReset->IsPendingKill())
         return true;
 
     if (ActorToReset->IsRootComponentStatic())
         return false; //I...think...
     
     return true;
 }

Now, this code works(ish) when I'm testing in with 1 player in a non-dedicated server. If I test with two players in a dedicated server, the objects stay the way they are. Sometimes I can get them to disappear from the clients, altogether, but it's clear that they respawned on the server, because I "collide" with empty air where the objects are supposed to be.

I also tried using "FReloadObjectArc". Instead of storing a pointer to the Actors at when BeginPlay was called, I was serializing them in to their own FReloadObjectArc, then trying to overwrite them in "RestartRound". That didn't do anything.

I'm close (I think). I just need to know why the objects aren't respawning on the clients. And why static mesh actors aren't respawning at all.

Thoughts?

Product Version: UE 4.8
Tags:
more ▼

asked Jun 14 '15 at 12:16 AM in C++ Programming

avatar image

Nimgoble
31 1 3 8

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

thank you very much kamera sistemleri

more ▼

answered Jun 14 '15 at 01:22 AM

avatar image

kamerasistemleri
0

avatar image Nimgoble Jun 14 '15 at 01:39 AM

.......wat

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question