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"

OnComponentHit returns bad values from GetTransform().GetLocation()?

Dear Epic,

I'm noticing some strange output from GetTransform() when calling it during OnComponentHit.

Setup

I'm running some checks to see if my character can climb surfaces during the collisions. During these checks I'm trying to use FVectors relating to my actor's location in the world.

I cannot use GetActorLocation() because I need to use an FTransform so I can use TransformPosition() and get trace and sweep locations relative to my actor's current facing direction and location.

However I'm getting bad values from GetTransform().GetLocation().

Code

The Capsule is 96uu

I'm using the absolute basic third person c++ code template. Only things changed are:

AWorkshopCharacter.h

 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 #pragma once
 
 #include "GameFramework/SpringArmComponent.h"
 #include "WorkshopCharacter.generated.h"
 
 UCLASS(config=Game)
 class AWorkshopCharacter : public ACharacter
 {
     GENERATED_UCLASS_BODY()
 
     /** Camera boom positioning the camera behind the character */
     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
     TSubobjectPtr<class USpringArmComponent> CameraBoom;
 
     /** Follow camera */
     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
     TSubobjectPtr<class UCameraComponent> FollowCamera;
 
     /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
     float BaseTurnRate;
 
     /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
     float BaseLookUpRate;
 
     /** Called when touching an object */
     UFUNCTION()
     void OnHit(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
 
 protected:
 
     /** Called for forwards/backward input */
     void MoveForward(float Value);
 
     /** Called for side to side input */
     void MoveRight(float Value);
 
     /** 
      * Called via input to turn at a given rate. 
      * @param Rate    This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
      */
     void TurnAtRate(float Rate);
 
     /**
      * Called via input to turn look up/down at a given rate. 
      * @param Rate    This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
      */
     void LookUpAtRate(float Rate);
 
     /** Handler for when a touch input begins. */
     void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);
 
 protected:
     // APawn interface
     virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;
     // End of APawn interface
 };
 

AWorkshopCharacter.cpp

 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 
 #include "Workshop.h"
 #include "WorkshopCharacter.h"
 
 //////////////////////////////////////////////////////////////////////////
 // AWorkshopCharacter
 
 AWorkshopCharacter::AWorkshopCharacter(const class FPostConstructInitializeProperties& PCIP)
     : Super(PCIP)
 {
     // Set size for collision capsule
     CapsuleComponent->InitCapsuleSize(42.f, 96.0f);
     CapsuleComponent->OnComponentHit.AddDynamic(this, &AWorkshopCharacter::OnHit);
 
     // set our turn rates for input
     BaseTurnRate = 45.f;
     BaseLookUpRate = 45.f;
 
     // Don't rotate when the controller rotates. Let that just affect the camera.
     bUseControllerRotationPitch = false;
     bUseControllerRotationYaw = false;
     bUseControllerRotationRoll = false;
 
     // Configure character movement
     CharacterMovement->bOrientRotationToMovement = true; // Character moves in the direction of input...    
     CharacterMovement->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate
     CharacterMovement->JumpZVelocity = 600.f;
     CharacterMovement->AirControl = 0.2f;
 
     // Create a camera boom (pulls in towards the player if there is a collision)
     CameraBoom = PCIP.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
     CameraBoom->AttachTo(RootComponent);
     CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character    
     CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller
 
     // Create a follow camera
     FollowCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FollowCamera"));
     FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
     FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm
 
     // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
     // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)
 }
 
 //////////////////////////////////////////////////////////////////////////
 // Hit
 
 void AWorkshopCharacter::OnHit(AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
 {
     GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Yellow, GetTransform().GetLocation().ToString());
 }
 
 //////////////////////////////////////////////////////////////////////////
 // Input
 
 void AWorkshopCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
 {
     // Set up gameplay key bindings
     check(InputComponent);
     InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
 
     InputComponent->BindAxis("MoveForward", this, &AWorkshopCharacter::MoveForward);
     InputComponent->BindAxis("MoveRight", this, &AWorkshopCharacter::MoveRight);
 
     // We have 2 versions of the rotation bindings to handle different kinds of devices differently
     // "turn" handles devices that provide an absolute delta, such as a mouse.
     // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
     InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
     InputComponent->BindAxis("TurnRate", this, &AWorkshopCharacter::TurnAtRate);
     InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
     InputComponent->BindAxis("LookUpRate", this, &AWorkshopCharacter::LookUpAtRate);
 
     // handle touch devices
     InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AWorkshopCharacter::TouchStarted);
 }
 
 
 void AWorkshopCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
 {
     // jump, but only on the first touch
     if (FingerIndex == ETouchIndex::Touch1)
     {
         Jump();
     }
 }
 
 void AWorkshopCharacter::TurnAtRate(float Rate)
 {
     // calculate delta for this frame from the rate information
     AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
 }
 
 void AWorkshopCharacter::LookUpAtRate(float Rate)
 {
     // calculate delta for this frame from the rate information
     AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
 }
 
 void AWorkshopCharacter::MoveForward(float Value)
 {
     if ((Controller != NULL) && (Value != 0.0f))
     {
         // find out which way is forward
         const FRotator Rotation = Controller->GetControlRotation();
         const FRotator YawRotation(0, Rotation.Yaw, 0);
 
         // get forward vector
         const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
         AddMovementInput(Direction, Value);
     }
 }
 
 void AWorkshopCharacter::MoveRight(float Value)
 {
     if ( (Controller != NULL) && (Value != 0.0f) )
     {
         // find out which way is right
         const FRotator Rotation = Controller->GetControlRotation();
         const FRotator YawRotation(0, Rotation.Yaw, 0);
     
         // get right vector 
         const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
         // add movement in that direction
         AddMovementInput(Direction, Value);
     }
 }
 


Results

And my results are:

Here we see the results of the above test. I'm getting two different Z values. (Note: 223.150 is the correct Z location) alt text

And here we see the same identical code running in a Tick Override, but here I seem to be getting consistent accurate results.

alt text

Anomalies

When using GetActorLocation() in my OnHit function I get consistent Z location results. But I cannot use TransformPosition from an FVector.

I even attempted to create a new FTransform and set the Translation component by:

 FTransform( GetActorLocation() )

And I still get the same strange offset results.

Product Version: Not Selected
Tags:
outputtick.jpg (138.0 kB)
debug.jpg (373.8 kB)
more ▼

asked Apr 01 '14 at 09:05 AM in Bug Reports

avatar image

Mercurial Forge
99 13 17 18

(comments are locked)
10|2000 characters needed characters left

2 answers: sort voted first

Hey Oliver, thanks for bringing this up. This doesn't look like an actual bug, and I think this is what is happening:

  1. When you log the location in the tick event, that is correct because it's the location of the player at the moment of tick.

  2. When you log the location in the OnHit event, you are getting a couple of hit results during the same frame (your screenshot made it easier to diagnose, so thanks for that). When you are walking up against a wall, you collide with that wall (the first hit result you log, with the "correct" Z). Then we try to step up the surface, by sweeping the capsule up, forward, and down to see if we can step up onto or over the barrier. In this case, the capsule hits the wall in front of us and we fail to get on or over the barrier, so the attempt is canceled. However, you are getting an OnHit callback for this attempt, which is why you are seeing the higher Z location.

I reproduced this and debugged it with a similar setup so I'm pretty sure this is what is going on. GetTransform().GetLocation() should behave identical to GetActorLocation(). If you look at the source, GetTransform returns ComponentToWorld of the RootComponent (capsule in your case), and GetActorLocation() returns ComponentToWorld.GetLocation().

Hopefully this clarifies things for you! Let me know if you have further questions (and sorry for the delay, I was out sick for a while).

-Zak

more ▼

answered Apr 22 '14 at 07:20 PM

avatar image

LEGO_MANIAC STAFF
995 18 16 39

avatar image Mercurial Forge Apr 23 '14 at 05:53 PM

Thanks Zak, no problem about taking some time, I understand!

I guess my only unanswered questions would be. If I'm trying to use GetTransform().GetLocation() and I'm getting these oscillating results, it creates a strange and inaccurate Trace.

In otherwords, there may be instances where the trace is both true and false within the same frame or oscillating frames. This wouldn't be useful if I need the trace to return a constant true or false over a period of time in order to activate something like a ledge climb.

So would be it be best to set a bool true during the OnHit and run the traces from Tick? It sounds like this would be best way.

Thanks again for clearing this up.

avatar image LEGO_MANIAC STAFF Apr 23 '14 at 06:13 PM

It sounds like you might want to add a bool around StepUp so you know to ignore those hit results within your OnHit. But running the traces elsewhere might work as well.

(comments are locked)
10|2000 characters needed characters left

Hi Oliver,

I gave this one a try and couldn't seem to repro it. Could you send over the AWorkshopCharacter class that you're working on so we can see if we can reproduce it with that?

Maybe you have two different actors or components getting hit?

Someone here pointed out that the differences look like they might be the half height of the capsule, exactly how tall is your capsule?

more ▼

answered Apr 18 '14 at 06:26 PM

avatar image

User-1420270633 STAFF
943 27 26 58

avatar image Mercurial Forge Apr 18 '14 at 07:32 PM

I added the code and responses to the main question. You will see i'm simply hitting a default architecture piece "Wall_400x200" and getting the errors based on the code provided.

I hope it's something simple :(

(comments are locked)
10|2000 characters needed characters left
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