# Spline应用

# Spline移动对象

让角色跟随Spline的轨迹移动:

蓝图实现为:BP_Spline_Move

蓝图原理为:

splineMove

# Spline管道

通过Spline来控制管道类的物体的摆放:

蓝图实现为:BP_Spline_Pipeline

蓝图原理为:

splinePipeline

# Spline揽绳

下面使用Spline来放置揽绳一样的东西:

蓝图实现为:BP_LanSheng

蓝图实现细节为:

splineLanSheng

# Spline放置Actor

# Spline固定距离

固定距离摆放物体,拖拽Spline即可实现。

蓝图实现为:BP_Spline_SetActor

蓝图原理为:

splineSetActor

# Spline放置路块

每固定一个距离放置路块,并且路块会填充该距离:

蓝图实现为:BP_Spline_SetRoadActor

蓝图原理为:

splineSetRoadActor

# Spline放置墙块

使用Spline放置墙块,在两个节点之间放置一块墙,不管角度如何,两个墙的衔接处不会扭曲。

需要的资料有:

蓝图原理为:

SplineWall

WallColor

# 代码实现

下面是C++实现spline放置墙块的实现:

//==============================AMySplineActor.h==========================

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SplineComponent.h"
#include "Components/SplineMeshComponent.h"

#include "MySplineActor.generated.h"

UCLASS()
class MYRUNTIMETOOLS_API AMySplineActor : public AActor
{
    GENERATED_BODY()

public:
    // Sets default values for this actor's properties
    AMySplineActor();

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "AAA MySceneComponent",meta = (AllowPrivateAccess = true))
    USceneComponent* MyRootComp;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AAA MySceneComponent",meta = (AllowPrivateAccess = true))
    USplineComponent* MySpline; 
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AAA MySceneComponent",meta = (AllowPrivateAccess = true))
    UStaticMesh* targetMesh;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AAA MySceneComponent",meta = (AllowPrivateAccess = true))
    UMaterial* targetMaterial;
    
    void PutMeshWithPoints();
    virtual void OnConstruction(const FTransform& Transform) override;
    
protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};


//==============================AMySplineActor.cpp==========================
#include "MySplineActor.h"


// Sets default values
AMySplineActor::AMySplineActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    MyRootComp = CreateDefaultSubobject<USceneComponent>(TEXT("RootComp"));
    //MyRootComp->SetMobility(EComponentMobility::Movable);
    RootComponent = MyRootComp;

    MySpline = CreateDefaultSubobject<USplineComponent>(TEXT("MySpline"));
    MySpline->SetupAttachment(MyRootComp);
}

// Called when the game starts or when spawned
void AMySplineActor::BeginPlay()
{
    Super::BeginPlay();
    
}

// Called every frame
void AMySplineActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

void AMySplineActor::PutMeshWithPoints()
{
    int pointNum = MySpline->GetNumberOfSplinePoints();
    
    if(pointNum<2)
        return;
    
    for(int i=0;i<pointNum-1;i++)
    {
        const int pointEndNum = (i+1)%pointNum;
        USplineMeshComponent* pSplineMesh = NewObject<USplineMeshComponent>(this, USplineMeshComponent::StaticClass());
        pSplineMesh->SetMobility(EComponentMobility::Movable);
        pSplineMesh->CreationMethod = EComponentCreationMethod::UserConstructionScript;
        pSplineMesh->SetStaticMesh(targetMesh);
        pSplineMesh->SetMaterial(0,targetMaterial);
        //pSplineMesh->SetupAttachment(MySpline);
        pSplineMesh->AttachToComponent(MySpline,FAttachmentTransformRules::KeepRelativeTransform);
        //pSplineMesh->SetForwardAxis(ForwardAxis, false);
        FVector StartPos;
        FVector StartTangent;
        MySpline->GetLocationAndTangentAtSplinePoint(i, StartPos, StartTangent, ESplineCoordinateSpace::Local);
        FVector EndPos;
        FVector EndTangent;
        MySpline->GetLocationAndTangentAtSplinePoint(pointEndNum, EndPos, EndTangent, ESplineCoordinateSpace::Local);
        pSplineMesh->SetStartAndEnd(StartPos, StartTangent, EndPos, EndTangent);
    }
 
    // Register the component
    RegisterAllComponents();

}

void AMySplineActor::OnConstruction(const FTransform& Transform)
{
    Super::OnConstruction(Transform);
    PutMeshWithPoints();
}
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