六一的部落格


关关难过关关过,前路漫漫亦灿灿。



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网格体

  1. 获取骨骼网格体所有下级Actor的可见组件
    1TArray<USceneComponent*> MeshChildren;
    2GetMesh()->GetChildrenComponents(true, MeshChildren);
  2. 遍历可见组件, 通过图元组件设置玩家是否可见
    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}

查看

  1. BP_STUPlayerCharacter可见摄像机碰撞组件


  2. 摄像机碰撞组件与游戏角色胶囊组件发生重叠时, 游戏角色骨骼网格体和下级网格体均不可被玩家看见


  3. 射击特效仍可见


修复弹簧臂组件发生碰撞时摄像机组件穿模


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网格体

  1. 获取骨骼网格体所有下级Actor的可见组件
    1TArray<USceneComponent*> MeshChildren;
    2GetMesh()->GetChildrenComponents(true, MeshChildren);
  2. 遍历可见组件, 通过图元组件设置玩家是否可见
    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}

查看

  1. BP_STUPlayerCharacter可见摄像机碰撞组件


  2. 摄像机碰撞组件与游戏角色胶囊组件发生重叠时, 游戏角色骨骼网格体和下级网格体均不可被玩家看见


  3. 射击特效仍可见