zoukankan      html  css  js  c++  java
  • UnrealEngine4入门(二) 实现一个可用按键控制的球体

    源码摘自官网guide,加上部分自己的理解和注释

    接上篇博客 本文实现一个可用WASD控制滚动的球体

    先创建一个可见的球体:

    在CollidingPawn.cpp的构造函数ACollidingPawn::ACollidingPawn()中添加一个球体,一个网格组件(mesh),一个弹簧臂和相机,代码如下:

        //创建一个球体
        USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
        //设置为根组件
        RootComponent = SphereComponent;
        //设置半径
        SphereComponent->InitSphereRadius(40.0f);
        SphereComponent->SetCollisionProfileName(TEXT("Pawn"));
    
        // 创建并放置网格物体组件,这样我们能看到球体的位置
        UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
        //如果不把网格附加到SphereComponent 就看不到球体
        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));
        }
    
        //  使用弹簧臂来让相机获得一种平滑、自然的运动。
        //  弹簧臂的目的是让视角跟SphereComponent保持一定距离,如果不加,效果像fps游戏的第一视角一样
        USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm"));
        SpringArm->AttachTo(RootComponent);
        SpringArm->RelativeRotation = FRotator(-45.f, 0.f, 0.f); //45度角
        SpringArm->TargetArmLength = 400.0f; //弹簧臂长度
        SpringArm->bEnableCameraLag = true;
        SpringArm->CameraLagSpeed = 3.f;
    
        // 创建相机并附加到弹簧臂
        // 如果没有相机 什么都看不到
        UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
        Camera->AttachTo(SpringArm, USpringArmComponent::SocketName);

    然后配置按键: 打开ue编辑器, 选择编辑->项目设置-> 输入, 然后在右边的axis mappings加入如下设置:

    MoveForWard,MoveRight,Turn,Turn_Y 可自定义,表示跟各个按键的绑定关系。

    然后创建一个类CollidingPawnMovementComponent继承自PawnMovementComponent(控制pawn移动的组件),我们可以把WASD绑定的行为绑定到这个component上,然后把该component绑定到我们刚才创建的球体上:

    CollidingPawnMovementComponent.cpp

    #include "Demo.h"
    #include "CollidingPawnMovementComponent.h"
    
    void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
    {
        Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
    
        // Make sure that everything is still valid, and that we are allowed to move.
        if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
        {
            return;
        }
    
        // Get (and then clear) the movement vector that we set in ACollidingPawn::Tick
        FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f;
        if (!DesiredMovementThisFrame.IsNearlyZero())
        {
            FHitResult Hit;
            SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit);
    
            // If we bumped into something, try to slide along it
            if (Hit.IsValidBlockingHit())
            {
                SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit);
            }
        }
    };

    然后在CollidingPawn.h中加入如下代码:

    class UCollidingPawnMovementComponent* OurMovementComponent;

    先将movementComponent绑定到刚才加的球体上,在CollidingPawn构造函数底部加入如下代码:

        // Create an instance of our movement component, and tell it to update the root.
        OurMovementComponent = CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent"));
        OurMovementComponent->UpdatedComponent = RootComponent;

    为了让游戏中的其他类知道CollidingPawn目前正在使用CollidingPawnMovementComponent作为移动控制组件,需要在CollidingPawn.h中加入以下代码:

    virtual UPawnMovementComponent* GetMovementComponent() const override;

    然后在CollidingPawn.cpp中加入:

    UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const
    {
        return OurMovementComponent;
    }

     刚才我们已经将新创建的移动控制组件绑定到了球体上,现在需要把WASD触发的函数绑定到移动组件上,在CollidingPawn中实现往前移动,往左移动,转动视角的三个方法:

    // 往前(后)移动
    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);
    }

    然后将这三个方法在ACollidingPawn::SetupPlayerInputComponent中注册:

    void ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
    {
        Super::SetupPlayerInputComponent(InputComponent);
    
        InputComponent->BindAxis("MoveForward", this, &ACollidingPawn::MoveForward);
        InputComponent->BindAxis("MoveRight", this, &ACollidingPawn::MoveRight);
        InputComponent->BindAxis("Turn", this, &ACollidingPawn::Turn);
    }

    以上就完成了一个可用WASD移动和鼠标控制左右视角的球体

    如果上下移动视角,可仿照以上的ACollidingPawn::Turn方法,将NewRotation.Yaw += AxisValue; 改为NewRotation.Pitch += AxisValue;即可

  • 相关阅读:
    PCI Express体系结构导读(3)- PCIE
    PCI Express体系结构导读(2)
    npm添加代理和取消代理
    流媒体压力测试rtmp&hls(含推流和拉流)
    流媒体跳坑: 03-视频会议:使用LiveRTC来做视频直播
    流媒体跳坑: 02-视频会议:Webrtc服务器
    正交调制解调(MATLAB)
    mp4文件断电保存-(关于:MP4视频文件损坏的一点想法)
    流媒体跳坑: 01-Mp4 文件解析
    centos 守护 node 进程
  • 原文地址:https://www.cnblogs.com/hithlb/p/4855234.html
Copyright © 2011-2022 走看看