// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Pawn.h" #include "CollidingPawn.generated.h" //CollidingPawn.h UCLASS() class HOWTO_COMPONENTS_API ACollidingPawn : public APawn { GENERATED_BODY() public: // Sets default values for this pawn's properties ACollidingPawn(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; UPROPERTY() class UParticleSystemComponent* OurParticleSystem;//粒子系统 UPROPERTY() class UCollidingPawnMovementComponent* OurMovementComponent;//移动系统 virtual UPawnMovementComponent* GetMovementComponent() const override;//重写函数以便导入我们自己设置的input //移动函数 void MoveForward(float AxisValue); void MoveRight(float AxisValue); void Turn(float AxisValue); void ParticleToggle(); };
//CollidingPawn.cpp #include "CollidingPawn.h" #include "CollidingPawnMovementComponent.h" #include "Camera/CameraComponent.h" #include "Components/SphereComponent.h" #include "GameFramework/SpringArmComponent.h" #include "Particles/ParticleSystemComponent.h" // Sets default values ACollidingPawn::ACollidingPawn() { // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; USphereComponent* SphereComponent=CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));//创建球体 RootComponent=SphereComponent;//设置为根物体 SphereComponent->InitSphereRadius(40.0);//设置半径 //SphereComponent->SetCollisionProfileName(TEXT("Pawn")); UStaticMeshComponent* SphereVisual =CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation")); SphereVisual->SetupAttachment(RootComponent); static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere")); if(SphereVisualAsset.Succeeded())//找到球体,如果找到的话,设置其为静态网格体,设置位置以及缩放 { SphereVisual->SetStaticMesh(SphereVisualAsset.Object); SphereVisual->SetRelativeLocation(FVector(0,0,-40)); SphereVisual->SetWorldScale3D(FVector(0.8)); } OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles")); OurParticleSystem->SetupAttachment(SphereVisual); OurParticleSystem->bAutoActivate=false; OurParticleSystem->SetRelativeLocation(FVector(-20,0,-20)); static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire")); if(ParticleAsset.Succeeded()) { OurParticleSystem->SetTemplate(ParticleAsset.Object); } USpringArmComponent* SpringArm=CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm")); SpringArm->SetupAttachment(RootComponent); SpringArm->SetRelativeLocation(FVector(-40,0,0)); SpringArm->TargetArmLength=400;//弹簧臂长度 SpringArm->bEnableCameraLag=true;//是否平滑 SpringArm->CameraLagSpeed=3;//平滑速度 UCameraComponent* Camera=CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera")); Camera->SetupAttachment(SpringArm,USpringArmComponent::SocketName);//将新创建的摄像机设置在弹簧臂的插槽上 AutoPossessPlayer=EAutoReceiveInput::Player0;//设置默认控制玩家 OurMovementComponent=CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent")); OurMovementComponent->UpdatedComponent=RootComponent;//更新根组件 } UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const//重写方法 { return OurMovementComponent; } // Called when the game starts or when spawned void ACollidingPawn::BeginPlay() { Super::BeginPlay(); } // Called every frame void ACollidingPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); } // Called to bind functionality to input void ACollidingPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); //绑定按键 InputComponent->BindAction("ParticleToggle",IE_Pressed,this,&ACollidingPawn::ParticleToggle); InputComponent->BindAxis("MoveForward",this,&ACollidingPawn::MoveForward); InputComponent->BindAxis("MoveRight",this,&ACollidingPawn::MoveRight); InputComponent->BindAxis("Turn",this,&ACollidingPawn::Turn); } 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 ro=GetActorRotation(); ro.Yaw+=AxisValue; SetActorRotation(ro); } void ACollidingPawn::ParticleToggle() { if(OurParticleSystem&&OurParticleSystem->Template) { OurParticleSystem->ToggleActive(); } }
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/PawnMovementComponent.h" #include "CollidingPawnMovementComponent.generated.h" /** * CollidingPawnMoment.h */ UCLASS() class HOWTO_COMPONENTS_API UCollidingPawnMovementComponent : public UPawnMovementComponent { GENERATED_BODY() public: //重写tickcomponent方法 virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; };
//CollidingPawnMovement.cpp #include "CollidingPawnMovementComponent.h" void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if(!PawnOwner||!UpdatedComponent||ShouldSkipUpdate(DeltaTime))//如果不是玩家,不是更新组件,如果不能移动等 { return; } FVector DesiredMovementThisFrame =ConsumeInputVector().GetClampedToMaxSize(1.0)*DeltaTime*150; if(!DesiredMovementThisFrame.IsNearlyZero())//如果不接近0 { FHitResult hit; //更新移动组件 SafeMoveUpdatedComponent(DesiredMovementThisFrame,UpdatedComponent->GetComponentRotation(),true,hit); if(hit.IsValidBlockingHit())//如果碰撞了 { //划过去 SlideAlongSurface(DesiredMovementThisFrame,1-hit.Time,hit.Normal,hit); } } }