keywords: UE4, Collision, Simulate Physics, RigidBody

UProjectileMovementComponent相关

官方第一人称射击模版项目中,是在构造函数中就设置好了速度:

ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileComp"));
ProjectileMovement->UpdatedComponent = CollisionComp;
ProjectileMovement->InitialSpeed = 3000.f;
ProjectileMovement->MaxSpeed = 3000.f;
ProjectileMovement->bRotationFollowsVelocity = true;
ProjectileMovement->bShouldBounce = true;

两个问题:

  1. 如何停止移动;
  2. 如何在运行时期间修改速度;

问题1解决方法:
默认情况下,Actor spawn之后,就会受到 ProjectileMovement 影响立即移动,如何在 Spawn 之后马上停止移动:

ProjectileMovement->Deactivate();

问题2解决方法:
如何在 Spawn 之后修改 Speed,两种方式:

UProjectileMovementComponent->SetVelocityInLocalSpace(FVector NewVelocity);

或者

UProjectileMovementComponent->Velocity = NewVelocity;

Velocity计算方式:

Velocity = Velocity.GetSafeNormal() * InitialSpeed;
前者速度方向是相对于 UProjectileMovementComponent本地坐标系 的相对Rotation,后者速度方向是相对于世界坐标系的绝对Rotation。

注意:当使用 UProjectileMovementComponent 后,UPrimitiveComponent::SetSimulatePhysics() 启用物理会与 ProjectileMovement 冲突。如果要使用物理,那么只能去掉 UProjectileMovementComponent ,使用 Add Impulse 来代替。

参考:
Simulate Physics and Projectile Movement Component
https://answers.unrealengine.com/questions/736999/simulate-physics-and-projectile-movement-component.html

UProjectileMovementComponent处理平面滑动

bool UProjectileMovementComponent::HandleSliding(FHitResult& Hit, float& SubTickTimeRemaining)
模拟物理时StaticMesh和CollisionComponent冲突

记住:StaticMesh自带刚体(RigidBody),并能执行碰撞(Collision)相关逻辑。
比如新建一个 Actor,并在该 Actor 内部创建了一个 BoxComponent ,然后再创建一个 StaticMeshComponent 并 Attach 到 BoxComponent 上。
如果不模拟物理,那么没有问题,一旦模拟物理并执行 AddImpulse 时,就会出问题。

现象:
如果只对 StaticMeshComponent 执行击飞,那么 BoxComponent 会停在原地,如果对 BoxComponent 击飞: BoxComponent->BodyInstance.AddImpulse() ,那么 StaticMeshComponent 不会动。

解决办法:
直接使用 StaticMeshComponent Collision ,不用与 Col1isionComponent 附加。

如何处理发射刚体与角色刚体冲突

问题现象:
当角色的CollisionComponent半径较大时,此时想在角色面前发射(AddImpulse)一个Simulate PhysicsStaticMeshActor,但是当这个 Actor 刚发射之前,其刚体正好和角色的刚体相互影响,导致 Actor 没能按预定方向和速度运动。

三种解决办法:

  • 减小角色刚体半径,或者发射点放在刚体半径以外。或者将发射物的生成坐标放在角色胶囊体之外。
  • 通过自定义碰撞通道将两个Mesh的碰撞避开。
  • 使用UPrimitiveComponent::IgnoreActorWhenMoving()将胶囊体从子弹的碰撞检测中过滤掉。
不使用 MovementComponent 情况下设置 Gravity 大小

MovementComponent 有个属性Gravity Scale来设置重力大小。
假设一个 Actor 如果没有添加 MovementComponent ,只有一个 StaticMeshComponent ,此时 StaticMeshComponent 模拟物理时,其重力加速度较小,这种情况下有没办法设置重力加速度大小?方式如下:

StaticMeshComp->SetSimulatePhysics(true);
StaticMeshComp->AddImpulse(SpeedInWorld);

然后在 Tick 函数中每帧设置:

FVector Velocity = StaticMeshComp->GetPhysicsLinearVelocity();
Velocity.Z -= 100.f;
StaticMeshComp->SetPhysicsLinearVelocity(Velocity);

说明:GetPhysicsLinearVelocity 默认为0,这里修改成 -100.f 的重力下降速率,

禁用、开启物理
//禁用所有子组件的物理模拟(但是没有对应的开启物理的API)
AActor::DisableComponentsSimulatePhysics();

//禁用指定组件的物理模拟
GetCapsuleComponent()->SetSimulatePhysics(false);
GetMesh()->SetSimulatePhysics(false);
Ingore special Actor’s Collision when it moving
/**
 * Tells this component whether to ignore collision with all components of a specific Actor when this component is moved.
 * Components on the other Actor may also need to be told to do the same when they move.
 * Does not affect movement of this component when simulating physics.
 */
void UPrimitiveComponent::IgnoreActorWhenMoving(AActor* Actor, bool bShouldIgnore)
mesh scale 与物理

如果修改mesh (StaticMesh和SkeletalMesh)的Scale,则会影响刚体碰撞问题,比如,一个碎片在地面上微微飘到。
所以不建议修改资产的scale,且SpawnActor()接口中的Transform参数,如果修改Scale默认是不生效的,官方也不建议修改Scale。

收集资料

Using Async Collision Traces in Unreal Engine 4
https://medium.com/@bryan.corell/using-async-collision-traces-in-unreal-engine-4-2cc312c825f5

Inside Unreal Physics
http://www.recursiveblueprints.fun/inside-unreal-physics/

UE4 How to Connect Skeletal Mesh with object using Physics Constraints in Unreal Engine 4 Tutorial.
https://www.youtube.com/watch?v=uHV6VHzPqxM

The Art of PhysX
https://pdfs.semanticscholar.org/presentation/faec/14b559373222fa1f2150e3aaaaf6f20b3b2e.pdf