UMovementComponent::TwoWallAdjust

本文介绍了一个虚拟环境中处理角色与两个墙面碰撞的算法。当角色在两个墙面之间移动时,通过计算调整移动方向来确保平滑的移动效果。该算法考虑了两墙面之间的夹角,并据此选择合适的移动方向。
void UCharacterMovementComponent::PhysFalling(float deltaTime, int32 Iterations)
{
		else if ( Hit.bBlockingHit )
		{	
			const FVector OldHitNormal = Hit.Normal;
				const FVector OldHitImpactNormal = Hit.ImpactNormal;				
				FVector Delta = ComputeSlideVector(Adjusted, 1.f - Hit.Time, OldHitNormal, Hit);
					// Move in deflected direction.
					SafeMoveUpdatedComponent( Delta, PawnRotation, true, Hit);
					
					if (Hit.bBlockingHit)
					{
						// hit second wall

						FVector PreTwoWallDelta = Delta;
						TwoWallAdjust(Delta, Hit, OldHitNormal);

在物理下落过程中,第一次碰撞后偏转移动过程,再次碰撞 hit seconde wall,调用TwoWallAdjust方法处理。

	/**
	 * Compute a movement direction when contacting two surfaces.
	 * @param Delta:		[In] Amount of move attempted before impact. [Out] Computed adjustment based on impacts.
	 * @param Hit:			Impact from last attempted move
	 * @param OldHitNormal:	Normal of impact before last attempted move
	 * @return Result in Delta that is the direction to move when contacting two surfaces.
	 */
	virtual void TwoWallAdjust(FVector &Delta, const FHitResult& Hit, const FVector &OldHitNormal) const;


void UMovementComponent::TwoWallAdjust(FVector& OutDelta, const FHitResult& Hit, const FVector& OldHitNormal) const
{
	FVector Delta = OutDelta;
	const FVector HitNormal = Hit.Normal;

	if ((OldHitNormal | HitNormal) <= 0.f) //90 or less corner, so use cross product for direction
	{
		const FVector DesiredDir = Delta;
		FVector NewDir = (HitNormal ^ OldHitNormal);
		NewDir = NewDir.GetSafeNormal();
		Delta = (Delta | NewDir) * (1.f - Hit.Time) * NewDir;
		if ((DesiredDir | Delta) < 0.f)
		{
			Delta = -1.f * Delta;
		}
	}
	else //adjust to new wall
	{
		const FVector DesiredDir = Delta;
		Delta = ComputeSlideVector(Delta, 1.f - Hit.Time, HitNormal, Hit);
		if ((Delta | DesiredDir) <= 0.f)
		{
			Delta = FVector::ZeroVector;
		}
		else if ( FMath::Abs((HitNormal | OldHitNormal) - 1.f) < KINDA_SMALL_NUMBER )
		{
			// we hit the same wall again even after adjusting to move along it the first time
			// nudge away from it (this can happen due to precision issues)
			Delta += HitNormal * 0.01f;
		}
	}

	OutDelta = Delta;
}

两个墙面夹角<=90°(等价于两个法向量夹角>=90°,二者点积 <= 0),判断两个法向量叉乘的方向(向量)是否可移动。

两个墙面夹角>90°(等价于两个法向量夹角<90°,二者点积 > 0),判断是否可向第二个墙面移动。


 

UE C++中,`GetCharacterMovement()` 和 `GetMovementComponent()` 都与角色的移动组件相关,但它们存在一些区别。 `GetCharacterMovement()` 是 `ACharacter` 类的一个成员函数,它专门用于获取角色的 `UCharacterMovementComponent` 类型的移动组件。`UCharacterMovementComponent` 是一个专门为角色设计的移动组件,提供了一系列角色移动相关的功能,如行走、跑步、跳跃、蹲伏等。以下是使用 `GetCharacterMovement()` 的示例代码: ```cpp #include "GameFramework/CharacterMovementComponent.h" // 在角色类的某个函数中使用 void AYourCharacterClass::SomeFunction() { UCharacterMovementComponent* MovementComponent = GetCharacterMovement(); if (MovementComponent) { MovementComponent->MaxWalkSpeed = 600.0f; } } ``` `GetMovementComponent()` 是 `AActor` 类的一个成员函数,它返回的是一个更通用的 `UMovementComponent` 类型的移动组件。`UMovementComponent` 是一个基类,`UCharacterMovementComponent` 也是从它派生而来的。`GetMovementComponent()` 可以用于任何继承自 `AActor` 的类,而不仅仅是角色类。不过,由于它返回的是基类指针,在使用一些 `UCharacterMovementComponent` 特有的功能时,可能需要进行类型转换。以下是使用 `GetMovementComponent()` 的示例代码: ```cpp #include "Components/MovementComponent.h" #include "GameFramework/CharacterMovementComponent.h" // 在角色类的某个函数中使用 void AYourCharacterClass::SomeFunction() { UMovementComponent* MovementComponent = GetMovementComponent(); if (MovementComponent) { UCharacterMovementComponent* CharacterMovement = Cast<UCharacterMovementComponent>(MovementComponent); if (CharacterMovement) { CharacterMovement->MaxWalkSpeed = 600.0f; } } } ``` 综上所述,`GetCharacterMovement()` 是专门为角色类设计的,返回的是 `UCharacterMovementComponent` 类型的指针,可以直接使用角色移动相关的功能;而 `GetMovementComponent()` 是一个更通用的函数,返回的是 `UMovementComponent` 类型的指针,在用于角色类时可能需要进行类型转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值