Announcement

Collapse
No announcement yet.

Spawning actor behind another actor

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Spawning actor behind another actor

    Previously, I just spawned based on the location of the pawn - literally with GetActorLocation - which, while obviously not ideal and causes AI pathfinding issues (object occasionally spawning inside spawning AI) it worked well enough for prototyping and making sure that the AI functioned correctly etc.

    I was wondering, how would I go about spawning behind the actor a couple of units?

    Any help is greatly appreciated.

    #2
    Hi,

    I'm not really a vector magician, but the first thing comes to my mind is to rotate the ForwardVector of the OtherActor 180 and multiply it by the distance something like:
    Code:
    #include "Kismet/KismetMathLibrary.h"
    
    FRotator NewRotation = OtherActor->GetActorRotation();
    NewRotation.Yaw = NewRotation.Yaw + 180.0f;
    const float Distance = 500.0f;
    const FVector SpawnLocation = OtherActor->GetActorLocation() + (UKismetMathLibrary::GetForwardVector(NewRotation) * Distance)
    Last edited by Kontur; 07-01-2017, 10:13 PM.

    Comment


      #3
      Originally posted by Kontur View Post
      Hi,

      I'm not really a vector magician, but the first thing comes to my mind is to rotate the ForwardVector of the OtherActor 180 and multiply it by the distance something like:
      Code:
      #include "Kismet/KismetMathLibrary.h"
      
      FRotator NewRotation = OtherActor->GetActorRotation();
      NewRotation.Yaw = NewRotation.Yaw + 180.0f;
      const float Distance = 500.0f;
      const FVector SpawnLocation = OtherActor->GetActorLocation() + (UKismetMathLibrary::GetForwardVector(NewRotation) * Distance)
      I had wondered why that was not working, turns out I forgot to set it to SpawnLocation (oops! ). Fixed now. Thank you so much for your help!

      Additionally, do you know how to make it aware of the surroundings as to not spawn within a wall etc?

      Comment


        #4
        You would want to do some traces to determine that. It really depends on how complex you want it to make, but for a basic system, do a simple LineTrace from the back of the OtherActor to the SpawnLocation. If it was a bBlockingHit, then the ray could not reach the SpawnLocation->something is in the way.

        Comment


          #5
          Originally posted by Kontur View Post
          You would want to do some traces to determine that. It really depends on how complex you want it to make, but for a basic system, do a simple LineTrace from the back of the OtherActor to the SpawnLocation. If it was a bBlockingHit, then the ray could not reach the SpawnLocation->something is in the way.
          I would have to check the length of the trace as well, since otherwise it would hit walls on other side of level and fail, right?


          EDIT: Is this how I would do it (or similar)? https://wiki.unrealengine.com/Trace_...xample_Usage_3
          Last edited by Markyroson; 07-02-2017, 11:17 AM.

          Comment


            #6
            Originally posted by Markyroson View Post
            I would have to check the length of the trace as well, since otherwise it would hit walls on other side of level and fail, right?
            I'm not sure what you mean. I was assuming that you want to spawn an actor X distance behind another actor, and check if there is no wall between the two actors.

            If you do a line trace from the 'OtherActor' to the 'SpawnLocation', the ray should travel from 'OtherActor' to 'SpawnLocation'. If there is anything blocking the ray, the bBlockingHit flag will be set to true, so you know that there is something between the two actors. I'm not sure how distance comes into play?

            This is how I'd do the trace, assuming the 'OtherActor' is the Player:
            Code:
            //Retrieving the Player Character from the Player Controller.
            APlayerClass* MyPlayer = Cast<APlayerClass>(MyPlayerController->GetCharacter());
            
            if (MyPlayer != nullptr && GetWorld() != nullptr)
            {
            	//Initializing the Start Location of the trace to the world location of the "Player".
            	const FVector TraceStart = MyPlayer->GetActorLocation();
            
            	//Initializing the End Location of the trace to the previously calculated 'SpawnLocation'.
            	const FVector TraceEnd = SpawnLocation;
            
            	//Inititalizing the Line Trace Parameters.
            	FCollisionQueryParams TraceParameters = FCollisionQueryParams(FName(TEXT("Trace Parameters")));
            	TraceParameters.bTraceComplex = false;
            	TraceParameters.bTraceAsyncScene = true;
            	TraceParameters.bReturnPhysicalMaterial = false;
            
            	//Initializing the Line Trace ignore list.
            	TArray<AActor*> TraceIgnoreList;
            	TraceIgnoreList.Add(MyPlayer);
            	TraceParameters.AddIgnoredActors(TraceIgnoreList);
            
            	//Initializing the "TraceHitResult".
            	FHitResult TraceHitResult(ForceInit);
            
            	//Performing the actual trace on the 'Visibility' channel.
            	GetWorld()->LineTraceSingleByChannel(TraceHitResult, TraceStart, TraceEnd, ECC_Visibility, TraceParameters);
            			
            	//If the trace was not a blocking hit.
            	if (TraceHitResult.bBlockingHit == false)
            	{
                         //There is nothing blocking the ray between the two locations, we can spawn out actor at "SpawnLocation".
                    }

            Comment


              #7
              Originally posted by Kontur View Post
              I'm not sure what you mean. I was assuming that you want to spawn an actor X distance behind another actor, and check if there is no wall between the two actors.

              If you do a line trace from the 'OtherActor' to the 'SpawnLocation', the ray should travel from 'OtherActor' to 'SpawnLocation'. If there is anything blocking the ray, the bBlockingHit flag will be set to true, so you know that there is something between the two actors. I'm not sure how distance comes into play?

              This is how I'd do the trace, assuming the 'OtherActor' is the Player:
              Code:
              //Retrieving the Player Character from the Player Controller.
              APlayerClass* MyPlayer = Cast<APlayerClass>(MyPlayerController->GetCharacter());
              
              if (MyPlayer != nullptr && GetWorld() != nullptr)
              {
              	//Initializing the Start Location of the trace to the world location of the "Player".
              	const FVector TraceStart = MyPlayer->GetActorLocation();
              
              	//Initializing the End Location of the trace to the previously calculated 'SpawnLocation'.
              	const FVector TraceEnd = SpawnLocation;
              
              	//Inititalizing the Line Trace Parameters.
              	FCollisionQueryParams TraceParameters = FCollisionQueryParams(FName(TEXT("Trace Parameters")));
              	TraceParameters.bTraceComplex = false;
              	TraceParameters.bTraceAsyncScene = true;
              	TraceParameters.bReturnPhysicalMaterial = false;
              
              	//Initializing the Line Trace ignore list.
              	TArray<AActor*> TraceIgnoreList;
              	TraceIgnoreList.Add(MyPlayer);
              	TraceParameters.AddIgnoredActors(TraceIgnoreList);
              
              	//Initializing the "TraceHitResult".
              	FHitResult TraceHitResult(ForceInit);
              
              	//Performing the actual trace on the 'Visibility' channel.
              	GetWorld()->LineTraceSingleByChannel(TraceHitResult, TraceStart, TraceEnd, ECC_Visibility, TraceParameters);
              			
              	//If the trace was not a blocking hit.
              	if (TraceHitResult.bBlockingHit == false)
              	{
                           //There is nothing blocking the ray between the two locations, we can spawn out actor at "SpawnLocation".
                      }
              Thanks! Just wondering, how do I make the trace visible for debug purposes to ensure that it is actually working properly? Thanks again for your help.

              Comment


                #8
                If I remember correctly, you need a TraceTag to be set in the World and FCollisionQueryParams before the trace, something like this:
                Code:
                const FName TraceTag("TraceTag");
                GetWorld()->DebugDrawTraceTag = TraceTag;
                TraceParameters.TraceTag = TraceTag;
                I'm not sure if I remember this correctly, so you might want to double check it on google.

                Comment

                Working...
                X