修复弹簧臂组件发生碰撞时摄像机组件穿模
2023年11月22日 2024年1月11日
Camera Inside Character Fix
说明
当游戏角色与物体较近时, 弹簧臂组件可能与物体发生碰撞, 此时, 摄像机组件会与游戏角色胶囊组件重叠, 进入到游戏角色骨骼网格体
摄像机组件与游戏角色胶囊组件重叠时, 本节会设置骨骼网格体玩家不可见, 网格体下级所有Actor的网格体亦玩家不可见
API导航
游戏角色
获取胶囊组件
1/** Returns CapsuleComponent subobject **/ 2FORCEINLINE class UCapsuleComponent* GetCapsuleComponent() const { return CapsuleComponent; }
获取骨骼网格体组件
1/** Returns Mesh subobject **/ 2FORCEINLINE class USkeletalMeshComponent* GetMesh() const { return Mesh; }
可见组件
USceneComponent
获取下级Actor的可见组件
bIncludeAllDescendants | |
---|---|
true | 获取所有下级可见组件 |
false | 获取直接下级可见组件 |
1/** 2 * Gets all components that are attached to this component, possibly recursively 3 * @param bIncludeAllDescendants Whether to include all descendants in the list of children (i.e. grandchildren, great grandchildren, etc.) 4 * @param Children The list of attached child components 5 */ 6UFUNCTION(BlueprintCallable, Category="Components") 7void GetChildrenComponents(bool bIncludeAllDescendants, TArray<USceneComponent*>& Children) const;
图元组件
UPrimitiveComponent
提供两种委托: 在发生重叠事件, 和重叠事件结束时通知客户端
1/** Delegate for notification of start of overlap with a specific component */ 2DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams( FComponentBeginOverlapSignature, UPrimitiveComponent, OnComponentBeginOverlap, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult); 3/** Delegate for notification of end of overlap with a specific component */ 4DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_FourParams( FComponentEndOverlapSignature, UPrimitiveComponent, OnComponentEndOverlap, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex); 5 6/** 7 * Event called when something starts to overlaps this component, for example a player walking into a trigger. 8 * For events when objects have a blocking collision, for example a player hitting a wall, see 'Hit' events. 9 * 10 * @note Both this component and the other one must have GetGenerateOverlapEvents() set to true to generate overlap events. 11 * @note When receiving an overlap from another object's movement, the directions of 'Hit.Normal' and 'Hit.ImpactNormal' 12 * will be adjusted to indicate force from the other object against this object. 13 */ 14UPROPERTY(BlueprintAssignable, Category="Collision") 15FComponentBeginOverlapSignature OnComponentBeginOverlap; 16 17/** 18 * Event called when something stops overlapping this component 19 * @note Both this component and the other one must have GetGenerateOverlapEvents() set to true to generate overlap events. 20 */ 21UPROPERTY(BlueprintAssignable, Category="Collision") 22FComponentEndOverlapSignature OnComponentEndOverlap;
处理函数签名
1// OnComponentBeginOverlap 2void OnBeginOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult); 3 4// OnComponentEndOverlap 5void OnEndOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);
检查是否与其他组件发生重叠
1/** 2 * Check whether this component is overlapping another component. 3 * @param OtherComp Component to test this component against. 4 * @return Whether this component is overlapping another component. 5 */ 6UFUNCTION(BlueprintPure, Category="Collision", meta=(UnsafeDuringActorConstruction="true")) 7bool IsOverlappingComponent(const UPrimitiveComponent* OtherComp) const;
设置玩家可见
UPrimitiveComponent::SetOwnerNoSee
为摄像机组件添加球形碰撞
protected
ShootThemUp: Player/STUPlayerCharacter.h
1class USphereComponent; 2 3UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components") 4USphereComponent *CameraCollisionComponent;
设置碰撞响应重叠
ShootThemUp: Player/STUPlayerCharacter.cpp
1#include "Components/SphereComponent.h" 2 3// 构造函数 4CameraCollisionComponent = CreateDefaultSubobject<USphereComponent>("CameraCollisionComponent"); 5CameraCollisionComponent->SetSphereRadius(10.0f); 6CameraCollisionComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap); 7CameraCollisionComponent->SetupAttachment(CameraComponent);
检查球形组件是否与游戏角色胶囊组件发生碰撞, 作出相应处理
private
ShootThemUp: Player/STUPlayerCharacter.h
1void CheckCameraOverlap();
获取重叠信息
1const auto HideMesh = CameraCollisionComponent->IsOverlappingComponent(GetCapsuleComponent());
设置玩家是否可见骨骼网格体
1GetMesh()->SetOwnerNoSee(HideMesh);
设置玩家是否可见骨骼网格体下级Actor网格体
- 获取骨骼网格体所有下级Actor的可见组件
1TArray<USceneComponent*> MeshChildren; 2GetMesh()->GetChildrenComponents(true, MeshChildren);
- 遍历可见组件, 通过图元组件设置玩家是否可见
1for (auto SceneComponent : MeshChildren) 2{ 3 const auto PrimitiveComponent = Cast<UPrimitiveComponent>(SceneComponent); 4 if (PrimitiveComponent) 5 { 6 PrimitiveComponent->SetOwnerNoSee(HideMesh); 7 } 8}
完整实现
ShootThemUp: Player/STUPlayerCharacter.cpp
1#include "Components/CapsuleComponent.h" 2#include "Components/SkeletalMeshComponent.h" 3 4void ASTUPlayerCharacter::CheckCameraOverlap() 5{ 6 const auto HideMesh = CameraCollisionComponent->IsOverlappingComponent(GetCapsuleComponent()); 7 8 GetMesh()->SetOwnerNoSee(HideMesh); 9 10 TArray<USceneComponent*> MeshChildren; 11 GetMesh()->GetChildrenComponents(true, MeshChildren); 12 13 for (auto SceneComponent : MeshChildren) 14 { 15 const auto PrimitiveComponent = Cast<UPrimitiveComponent>(SceneComponent); 16 if (PrimitiveComponent) 17 { 18 PrimitiveComponent->SetOwnerNoSee(HideMesh); 19 } 20 } 21}
为摄像机碰撞组件注册重叠事件
ShootThemUp: Player/STUPlayerCharacter.h
1// protected 2virtual void BeginPlay() override; 3 4// private 5 6UFUNCTION() 7void OnCameraCollisionBeginOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult); 8 9UFUNCTION() 10void OnCameraCollisionEndOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);
ShootThemUp: Player/STUPlayerCharacter.cpp
1void ASTUPlayerCharacter::OnCameraCollisionBeginOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult) 2{ 3 CheckCameraOverlap(); 4} 5 6void ASTUPlayerCharacter::OnCameraCollisionEndOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex) 7{ 8 CheckCameraOverlap(); 9} 10 11void ASTUPlayerCharacter::BeginPlay() 12{ 13 Super::BeginPlay(); 14 check(CameraCollisionComponent); 15 16 CameraCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &ASTUPlayerCharacter::OnCameraCollisionBeginOverlap); 17 CameraCollisionComponent->OnComponentEndOverlap.AddDynamic(this, &ASTUPlayerCharacter::OnCameraCollisionEndOverlap); 18}
查看
-
BP_STUPlayerCharacter可见摄像机碰撞组件
-
摄像机碰撞组件与游戏角色胶囊组件发生重叠时, 游戏角色骨骼网格体和下级网格体均不可被玩家看见
-
射击特效仍可见