• ue4 1官网编程指南总结


    https://docs.unrealengine.com/latest/CHN/index.html

    中编程指南


    快速入门 actor生命周期

    FloatingActor.h

    #pragma once
    #include "GameFramework/Actor.h"
    #include "FloatingActor.generated.h"
    UCLASS()
    class QUICKSTART_API AFloatingActor : public AActor
    {
        GENERATED_BODY()
    public: 
        // 设置此actor属性的默认值
        AFloatingActor();
        virtual void BeginPlay() override;
        virtual void Tick( float DeltaSeconds ) override;
        float RunningTime;
    };

    FloatingActor.cpp

    #include "QuickStart.h"
    #include "FloatingActor.h"
    
    // 设置默认值
    AFloatingActor::AFloatingActor()
    {
        // 将此actor设置为在每一帧都调用Tick()。  如果您不需要这项功能,您可以关闭它以改善性能。
        PrimaryActorTick.bCanEverTick = true;
    }
    
    // 当游戏开始或生成时调用
    void AFloatingActor::BeginPlay()
    {
        Super::BeginPlay();
    }
    
    // 在每一帧调用
    void AFloatingActor::Tick( float DeltaTime )
    {
        Super::Tick( DeltaTime );
    
        FVector NewLocation = GetActorLocation();
        float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
        NewLocation.Z += DeltaHeight * 20.0f;      //把高度以20的系数进行缩放
        RunningTime += DeltaTime;
        SetActorLocation(NewLocation);
    }


    获取设置本地位置

    1 GetActorLocation(),SetActorLocation(FVector v)


    数学函数库

    2 FMath


    3 UCLASS() - 告知虚幻引擎生成类的反射数据。类必须派生自 UObject。
    USTRUCT() - 告知虚幻引擎生成结构体的反射数据。
    GENERATED_BODY() - UE4 使用它替代为类型生成的所有必需样板文件代码。
    UPROPERTY() - 使 UCLASS 或 USTRUCT 的成员变量可用作 UPROPERTY。UPROPERTY 用途广泛。它允许变量被复制、被序列化,并可从蓝图中进行访问。垃圾回收器还使用它们来追踪对 UObject 的引用数。

    UFUNCTION() - 使 UCLASS 或 USTRUCT 的类方法可用作 UFUNCTION。UFUNCTION 允许类方法从蓝图中被调用,并在其他资源中用作 RPC。



    玩家输入与Pawns

    MyPawn.h
    #pragma once
    
    #include "GameFramework/Pawn.h"
    #include "MyPawn.generated.h"
    
    UCLASS()
    class HOWTO_PLAYERINPUT_API AMyPawn : public APawn
    {
        GENERATED_BODY()
    public:
        // 设置默认值
        AMyPawn();
        // 当游戏开始或生成时调用
        virtual void BeginPlay() override;
        // 在每一帧调用
        virtual void Tick(float DeltaSeconds) override;
        // 调用以绑定功能到输入
        virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;//  nafio info 这个是override的
        UPROPERTY(EditAnywhere)
        USceneComponent* OurVisibleComponent;
        // 输入函数
        void Move_XAxis(float AxisValue);
        void Move_YAxis(float AxisValue);
        void StartGrowing();
        void StopGrowing();
        //输入变量
        FVector CurrentVelocity;
        bool bGrowing;
    };
    
    

    MyPawn.cpp
    #include "HowTo_PlayerInput.h"
    #include "MyPawn.h"
    
    // 设置默认值
    AMyPawn::AMyPawn()
    {
        // 将此pawn设置为在每一帧都调用Tick()。  如果您不需要这项功能,您可以关闭它以改善性能。
        PrimaryActorTick.bCanEverTick = true;
    
        // 将此pawn设置为由最低数量的玩家进行控制
        AutoPossessPlayer = EAutoReceiveInput::Player0;
    
        // 创建一个可供添加对象的空根组件。
        RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
        // 创建相机和可见项目
        UCameraComponent* OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));
        OurVisibleComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("OurVisibleComponent"));
        // 附加相机和可见对象到根组件。 偏移并旋转相机。
        OurCamera->AttachTo(RootComponent);
        OurCamera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f));
        OurCamera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
        OurVisibleComponent->AttachTo(RootComponent);
    }
    
    // 当游戏开始或生成时调用
    void AMyPawn::BeginPlay()
    {
        Super::BeginPlay();
    
    }
    
    // 在每一帧调用
    void AMyPawn::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    
        // 基于"Grow"操作来处理增长和收缩
        {
            float CurrentScale = OurVisibleComponent->GetComponentScale().X;
            if (bGrowing)
            {
                //  在一秒的时间内增长到两倍的大小
                CurrentScale += DeltaTime;
            }
            else
            {
                // 随着增长收缩到一半
                CurrentScale -= (DeltaTime * 0.5f);
            }
            // 确认永不低于起始大小,或增大之前的两倍大小。
            CurrentScale = FMath::Clamp(CurrentScale, 1.0f, 2.0f);
            OurVisibleComponent->SetWorldScale3D(FVector(CurrentScale));
        }
    
        // 基于"MoveX"和 "MoveY"坐标轴来处理移动
        {
            if (!CurrentVelocity.IsZero())
            {
                FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
                SetActorLocation(NewLocation);
            }
        }
    }
    
    // 调用以绑定功能到输入
    void AMyPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
    {
        Super::SetupPlayerInputComponent(InputComponent);
    
        // 在按下或松开"Grow"键时进行响应。
        InputComponent->BindAction("Grow", IE_Pressed, this, &AMyPawn::StartGrowing);
        InputComponent->BindAction("Grow", IE_Released, this, &AMyPawn::StopGrowing);
    
        // 在每一帧都对两个移动坐标轴的值进行响应,它们分别是"MoveX"和"MoveY"。
        InputComponent->BindAxis("MoveX", this, &AMyPawn::Move_XAxis);
        InputComponent->BindAxis("MoveY", this, &AMyPawn::Move_YAxis);
    }
    
    void AMyPawn::Move_XAxis(float AxisValue)
    {
        // 以每秒100单位的速度向前或向后移动
        CurrentVelocity.X = FMath::Clamp(AxisValue, -1.0f, 1.0f) * 100.0f;
    }
    
    void AMyPawn::Move_YAxis(float AxisValue)
    {
        // 以每秒100单位的速度向右或向左移动
        CurrentVelocity.Y = FMath::Clamp(AxisValue, -1.0f, 1.0f) * 100.0f;
    }
    
    void AMyPawn::StartGrowing()
    {
        bGrowing = true;
    }
    
    void AMyPawn::StopGrowing()
    {
        bGrowing = false;
    }


    1 SetupPlayerInputCompnent复写了pawn的方法,用于注册输入

    actor->pawn(加了接收输入信息方法)->character(加了走动)

    输入绑定略...


    2 AutoPossessPlayer = EAutoReceiveInput::Player0;

    这句翻译应该有问题,应该是由player0输入来控制当前这个pawn


    3 DeltaTime一次循环时间间隔


    游戏控制相机

    //Find the actor that handles control for the local player.
    APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
    OurPlayerController->GetViewTarget();//获取当前Controller相机
    OurPlayerController->SetViewTarget(CameraOne);//直接切换到相机1
    OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);//平滑切换到相机2

    获取controller原型
    static APlayerController * GetPlayerController
    (
        const UObject * WorldContextObject,
        int32 PlayerIndex
    )
    Returns the player controller at the specified player index
    第一个UObject类型参数这里传的是actor获取的就是这个actor的第index个controller


    变量,定时器和事件

    Countdown.h
    #pragma once
    
    #include "GameFramework/Actor.h"
    #include "Countdown.generated.h"
    
    UCLASS()
    class HOWTO_VTE_API ACountdown : public AActor
    {
        GENERATED_BODY()
    
    public: 
        // 设置该 actor 属性的默认值
        ACountdown();
    
        // 游戏开始时或生成时调用
        virtual void BeginPlay() override;
    
        // 每帧调用
        virtual void Tick( float DeltaSeconds ) override;
    
        //倒计时运行时长,按秒计
        UPROPERTY(EditAnywhere)
        int32 CountdownTime;
    
        UTextRenderComponent* CountdownText;
    
        void UpdateTimerDisplay();
    
        void AdvanceTimer();
    
        UFUNCTION(BlueprintNativeEvent)
        void CountdownHasFinished();
        virtual void CountdownHasFinished_Implementation();
    
        FTimerHandle CountdownTimerHandle;
    };

    Countdown.cpp
    #include "HowTo_VTE.h"
    #include "Countdown.h"
    
    // 设置默认值
    ACountdown::ACountdown()
    {
        // 将此 actor 设为每帧调用 Tick()。不需要时可将此关闭,以提高性能。
        PrimaryActorTick.bCanEverTick = false;
    
        CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
        CountdownText->SetHorizontalAlignment(EHTA_Center);
        CountdownText->SetWorldSize(150.0f);
        RootComponent = CountdownText;
    
        CountdownTime = 3;
    }
    
    // 游戏开始时或生成时调用
    void ACountdown::BeginPlay()
    {
        Super::BeginPlay();
    
        UpdateTimerDisplay();
        GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);
    }
    
    // 每帧调用
    void ACountdown::Tick( float DeltaTime )
    {
        Super::Tick( DeltaTime );
    
    }
    
    void ACountdown::UpdateTimerDisplay()
    {
        CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
    }
    
    void ACountdown::AdvanceTimer()
    {
        --CountdownTime;
        UpdateTimerDisplay();
        if (CountdownTime < 1)
        {
            // 倒计时结束,停止运行定时器。
            GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
            //在定时器结束时按需要执行特殊操作。
            CountdownHasFinished();
        }
    }
    
    void ACountdown::CountdownHasFinished_Implementation()
    {
        //改为一个特殊的读出
        CountdownText->SetText(TEXT("GO!"));
    }

    1 FTimerHandle CountdownTimerHandle;定时器
    调用方法
    2 BeginPlay中设置定时器事件
    GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);
    3 定时执行AdvanceTimer函数
    4 手动计时,到达后使用
     GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
    停止计时器



    玩家控制的相机

    输入绑定略
    PawnWithCamera.h
    #pragma once
    
    #include "GameFramework/Pawn.h"
    #include "PawnWithCamera.generated.h"
    
    UCLASS()
    class HOWTO_PLAYERCAMERA_API APawnWithCamera : public APawn
    {
        GENERATED_BODY()
    
    public:
        // 设置此pawn属性的默认值
        APawnWithCamera();
    
        // 当游戏开始或生成时调用
        virtual void BeginPlay() override;
    
        // 在每一帧调用
        virtual void Tick( float DeltaSeconds ) override;
    
        // 调用以绑定功能到输入
        virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
    
    protected:
        UPROPERTY(EditAnywhere)
        USpringArmComponent* OurCameraSpringArm;
        UCameraComponent* OurCamera;
    
        //输入变量
        FVector2D MovementInput;
        FVector2D CameraInput;
        float ZoomFactor;
        bool bZoomingIn;
    
        // 输入函数
        void MoveForward(float AxisValue);
        void MoveRight(float AxisValue);
        void PitchCamera(float AxisValue);
        void YawCamera(float AxisValue);
        void ZoomIn();
        void ZoomOut();
    };

    PawnWithCamera.cpp
    #include "HowTo_PlayerCamera.h"
    #include "PawnWithCamera.h"
    
    // 设置默认值
    APawnWithCamera::APawnWithCamera()
    {
        // 将此pawn设置为在每一帧都调用Tick()。  如果您不需要这项功能,您可以关闭它以改善性能。
        PrimaryActorTick.bCanEverTick = true;
    
        //创建组件
        RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
        OurCameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
        OurCameraSpringArm->AttachTo(RootComponent);
        OurCameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));
        OurCameraSpringArm->TargetArmLength = 400.f;
        OurCameraSpringArm->bEnableCameraLag = true;
        OurCameraSpringArm->CameraLagSpeed = 3.0f;
        OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));
        OurCamera->AttachTo(OurCameraSpringArm, USpringArmComponent::SocketName);
    
        //控制默认玩家
        AutoPossessPlayer = EAutoReceiveInput::Player0;
    }
    
    // 当游戏开始或生成时调用
    void APawnWithCamera::BeginPlay()
    {
        Super::BeginPlay();
    
    }
    
    // 在每一帧调用
    void APawnWithCamera::Tick( float DeltaTime )
    {
        Super::Tick(DeltaTime);
    
        //如果按下了放大按钮则放大,否则就缩小
        {
            if (bZoomingIn)
            {
                ZoomFactor += DeltaTime / 0.5f;         //Zoom in over half a second
            }
            else
            {
                ZoomFactor -= DeltaTime / 0.25f;        //Zoom out over a quarter of a second
            }
            ZoomFactor = FMath::Clamp<float>(ZoomFactor, 0.0f, 1.0f);
            // 基于ZoomFactor来混合相机的视域和弹簧臂的长度
            OurCamera->FieldOfView = FMath::Lerp<float>(90.0f, 60.0f, ZoomFactor);
            OurCameraSpringArm->TargetArmLength = FMath::Lerp<float>(400.0f, 300.0f, ZoomFactor);
        }
    
        //选择actor的偏转,这样将会旋转相机,因为相机附着于actor
        {
            FRotator NewRotation = GetActorRotation();
            NewRotation.Yaw += CameraInput.X;
            SetActorRotation(NewRotation);
        }
    
        // 选择相机的倾斜,但对其进行限制,这样我们将总是向下看
        {
            FRotator NewRotation = OurCameraSpringArm->GetComponentRotation();
            NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -80.0f, -15.0f);
            OurCameraSpringArm->SetWorldRotation(NewRotation);
        }
    
        // 基于"MoveX"和 "MoveY"轴来处理移动
        {
            if (!MovementInput.IsZero())
            {
                // 把移动输入轴的值每秒缩放100个单位
                MovementInput = MovementInput.SafeNormal() * 100.0f;
                FVector NewLocation = GetActorLocation();
                NewLocation += GetActorForwardVector() * MovementInput.X * DeltaTime;
                NewLocation += GetActorRightVector() * MovementInput.Y * DeltaTime;
                SetActorLocation(NewLocation);
            }
        }
    }
    
    // 调用以绑定功能到输入
    void APawnWithCamera::SetupPlayerInputComponent(class UInputComponent* InputComponent)
    {
        Super::SetupPlayerInputComponent(InputComponent);
    
        // 绑定事件到"ZoomIn"
        InputComponent->BindAction("ZoomIn", IE_Pressed, this, &APawnWithCamera::ZoomIn);
        InputComponent->BindAction("ZoomIn", IE_Released, this, &APawnWithCamera::ZoomOut);
    
        //为四条轴绑定每帧的处理
        InputComponent->BindAxis("MoveForward", this, &APawnWithCamera::MoveForward);
        InputComponent->BindAxis("MoveRight", this, &APawnWithCamera::MoveRight);
        InputComponent->BindAxis("CameraPitch", this, &APawnWithCamera::PitchCamera);
        InputComponent->BindAxis("CameraYaw", this, &APawnWithCamera::YawCamera);
    }
    
    // 输入函数
    void APawnWithCamera::MoveForward(float AxisValue)
    {
        MovementInput.X = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
    }
    
    void APawnWithCamera::MoveRight(float AxisValue)
    {
        MovementInput.Y = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
    }
    
    void APawnWithCamera::PitchCamera(float AxisValue)
    {
        CameraInput.Y = AxisValue;
    }
    
    void APawnWithCamera::YawCamera(float AxisValue)
    {
        CameraInput.X = AxisValue;
    }
    
    void APawnWithCamera::ZoomIn()
    {
        bZoomingIn = true;
    }
    
    void APawnWithCamera::ZoomOut()
    {
        bZoomingIn = false;
    }

    1 创建组件,RootCompnent是Actore的根节点,USceneComponent应该类似Transform,空节点,TEXT后面是组件节点名称
     RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
    类似的有,创建弹簧臂组件
    OurCameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));


    2 绑定到父节点,AttachTo
    OurCameraSpringArm->AttachTo(RootComponent);

    3 获取设置Actor相关属性
    GetActorRotation();
    SetActorRotation(NewRotation);

    4 四元数旋转操作
     FRotator NewRotation = OurCameraSpringArm->GetComponentRotation();
     NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -80.0f, -15.0f);
     OurCameraSpringArm->SetWorldRotation(NewRotation);

    5 FVector2获取单位向量,3维向量是FVector
     FVector2 MovementInput = MovementInput.SafeNormal()

    6 获取Actor 朝向相关
    GetActorForwardVector()
    GetActorRightVector()


    组件和碰撞

    CollidingPawn.h

    // 版权所有 1998-2017 Epic Games, Inc. 保留所有权利。
    
    #pragma once
    
    #include "GameFramework/Pawn.h"
    #include "CollidingPawn.generated.h"
    
    UCLASS()
    class HOWTO_COMPONENTS_API ACollidingPawn : public APawn
    {
        GENERATED_BODY()
    
    public:
        // 设置该 pawn 属性的默认值
        ACollidingPawn();
    
        // 游戏开始时或生成时调用
        virtual void BeginPlay() override;
    
        // 每帧调用
        virtual void Tick( float DeltaSeconds ) override;
    
        // 调用后将功能绑定到输入
        virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
    
        UParticleSystemComponent* OurParticleSystem;
        class UCollidingPawnMovementComponent* OurMovementComponent;
    
        virtual UPawnMovementComponent* GetMovementComponent() const override;
    
        void MoveForward(float AxisValue);
        void MoveRight(float AxisValue);
        void Turn(float AxisValue);
        void ParticleToggle();
    };

    CollidingPawn.cpp

    // 版权所有 1998-2017 Epic Games, Inc. 保留所有权利。
    
    #include "HowTo_Components.h"
    #include "CollidingPawn.h"
    #include "CollidingPawnMovementComponent.h"
    
    // 设置默认值
    ACollidingPawn::ACollidingPawn()
    {
        // 将此 pawn 设为每帧调用 Tick()。不需要时可将此关闭,以提高性能。
        PrimaryActorTick.bCanEverTick = true;
    
        // 我们的根组件是对物理作出反应的球体
        USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
        RootComponent = SphereComponent;
        SphereComponent->InitSphereRadius(40.0f);
        SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
    
        // 创建并放置一个网格体组件,以便了解球体的所在位置
        UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
        SphereVisual->AttachTo(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.0f, 0.0f, -40.0f));
            SphereVisual->SetWorldScale3D(FVector(0.8f));
        }
    
        // 创建一个可启用或停用的粒子系统
        OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
        OurParticleSystem->AttachTo(SphereVisual);
        OurParticleSystem->bAutoActivate = false;
        OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
        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->AttachTo(RootComponent);
        SpringArm->RelativeRotation = FRotator(-45.f, 0.f, 0.f);
        SpringArm->TargetArmLength = 400.0f;
        SpringArm->bEnableCameraLag = true;
        SpringArm->CameraLagSpeed = 3.0f;
    
        // 创建一个摄像机,将其附着到弹簧臂
        UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
        Camera->AttachTo(SpringArm, USpringArmComponent::SocketName);
    
        // 掌控默认玩家
        AutoPossessPlayer = EAutoReceiveInput::Player0;
    
        // 创建移动组件的一个实例,并告知其更新根组件。
        OurMovementComponent = CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent"));
        OurMovementComponent->UpdatedComponent = RootComponent;
    }
    
    // 游戏开始时或生成时调用
    void ACollidingPawn::BeginPlay()
    {
        Super::BeginPlay();
    
    }
    
    // 每帧调用
    void ACollidingPawn::Tick( float DeltaTime )
    {
        Super::Tick( DeltaTime );
    
    }
    
    // 调用后将功能绑定到输入
    void ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
    {
        Super::SetupPlayerInputComponent(InputComponent);
    
        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);
    }
    
    UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const
    {
        return OurMovementComponent;
    }
    
    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();
        }
    }

    CollidingPawnMovementComponent.h

    // 版权所有 1998-2017 Epic Games, Inc. 保留所有权利。
    
    #pragma once
    
    #include "GameFramework/PawnMovementComponent.h"
    #include "CollidingPawnMovementComponent.generated.h"
    
    /**
     * 
     */
    UCLASS()
    class HOWTO_COMPONENTS_API UCollidingPawnMovementComponent : public UPawnMovementComponent
    {
        GENERATED_BODY()
    
    public:
        virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;  
    };

    CollidingPawnMovementComponent.cpp

    // 版权所有 1998-2017 Epic Games, Inc. 保留所有权利。
    
    #include "HowTo_Components.h"
    #include "CollidingPawnMovementComponent.h"
    
    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);
            }
        }
    };

    1 创建一个静态网格组件,并使用资源填充
    // 创建并放置一个网格体组件,以便了解球体的所在位置
        UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
        SphereVisual->AttachTo(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.0f, 0.0f, -40.0f));
            SphereVisual->SetWorldScale3D(FVector(0.8f));
        }
    2 创建一个粒子组件,并用外部资源填充

     OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
        OurParticleSystem->AttachTo(SphereVisual);
        OurParticleSystem->bAutoActivate = false;
        OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
        static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
        if (ParticleAsset.Succeeded())
        {
            OurParticleSystem->SetTemplate(ParticleAsset.Object);
        }

    具体运动组件部分暂时略过。


  • 相关阅读:
    性能测试-地铁模型分析
    如何测试网页登录页面
    软件测试修炼之道(转载)
    每当在测试之路迷茫的时候来看看这篇文章
    软件测试博客较好的网址(供参考)
    Spring扩展:替换IOC容器中的Bean组件 -- @Replace注解
    拯救老旧工程,记桥接SpringMVC与Stripes框架
    Netty实现WebSocket,URI参数问题
    高性能内存队列Disruptor--原理分析
    Idea中Smart Tomcat插件启动报NullPointerException问题
  • 原文地址:https://www.cnblogs.com/nafio/p/9137081.html
Copyright © 2020-2023  润新知