• 13c++呵呵老师【pawn移动组件与碰撞】


    Pawn移动组件拥有部分强大内置功能,以便使用常见物理功能,同时便于在大量Pawn类型间共享移动代码。使用组件分隔不同功能是上佳方法,可在项目增大、Pawn越加复杂时减少杂乱。

    创建一个pwan类型的类

     1.打开 CollidingPawn.h 添加粒子组件

    1. UPROPERTY()
    2. class UParticleSystemComponent* OurParticleSystem;

     2.打开cpp文件,首先引用要用到的头文件

    1. #include "UObject/ConstructorHelpers.h"
    2. #include "Particles/ParticleSystemComponent.h"
    3. #include "Components/SphereComponent.h"
    4. #include "Camera/CameraComponent.h"
    5. #include "GameFramework/SpringArmComponent.h"

    3.在构造函数中添加各种组件和控制权

    1. // 根组件将成为对物理反应的球体
    2. USphereComponent* SphereComponent = CreateDefaultSubobject(TEXT("RootComponent"));
    3. RootComponent = SphereComponent;
    4. SphereComponent->InitSphereRadius(40.0f);
    5. //设置碰撞预设
    6. SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
    7. // 创建并放置网格体组件,以便查看球体位置
    8. UStaticMeshComponent* SphereVisual = CreateDefaultSubobject(TEXT("VisualRepresentation"));
    9. SphereVisual->SetupAttachment(RootComponent);
    10. //从磁盘加载资源
    11. static ConstructorHelpers::FObjectFinder SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
    12. if (SphereVisualAsset.Succeeded())
    13. {
    14. SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
    15. SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
    16. SphereVisual->SetWorldScale3D(FVector(0.8f));
    17. }
    18. // 创建可激活或停止的粒子系统
    19. OurParticleSystem = CreateDefaultSubobject(TEXT("MovementParticles"));
    20. OurParticleSystem->SetupAttachment(SphereVisual);
    21. //false:一开始不显示效果(没有激活)
    22. OurParticleSystem->bAutoActivate = false;
    23. OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
    24. //从磁盘加载资源
    25. static ConstructorHelpers::FObjectFinder
    26. ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
    27. if (ParticleAsset.Succeeded())
    28. {
    29. OurParticleSystem->SetTemplate(ParticleAsset.Object);
    30. }
    31. // 使用弹簧臂给予摄像机平滑自然的运动感。
    32. USpringArmComponent* SpringArm = CreateDefaultSubobject(TEXT("CameraAttachmentArm"));
    33. SpringArm->SetupAttachment(RootComponent);
    34. SpringArm->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f));
    35. SpringArm->TargetArmLength = 400.0f;
    36. SpringArm->bEnableCameraLag = true;
    37. SpringArm->CameraLagSpeed = 3.0f;
    38. // 创建摄像机并附加到弹簧臂
    39. UCameraComponent* Camera = CreateDefaultSubobject(TEXT("ActualCamera"));
    40. //将相机放在弹簧臂的插槽
    41. Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
    42. // 控制默认玩家
    43. AutoPossessPlayer = EAutoReceiveInput::Player0;

    ========================================================

    配置输入和创建Pawn移动组件

    1.配置操作映射和轴映射

     

    ========================================

    创建 移动组件 管理移动

    1.创建 移动组件 管理移动,而非直接在Pawn类中处理所有移动。本教程中将扩展 Pawn移动组件 类。

    2.与Pawn类不同的,Pawn移动组件类默认为不可见。要找到该组件,需选中 显示所有类(Show All Classes) 选项

     3.在搜索栏中输入"movement",以便快速缩小列表范围。

     4.由于已将Pawn类命名为 CollidingPawn,则将该类命为 CollidingPawnMovementComponent

    ===================================================

    为Pawn移动组件的行为编写代码

    底层逻辑:用movement组件来更新根组件

    1.为自定义Pawn移动组件编写代码。只需编写 TickComponent 函数(类似Actor的 Tick 函数)告知逐帧移动方式。在 CollidingPawnMovementComponent.h 中,需在类定义中覆盖 TickComponent

    1. public:
    2. //override就是可重写的意思
    3. virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;

     2.在 CollidingPawnMovementComponent.cpp 中定义此函数:

    1. void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
    2. {
    3. Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
    4. // 确保所有事物持续有效,以便进行移动。
    5. if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
    6. {
    7. return;
    8. }
    9. // 获取(然后清除)ACollidingPawn::Tick中设置的移动向量
    10. FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f;
    11. if (!DesiredMovementThisFrame.IsNearlyZero())
    12. {
    13. FHitResult Hit;
    14. SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);
    15. // 若发生碰撞,尝试滑过去
    16. if (Hit.IsValidBlockingHit())
    17. {
    18. SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);
    19. }
    20. }
    21. };

    ===============================================

    同时使用Pawn和组件

    1.要使用自定义 Pawn移动组件,首先需将变量添加到 Pawn 类进行追踪

    1. UPROPERTY()
    2. class UCollidingPawnMovementComponent* OurMovementComponent;

    2.在cpp中引入头文件

    #include "CollidingPawnMovementComponent.h"

     3.在构造函数中创建移动组件,并且设置组件更新根组件

    1. // 创建移动组件的实例,并要求其更新根。
    2. OurMovementComponent = CreateDefaultSubobject(TEXT("CustomMovementComponent"));
    3. OurMovementComponent->UpdatedComponent = RootComponent;

    4.Pawn拥有名为 GetMovementComponent 的函数,用于提供引擎中其他类访问该Pawn当前所用Pawn移动组件的权限。需覆盖该函数,使其返回自定义Pawn移动组件

    在 CollidingPawn.h 中的类定义中,需添加:

    virtual UPawnMovementComponent* GetMovementComponent() const override;

     5.而在 CollidingPawn.cpp 中,需按以下所示,添加覆盖函数的定义:

    1. UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const
    2. {
    3. return OurMovementComponent;
    4. }

    6.创建代码处理Pawn会接收的输入。首先在 CollidingPawn.h 中的类定义内声明以下函数:

    1. void MoveForward(float AxisValue);
    2. void MoveRight(float AxisValue);
    3. void Turn(float AxisValue);
    4. void ParticleToggle();

     7.在 CollidingPawn.cpp 中,按以下所示,添加此类函数的定义:

    1. void ACollidingPawn::MoveForward(float AxisValue)
    2. {
    3. if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
    4. {
    5. OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue);
    6. }
    7. }
    8. void ACollidingPawn::MoveRight(float AxisValue)
    9. {
    10. if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
    11. {
    12. OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue);
    13. }
    14. }
    15. void ACollidingPawn::Turn(float AxisValue)
    16. {
    17. FRotator NewRotation = GetActorRotation();
    18. NewRotation.Yaw += AxisValue;
    19. SetActorRotation(NewRotation);
    20. }
    21. void ACollidingPawn::ParticleToggle()
    22. {
    23. if (OurParticleSystem && OurParticleSystem->Template)
    24. {
    25. OurParticleSystem->ToggleActive();
    26. }
    27. }

    8.现在只需将函数绑定到输入事件。将下列代码添加到 ACollidingPawn::SetupPlayerInputComponent: 

    1. void ACollidingPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    2. {
    3. Super::SetupPlayerInputComponent(PlayerInputComponent);
    4. PlayerInputComponent->BindAction("ParticleToggle", IE_Pressed, this, &ACollidingPawn::ParticleToggle);
    5. PlayerInputComponent->BindAxis("MoveForward", this, &ACollidingPawn::MoveForward);
    6. PlayerInputComponent->BindAxis("MoveRight", this, &ACollidingPawn::MoveRight);
    7. PlayerInputComponent->BindAxis("Turn", this, &ACollidingPawn::Turn);
    8. }
  • 相关阅读:
    安卓逆向 - EdXposed LSPosed VirtualXposed
    【三剑客+JSP+Mysql+Tomcat】从前到后搭建简易编程导航小网站(期末作业)
    最真实的大数据SQL面试题(二)
    ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
    Java语言实现猜数字小游戏
    基于Session的认证与授权实践
    Flutter中的“迷你计算器”带有源代码
    深入理解计算机网络-4信号编码与调制4
    AURIX TC3XX内存映射分析
    土豆网鼠标经过显示遮罩---pink老师课程案例
  • 原文地址:https://blog.csdn.net/zhang2362167998/article/details/126675246