Download

FHitResult passed to SafeMoveUpdatedComponent is not updated on bounce

Hi

I used the ProjectileMovementComponent to create my own. This component will allow me to swap velocity between two pawns. The only thing missing is decreasing the velocity when the pawn hits something. Basically, I’d like to multiply the velocity vector by a coefficient at every collision. Here’s my code:




#include "MyMovementComponent.h"

#include "GameFramework/PawnMovementComponent.h"

void UMyMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    if (ShouldSkipUpdate(DeltaTime))
    {
        return;
    }

    PendingForceThisUpdate = PendingForce;
    ClearPendingForce();

    const FVector OldVelocity = Velocity;
    const FVector MoveDelta = ComputeMoveDelta(OldVelocity, DeltaTime);
    const auto OldRotation = UpdatedComponent->GetComponentRotation();

    if (!MoveDelta.IsNearlyZero())
    {
        FHitResult Hit;
        SafeMoveUpdatedComponent( MoveDelta, OldRotation, bSweepCollision, Hit );

        // Check hit to conditionally reduce velocity
    }
}

void UMyMovementComponent::AddForce(FVector Force)
{
    PendingForce += Force;
}

void UMyMovementComponent::ClearPendingForce(bool bClearImmediateForce /* = false */)
{
    PendingForce = FVector::ZeroVector;
    if (bClearImmediateForce)
    {
        PendingForceThisUpdate = FVector::ZeroVector;
    }
}

FVector UMyMovementComponent::ComputeAcceleration(const FVector& InVelocity, float DeltaTime) const
{
    FVector Acceleration(FVector::ZeroVector);

    Acceleration.Z += GetGravityZ();

    Acceleration += PendingForceThisUpdate;

    return Acceleration;
}

float UMyMovementComponent::GetMaxSpeed() const
{
    return MaxSpeed;
}

FVector UMyMovementComponent::LimitVelocity(FVector NewVelocity) const
{
    const float CurrentMaxSpeed = GetMaxSpeed();
    if (CurrentMaxSpeed > 0.f)
    {
        NewVelocity = NewVelocity.GetClampedToMaxSize(CurrentMaxSpeed);
    }

    return ConstrainDirectionToPlane(NewVelocity);
}

FVector UMyMovementComponent::ComputeVelocity(FVector InitialVelocity, float DeltaTime) const
{
    const FVector Acceleration = ComputeAcceleration(InitialVelocity, DeltaTime);
    const FVector NewVelocity = InitialVelocity + (Acceleration * DeltaTime);

    return LimitVelocity(NewVelocity);
}

FVector UMyMovementComponent::ComputeMoveDelta(const FVector& InVelocity, float DeltaTime) const
{
    const FVector NewVelocity = ComputeVelocity(InVelocity, DeltaTime); 
    const FVector Delta = (InVelocity * DeltaTime) + (NewVelocity - InVelocity) * (0.5f * DeltaTime);
    return Delta;
}

void UMyMovementComponent::SetVelocity(FVector Velocity_)
{
    Velocity = Velocity_;
    UpdateComponentVelocity();
};



I’d like to avoid using collision hit events, is there a way to keep this in the movement components’ context?

In case anyone faces my problem in the future, you can override the following function to check if any penetration case was resolved:



ResolvePenetrationImpl(const FVector& Adjustment, const FHitResult& Hit, const FQuat& NewRotationQuat)