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

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 };

 

posted on 2017-12-26 23:43  王子殿下  阅读(3281)  评论(0编辑  收藏  举报

导航