# HowTo_Components **Repository Path**: wblong/how-to_-components ## Basic Information - **Project Name**: HowTo_Components - **Description**: 学习利用组件将Pawn与物理交互、使用粒子效果等方法。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-08-01 - **Last Updated**: 2021-10-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: Cpp, UE4 ## README # 组件和碰撞 学习利用组件将Pawn与物理交互、使用粒子效果等方法。 ## 粒子系统组件 ```cpp UPROPERTY() class UParticleSystemComponent* OurParticleSystem; ``` 创建与物理场景交互的 球体组件、视觉显示碰撞形态的 静态网格体组件、可随意开关的粒子系统组件,及可用于附加 摄像机组件 控制游戏视角的 弹簧臂组件。 ```cpp #include "UObject/ConstructorHelpers.h" #include "Particles/ParticleSystemComponent.h" #include "Components/SphereComponent.h" #include "Camera/CameraComponent.h" #include "GameFramework/SpringArmComponent.h" // 根组件将成为对物理反应的球体 USphereComponent* SphereComponent = CreateDefaultSubobject(TEXT("RootComponent")); RootComponent = SphereComponent; SphereComponent->InitSphereRadius(40.0f); SphereComponent->SetCollisionProfileName(TEXT("Pawn")); // 创建并放置网格体组件,以便查看球体位置 UStaticMeshComponent* SphereVisual = CreateDefaultSubobject(TEXT("VisualRepresentation")); SphereVisual->SetupAttachment(RootComponent); static ConstructorHelpers::FObjectFinder SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere")); if (SphereVisualAsset.Succeeded()) { SphereVisual->SetStaticMesh(SphereVisualAsset.Object); SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f)); SphereVisual->SetWorldScale3D(FVector(0.8f)); } // 创建可激活或停止的粒子系统 OurParticleSystem = CreateDefaultSubobject(TEXT("MovementParticles")); OurParticleSystem->SetupAttachment(SphereVisual); OurParticleSystem->bAutoActivate = false; OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f)); static ConstructorHelpers::FObjectFinder ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire")); if (ParticleAsset.Succeeded()) { OurParticleSystem->SetTemplate(ParticleAsset.Object); } // 使用弹簧臂给予摄像机平滑自然的运动感。 USpringArmComponent* SpringArm = CreateDefaultSubobject(TEXT("CameraAttachmentArm")); SpringArm->SetupAttachment(RootComponent); SpringArm->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f)); SpringArm->TargetArmLength = 400.0f; SpringArm->bEnableCameraLag = true; SpringArm->CameraLagSpeed = 3.0f; // 创建摄像机并附加到弹簧臂 UCameraComponent* Camera = CreateDefaultSubobject(TEXT("ActualCamera")); Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName); // 控制默认玩家 AutoPossessPlayer = EAutoReceiveInput::Player0; ``` ## 移动组件 `UCollidingPawnMovementComponent : public UPawnMovementComponent` ```cpp void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); // 确保所有事物持续有效,以便进行移动。 if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime)) { return; } // 获取(然后清除)ACollidingPawn::Tick中设置的移动向量 FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f; if (!DesiredMovementThisFrame.IsNearlyZero()) { FHitResult Hit; SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit); // 若发生碰撞,尝试滑过去 if (Hit.IsValidBlockingHit()) { SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit); } } }; ``` ## 使用Pawn和组件 ```cpp UPROPERTY() class UCollidingPawnMovementComponent* OurMovementComponent; // 创建移动组件的实例,并要求其更新根。 OurMovementComponent = CreateDefaultSubobject(TEXT("CustomMovementComponent")); OurMovementComponent->UpdatedComponent = RootComponent; UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const { return OurMovementComponent; } ``` 处理Pawn会接收的输入。 ```cpp void MoveForward(float AxisValue); void MoveRight(float AxisValue); void Turn(float AxisValue); void ParticleToggle(); ``` ```cpp void ACollidingPawn::MoveForward(float AxisValue) { if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent)) { OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue); } } void ACollidingPawn::MoveRight(float AxisValue) { if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent)) { OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue); } } void ACollidingPawn::Turn(float AxisValue) { FRotator NewRotation = GetActorRotation(); NewRotation.Yaw += AxisValue; SetActorRotation(NewRotation); } void ACollidingPawn::ParticleToggle() { if (OurParticleSystem && OurParticleSystem->Template) { OurParticleSystem->ToggleActive(); } } InInputComponent->BindAction("ParticleToggle", IE_Pressed, this, &ACollidingPawn::ParticleToggle); InInputComponent->BindAxis("MoveForward", this, &ACollidingPawn::MoveForward); InInputComponent->BindAxis("MoveRight", this, &ACollidingPawn::MoveRight); InInputComponent->BindAxis("Turn", this, &ACollidingPawn::Turn); ``` ## Result ![1 how to component](./Images/how_to_components.png) ![1 how to component](./Images/how_to_component1.png) ## Reference 1. [组件和碰撞-https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/Components/](https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/Components/)