虚幻4 ue4 学习笔记pwan篇 1.4 pawn结合UPawnMovementComponent类 移动组件实现 移动球体添加物理碰撞

时间:2022-04-04 20:34:25

MyPawn.h部分

 1 // Fill out your copyright notice in the Description page of Project Settings.
2
3 #pragma once
4
5 #include "CoreMinimal.h"
6 #include "GameFramework/Pawn.h"
7 #include "MyPawn.generated.h"
8 UCLASS()
9 class TEST4_API AMyPawn : public APawn
10 {
11 GENERATED_BODY()
12
13 public:
14 // Sets default values for this pawn's properties
15 AMyPawn();
16
17 protected:
18 // Called when the game starts or when spawned
19 virtual void BeginPlay() override;
20
21 public:
22 // Called every frame
23 virtual void Tick(float DeltaTime) override;
24
25 // Called to bind functionality to input
26 virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
27 void fire();
28 void MoveForward(float AxisValue);
29 void MoveRight(float AxisValue);
30
31 class UMyPawnMovementComponent* OurMovementComponent;
32
33 virtual UPawnMovementComponent* GetMovementComponent() const override;
34 /*
35 1.引入同一项目类请加入 class
36 2.如果补加入头文件 只能引入同一项目引用 而不能确定继承关系
37
38 */
39 UParticleSystemComponent* OurParticleSystem;
40 private:
41 int32 coutFire = 0;//计数器 禁止外部对象和子对象访问
42 float RunningTime = 0.0f;
43
44 };

MyPawn.cpp部分

  1 // Fill out your copyright notice in the Description page of Project Settings.
2
3 #include "MyPawn.h"
4 #include "Runtime/Engine/Classes/Components/BoxComponent.h"
5 #include "Runtime/Engine/Classes/Components/SphereComponent.h"// USphereComponent 引用
6 #include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h" // ConstructorHelpers 引用
7 #include "Runtime/Engine/Classes/Particles/ParticleSystemComponent.h"//UParticleSystemComponent 引用
8 #include "Runtime/Engine/Classes/GameFramework/SpringArmComponent.h"//UStaticMeshComponent 引用
9 #include "Runtime/Engine/Classes/Camera/CameraComponent.h"//UCameraComponent 引用
10 #include "MyPawnMovementComponent.h"
11 #include "string"
12 using namespace std;
13 // Sets default values
14 AMyPawn::AMyPawn()
15 {
16 // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
17 PrimaryActorTick.bCanEverTick = true;
18 AutoPossessPlayer = EAutoReceiveInput::Player0;//这行代码不加 无法实现用户操作 此时用户视角就是当前pawn视角
19
20 USphereComponent * SphereComponent = CreateDefaultSubobject<USphereComponent>("RootComponent");
21 RootComponent = SphereComponent;//这里不一定非要用物体组件
22
23
24
25 // 创建静态网格物体
26 UStaticMeshComponent * SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>("VisualRepresentation");
27 SphereVisual->SetupAttachment(RootComponent);
28 SphereComponent->InitSphereRadius(40.f);// 实际物理 碰撞半径
29 SphereComponent->SetCollisionProfileName(TEXT("Pawn"));//碰撞设置 设置这个方法才可以实现物理碰撞 这里的名称必须为Pawn
30 //SetCollisionProfileName需要删除之前虚幻4场景中的pawn物体然后再重新加入才能实现物理碰撞
31 FName sComProName = SphereComponent->GetCollisionProfileName();// 得到 碰撞设置的名称
32
33 //打开素材库
34 static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAssetWzh(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
35 if (SphereVisualAssetWzh.Succeeded()) {
36 SphereVisual->SetStaticMesh(SphereVisualAssetWzh.Object);
37 SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));//设置位置0,0,0为初始位置
38 SphereVisual->SetWorldScale3D(FVector(0.8f));//SetWorldScale3D 设置组件在世界空间中的变换倍数。 倍数以原来模型大小为基准
39 }
40
41 // 创建一个可启用或停用的粒子系统
42 OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
43 OurParticleSystem->SetupAttachment(RootComponent);//直接将粒子系统添加到根组件上
44 OurParticleSystem->bAutoActivate = false;//在场景中激活
45
46 OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
47 OurParticleSystem->SetWorldScale3D(FVector(3.0f));//SetWorldScale3D 设置组件在世界空间中的变换倍数。 倍数以原来模型大小为基准
48 static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
49 if (ParticleAsset.Succeeded())
50 {
51 OurParticleSystem->SetTemplate(ParticleAsset.Object);
52 }
53
54
55 //加入个摄像头让视角看起来舒服点 当然不加也是可以看到
56 UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
57 Camera->SetupAttachment(RootComponent);
58 Camera->SetRelativeLocation(FVector(-250.f, 0.0f, 400));//设置位置0,0,0为初始位置
59 Camera->RelativeRotation = FRotator(-45.f, 0.f, 0.f);// y z x顺序旋转 一个旋转信息的容器 所有旋转值都以度数存储。
60
61 // 创建移动组件的一个实例,并告知其更新根组件。
62 //<UMyPawnMovementComponent>为自定义移动组件类
63 OurMovementComponent = CreateDefaultSubobject<UMyPawnMovementComponent>(TEXT("CustomMovementComponent"));//创建自定义移动组件类 如果没有这行代码无法实现物理碰撞无法使用自定义移动类移动球体
64 OurMovementComponent->UpdatedComponent = RootComponent;//这行代码不加也可以
65
66 }
67
68 // Called when the game starts or when spawned
69 void AMyPawn::BeginPlay()
70 {
71 Super::BeginPlay();
72
73
74 }
75
76 // Called every frame
77 void AMyPawn::Tick(float DeltaTime)//没两帧之间的时间间隔
78 {
79 Super::Tick(DeltaTime);
80
81
82 }
83
84 // Called to bind functionality to input
85 void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
86 {
87 Super::SetupPlayerInputComponent(PlayerInputComponent);
88 PlayerInputComponent->BindAction("fire", IE_Released, this, &AMyPawn::fire);
89 InputComponent->BindAxis("MoveRight", this, &AMyPawn::MoveRight);
90 InputComponent->BindAxis("MoveForward", this, &AMyPawn::MoveForward);
91 }
92
93 UPawnMovementComponent* AMyPawn::GetMovementComponent() const//得到移动组件
94 {
95 return OurMovementComponent;
96 }
97
98 void AMyPawn::fire() {
99 coutFire = !coutFire;
100 if (GEngine)
101 {
102 GEngine->AddOnScreenDebugMessage(-1, 0.2, FColor::Red, TEXT("火焰!"));
103
104 int32 active32 = OurParticleSystem->bIsActive;
105 //OurParticleSystem->ToggleActive(); //官方使用的ToggleActive()切换粒子状态 我建议不要使用这个函数 因为
106 //在快速按下键盘按键 调用事件函数fire时 无法执行里面的ToggleActive函数 但是可以打印文字“火焰“ 但是慢慢按就没问题
107 //我发现主要是 ToggleActive内部操作 bIsActive的问题 如果快速按下 bIsActive 就不会重新赋值 而是一直为1估计是虚幻4官方的bug, 慢慢按 才为0 我自己重新 定义一个外部变量coutFire 计数代替bIsActive 就没问题了不用ToggleActive实现
108 OurParticleSystem->SetActive(coutFire);//通过计数器 切换状态
109 }
110
111 }
112
113 void AMyPawn::MoveForward(float AxisValue)//移动前进
114 {
115
116
117 if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
118 {
119 if (GEngine)
120 {
121 // TEXT只能接受字符串常量
122
123 FVector xyz1 = GetActorForwardVector();
124 string str = to_string(xyz1.X) + " , " + to_string(xyz1.Y) + " , " + to_string(xyz1.Z) + " AxisValue = " + to_string(AxisValue);
125 FString fstr = FString(str.c_str());
126 //按下s键AxisValue为-1 w键AxisValue为1
127 GEngine->AddOnScreenDebugMessage(-1, 0.5, FColor::Yellow, fstr);
128 }
129
130 //AddInputVector 设置每次移动的方向和距离 输入值 0.0 - 1.0之前
131
132 //GetActorForwardVector()得到当前视角永远向前的值 通过计算sin和鼠标转动的大小实现 就算视角变换也永远向前
133 //x大小就是当前sin大小 默认是1/2π 90度等于1 取值范围-1 -- 1, y z永远为0
134
135 //AxisValue ue4里按键绑定的值 设置输入的向量值移动的大小
136
137 OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue);//AxisValue ue4里按键绑定的值 设置输入的向量值移动的大小 不按下时为0
138
139 if (GEngine)
140 {
141 // TEXT只能接受字符串常量
142 FVector xyz2 = OurMovementComponent->GetInputVector();//注意这里不是 GetActorForwardVector()
143
144 string str2 = to_string(xyz2.X) + " , " + to_string(xyz2.Y) + " , " + to_string(xyz2.Z) + " AxisValue = " + to_string(AxisValue) + " Speed = " + to_string(OurMovementComponent->GetMaxSpeed());
145 FString fstr2 = FString(str2.c_str());
146 GEngine->AddOnScreenDebugMessage(-1, 0.5, FColor::Red, fstr2);
147
148 }
149
150 }
151 }
152
153 void AMyPawn::MoveRight(float AxisValue)//移动向右
154 {
155 if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
156 {
157 OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue);
158 }
159 }

 

MyPawnMovementComponent.h部分

 1 // Fill out your copyright notice in the Description page of Project Settings.
2
3 #pragma once
4
5 #include "CoreMinimal.h"
6 #include "GameFramework/PawnMovementComponent.h"
7 #include "MyPawnMovementComponent.generated.h"
8
9 /**
10 *
11 */
12 UCLASS()
13 class TEST4_API UMyPawnMovementComponent : public UPawnMovementComponent
14 {
15 GENERATED_BODY()
16
17 public:
18 virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
19
20
21
22 };

 

MyPawnMovementComponent.cpp部分

 1 // Fill out your copyright notice in the Description page of Project Settings.
2
3 #include "MyPawnMovementComponent.h"
4 void UMyPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
5 {
6 Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
7
8 // 确保所有内容仍然有效,并允许移动。
9 if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
10 {
11 return;
12 }
13
14 // 获取(然后清除)在 ACollidingPawn::Tick 设置的移动矢量。
15 FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f;
16 if (!DesiredMovementThisFrame.IsNearlyZero())
17 {
18 FHitResult Hit;
19 SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);
20
21 // 如碰到物体,尝试沿其滑动
22 if (Hit.IsValidBlockingHit())
23 {
24 SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);
25 }
26 }
27 };