Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

codingfarm

flight 본문

Unreal 4/기타

flight

scarecrow1992 2020. 8. 8. 22:33

언리얼 기본 예제 프로젝트인 flight에 대해 알아보자

a,d 로 좌/우회전

w,s 로 하강/상승

L.shift, L.ctrl로 가속/감속을 하여 비행기를 조종한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
//FlightPawh.h
 
#pragma once
 
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "FlightPawn.generated.h"
 
UCLASS(Config=Game)
class AFlightPawn : public APawn
{
    GENERATED_BODY()
 
    /** StaticMesh component that will be the visuals for our flying pawn */
    UPROPERTY(Category = Mesh, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    class UStaticMeshComponent* PlaneMesh;
 
    /** Spring arm that will offset the camera */
    UPROPERTY(Category = Camera, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    class USpringArmComponent* SpringArm;
 
    /** Camera component that will be our viewpoint */
    UPROPERTY(Category = Camera, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* Camera;
public:
    AFlightPawn();
 
    // Begin AActor overrides
    virtual void Tick(float DeltaSeconds) override;
    virtual void NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit) override;
    // End AActor overrides
 
protected:
 
    // Begin APawn overrides
    virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override; // Allows binding actions/axes to functions
    // End APawn overrides
 
    /** Bound to the thrust axis */
    void ThrustInput(float Val);
    
    /** Bound to the vertical axis */
    void MoveUpInput(float Val);
 
    /** Bound to the horizontal axis */
    void MoveRightInput(float Val);
 
private:
 
    /** How quickly forward speed changes */
    UPROPERTY(Category=Plane, EditAnywhere)
    float Acceleration;
 
    /** How quickly pawn can steer */
    UPROPERTY(Category=Plane, EditAnywhere)
    float TurnSpeed;
 
    /** Max forward speed */
    UPROPERTY(Category = Pitch, EditAnywhere)
    float MaxSpeed;
 
    /** Min forward speed */
    UPROPERTY(Category=Yaw, EditAnywhere)
    float MinSpeed;
 
    /** Current forward speed */
    float CurrentForwardSpeed;
 
    /** Current yaw speed */
    float CurrentYawSpeed;
 
    /** Current pitch speed */
    float CurrentPitchSpeed;
 
    /** Current roll speed */
    float CurrentRollSpeed;
 
public:
    /** Returns PlaneMesh subobject **/
    FORCEINLINE class UStaticMeshComponent* GetPlaneMesh() const { return PlaneMesh; }
    /** Returns SpringArm subobject **/
    FORCEINLINE class USpringArmComponent* GetSpringArm() const { return SpringArm; }
    /** Returns Camera subobject **/
    FORCEINLINE class UCameraComponent* GetCamera() const { return Camera; }
};
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
//FlightPawn.cpp
 
#include "FlightPawn.h"
#include "UObject/ConstructorHelpers.h"
#include "Camera/CameraComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Engine/World.h"
#include "Engine/StaticMesh.h"
 
AFlightPawn::AFlightPawn()
{
    // Structure to hold one-time initialization
    struct FConstructorStatics
    {
        ConstructorHelpers::FObjectFinderOptional<UStaticMesh> PlaneMesh;
        FConstructorStatics()
            : PlaneMesh(TEXT("/Game/Flying/Meshes/UFO.UFO"))
        {
        }
    };
    static FConstructorStatics ConstructorStatics;
 
    // Create static mesh component
    PlaneMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PlaneMesh0"));
    PlaneMesh->SetStaticMesh(ConstructorStatics.PlaneMesh.Get());    // Set static mesh
    RootComponent = PlaneMesh;
 
    // Create a spring arm component
    SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm0"));
    SpringArm->SetupAttachment(RootComponent);    // Attach SpringArm to RootComponent
    SpringArm->TargetArmLength = 160.0f; // The camera follows at this distance behind the character    
    SpringArm->SocketOffset = FVector(0.f,0.f,60.f);
    SpringArm->bEnableCameraLag = false;    // Do not allow camera to lag
    SpringArm->CameraLagSpeed = 15.f;
 
    // Create camera component 
    Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera0"));
    Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);    // Attach the camera
    Camera->bUsePawnControlRotation = false// Don't rotate camera with controller
 
    // Set handling parameters
    Acceleration = 500.f;
    TurnSpeed = 50.f;
    MaxSpeed = 4000.f;
    MinSpeed = 500.f;
    CurrentForwardSpeed = 500.f;
}
 
void AFlightPawn::Tick(float DeltaSeconds)
{
    const FVector LocalMove = FVector(CurrentForwardSpeed * DeltaSeconds, 0.f, 0.f);
 
    // Move plan forwards (with sweep so we stop when we collide with things)
    AddActorLocalOffset(LocalMove, true);
 
    // Calculate change in rotation this frame
    FRotator DeltaRotation(0,0,0);
    DeltaRotation.Pitch = CurrentPitchSpeed * DeltaSeconds;
    DeltaRotation.Yaw = CurrentYawSpeed * DeltaSeconds;
    DeltaRotation.Roll = CurrentRollSpeed * DeltaSeconds;
 
    // Rotate plane
    AddActorLocalRotation(DeltaRotation);
 
    // Call any parent class Tick implementation
    Super::Tick(DeltaSeconds);
}
 
void AFlightPawn::NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
    Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
 
    // Deflect along the surface when we collide.
    FRotator CurrentRotation = GetActorRotation();
    SetActorRotation(FQuat::Slerp(CurrentRotation.Quaternion(), HitNormal.ToOrientationQuat(), 0.025f));
}
 
 
void AFlightPawn::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
    // Check if PlayerInputComponent is valid (not NULL)
    check(PlayerInputComponent);
 
    // Bind our control axis' to callback functions
    PlayerInputComponent->BindAxis("Thrust"this&AFlightPawn::ThrustInput);
    PlayerInputComponent->BindAxis("MoveUp"this&AFlightPawn::MoveUpInput);
    PlayerInputComponent->BindAxis("MoveRight"this&AFlightPawn::MoveRightInput);
}
 
void AFlightPawn::ThrustInput(float Val)
{
    // Is there any input?
    bool bHasInput = !FMath::IsNearlyEqual(Val, 0.f);
    // If input is not held down, reduce speed
    float CurrentAcc = bHasInput ? (Val * Acceleration) : (-0.5f * Acceleration);
    // Calculate new speed
    float NewForwardSpeed = CurrentForwardSpeed + (GetWorld()->GetDeltaSeconds() * CurrentAcc);
    // Clamp between MinSpeed and MaxSpeed
    CurrentForwardSpeed = FMath::Clamp(NewForwardSpeed, MinSpeed, MaxSpeed);
}
 
void AFlightPawn::MoveUpInput(float Val)
{
    // Target pitch speed is based in input
    float TargetPitchSpeed = (Val * TurnSpeed * -1.f);
 
    // When steering, we decrease pitch slightly
    TargetPitchSpeed += (FMath::Abs(CurrentYawSpeed) * -0.2f);
 
    // Smoothly interpolate to target pitch speed
    CurrentPitchSpeed = FMath::FInterpTo(CurrentPitchSpeed, TargetPitchSpeed, GetWorld()->GetDeltaSeconds(), 2.f);
}
 
void AFlightPawn::MoveRightInput(float Val)
{
    // Target yaw speed is based on input
    float TargetYawSpeed = (Val * TurnSpeed);
 
    // Smoothly interpolate to target yaw speed
    CurrentYawSpeed = FMath::FInterpTo(CurrentYawSpeed, TargetYawSpeed, GetWorld()->GetDeltaSeconds(), 2.f);
 
    // Is there any left/right input?
    const bool bIsTurning = FMath::Abs(Val) > 0.2f;
 
    // If turning, yaw value is used to influence roll
    // If not turning, roll to reverse current roll value.
    float TargetRollSpeed = bIsTurning ? (CurrentYawSpeed * 0.5f) : (GetActorRotation().Roll * -2.f);
 
    // Smoothly interpolate roll speed
    CurrentRollSpeed = FMath::FInterpTo(CurrentRollSpeed, TargetRollSpeed, GetWorld()->GetDeltaSeconds(), 2.f);
}
 
cs

cpp로 작성된 코드를 블루프린트로 상속받아 여러 오브젝트들을 만들던 기존의 널리쓰이던 방식과는 달리 이 프로젝트에서는 cpp파일 자체를 오브젝트로 사용한다

먼저 생성자를 살펴본다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
AFlightPawn::AFlightPawn()
{
    // Structure to hold one-time initialization
    struct FConstructorStatics
    {
        ConstructorHelpers::FObjectFinderOptional<UStaticMesh> PlaneMesh;
        FConstructorStatics()
            : PlaneMesh(TEXT("/Game/Flying/Meshes/UFO.UFO"))
        {
        }
    };
    static FConstructorStatics ConstructorStatics;
 
    // Create static mesh component
    PlaneMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PlaneMesh0"));
    PlaneMesh->SetStaticMesh(ConstructorStatics.PlaneMesh.Get());    // Set static mesh
    RootComponent = PlaneMesh;
 
    // Create a spring arm component
    SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm0"));
    SpringArm->SetupAttachment(RootComponent);    // Attach SpringArm to RootComponent
    SpringArm->TargetArmLength = 160.0f; // The camera follows at this distance behind the character    
    SpringArm->SocketOffset = FVector(0.f,0.f,60.f);
    SpringArm->bEnableCameraLag = false;    // Do not allow camera to lag
    SpringArm->CameraLagSpeed = 15.f;
 
    // Create camera component 
    Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera0"));
    Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);    // Attach the camera
    Camera->bUsePawnControlRotation = false// Don't rotate camera with controller
 
    // Set handling parameters
    Acceleration = 500.f;
    TurnSpeed = 50.f;
    MaxSpeed = 4000.f;
    MinSpeed = 500.f;
    CurrentForwardSpeed = 500.f;
}
cs

4~17. 언리얼 에디터가 아닌 코드상에서 에셋을 등록하기 위해 다소 번거로운 작업이 진행된다. 자세한 정보는 아래 문서를 확인한다.

https://docs.unrealengine.com/ko/Programming/Tutorials/Components/1/index.html

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
void AFlightPawn::Tick(float DeltaSeconds)
{
    const FVector LocalMove = FVector(CurrentForwardSpeed * DeltaSeconds, 0.f, 0.f);
 
    // Move plan forwards (with sweep so we stop when we collide with things)
    AddActorLocalOffset(LocalMove, true);
 
    // Calculate change in rotation this frame
    FRotator DeltaRotation(0,0,0);
    DeltaRotation.Pitch = CurrentPitchSpeed * DeltaSeconds;
    DeltaRotation.Yaw = CurrentYawSpeed * DeltaSeconds;
    DeltaRotation.Roll = CurrentRollSpeed * DeltaSeconds;
 
    // Rotate plane
    AddActorLocalRotation(DeltaRotation);
 
    // Call any parent class Tick implementation
    Super::Tick(DeltaSeconds);
}
 
void AFlightPawn::ThrustInput(float Val)
{
    // Is there any input?
    bool bHasInput = !FMath::IsNearlyEqual(Val, 0.f);
    // If input is not held down, reduce speed
    float CurrentAcc = bHasInput ? (Val * Acceleration) : (-0.5f * Acceleration);
    // Calculate new speed
    float NewForwardSpeed = CurrentForwardSpeed + (GetWorld()->GetDeltaSeconds() * CurrentAcc);
    // Clamp between MinSpeed and MaxSpeed
    CurrentForwardSpeed = FMath::Clamp(NewForwardSpeed, MinSpeed, MaxSpeed);
}
 
void AFlightPawn::MoveUpInput(float Val)
{
    // Target pitch speed is based in input
    float TargetPitchSpeed = (Val * TurnSpeed * -1.f);
 
    // When steering, we decrease pitch slightly
    TargetPitchSpeed += (FMath::Abs(CurrentYawSpeed) * -0.2f);
 
    // Smoothly interpolate to target pitch speed
    CurrentPitchSpeed = FMath::FInterpTo(CurrentPitchSpeed, TargetPitchSpeed, GetWorld()->GetDeltaSeconds(), 2.f);
}
 
void AFlightPawn::MoveRightInput(float Val)
{
    // Target yaw speed is based on input
    float TargetYawSpeed = (Val * TurnSpeed);
 
    // Smoothly interpolate to target yaw speed
    CurrentYawSpeed = FMath::FInterpTo(CurrentYawSpeed, TargetYawSpeed, GetWorld()->GetDeltaSeconds(), 2.f);
 
    // Is there any left/right input?
    const bool bIsTurning = FMath::Abs(Val) > 0.2f;
 
    // If turning, yaw value is used to influence roll
    // If not turning, roll to reverse current roll value.
    float TargetRollSpeed = bIsTurning ? (CurrentYawSpeed * 0.5f) : (GetActorRotation().Roll * -2.f);
 
    // Smoothly interpolate roll speed
    CurrentRollSpeed = FMath::FInterpTo(CurrentRollSpeed, TargetRollSpeed, GetWorld()->GetDeltaSeconds(), 2.f);
}
 
 
void AFlightPawn::NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
    Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
 
    // Deflect along the surface when we collide.
    FRotator CurrentRotation = GetActorRotation();
    SetActorRotation(FQuat::Slerp(CurrentRotation.Quaternion(), HitNormal.ToOrientationQuat(), 0.025f));
}
cs

입력에 맞추어 속도를 조정하고 비행기를 회전시킨다.

그리고 장애물에 충돌하면 매우 빠른속도로 비행기를 회전시킨다.

 

'Unreal 4 > 기타' 카테고리의 다른 글

펀치 - 발차기  (0) 2020.07.22
펀치 - 소리 재생  (0) 2020.07.20
펀치 - 충돌 이벤트(Hit Event)  (0) 2020.07.20
펀치 - 스켈레톤 소켓  (0) 2020.07.19
펀치 - 애니메이션 몽타주  (0) 2020.07.18
Comments