您的位置:首页 > 产品设计 > UI/UE

Unreal4 使用spline , splinemesh组件构建赛道小例子

2017-06-10 13:41 337 查看
本人最近几天一直想写一个赛道构建的例子,一下使用UnrealReal4中spline,splinemesh组件。具体怎么用大家去看官方的wiki就行了,这里直接贴代码`。

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RoadSpline.generated.h"

class USplineComponent;
class USplineMeshComponent;
class UTextRenderComponent;

USTRUCT()
struct FSplineRoadData
{
GENERATED_USTRUCT_BODY()

UPROPERTY( )
bool    LeftGuardRail;

UPROPERTY()
bool    RightGuardRail;

UPROPERTY( )
float   TrackBank;

UPROPERTY( )
float   TrackWidth;

UPROPERTY( )
float   TrackThickness;

FSplineRoadData()
: LeftGuardRail(true)
, RightGuardRail(true)
, TrackBank(0.0f)
, TrackWidth(1.0f)
, TrackThickness(1.0f)
{

}
};

UCLASS()
class RACER_API ARoadSpline : public AActor
{
GENERATED_BODY()

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

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void OnConstruction(const FTransform& Transform);
USplineMeshComponent* AddTrackElement(int index,UStaticMesh* mesh);
virtual void UpdateSplineMesh(TArray<USplineMeshComponent*>& splineArray);

virtual UTextRenderComponent* DrawTrackNumber( int index );
public:

UPROPERTY(EditDefaultsOnly, Category = "Road Components")
USplineComponent* mSplineComponent;

UPROPERTY( )
int NumberOfSplinePoints;

UPROPERTY( )
TArray<FSplineRoadData> RoadDataArray;

UPROPERTY( )
TArray<USplineMeshComponent*> SplineMeshArray;
UPROPERTY( )
TArray<USplineMeshComponent*> LeftSplineMeshArray;
UPROPERTY( )
TArray<USplineMeshComponent*> RightSplineMeshArray;

UPROPERTY( )
TArray<UTextRenderComponent*> textArray;

UPROPERTY(EditDefaultsOnly, Category = "LoopRoad")
bool    LoopingTrack; // 是否循环,貌似现在不可用

UPROPERTY()
int    mCurrentIndex; // 当前编辑第几个

UPROPERTY()
int    mPointIndex; // 当前编辑第几个

UPROPERTY(transient)
class UStaticMesh* CameraMesh;
UPROPERTY(transient)
class UStaticMesh* rightMesh;
UPROPERTY(transient)
class UStaticMesh* leftMesh;

UPROPERTY( EditDefaultsOnly, Category = "Collision" )
bool Collisions; // 是否支持碰撞

};


一下是实现:

// Fill out your copyright notice in the Description page of Project Settings.

#include "RoadSpline.h"
#include "Components/SplineComponent.h"
#include "Components/SplineMeshComponent.h"
#include "Components/TextRenderComponent.h"
#include "Engine/CollisionProfile.h"
#include "UObject/ConstructorHelpers.h"

// Sets default values
ARoadSpline::ARoadSpline()
: Collisions(false)
, mPointIndex(0)
{
// 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;
mSplineComponent = CreateDefaultSubobject<USplineComponent>(TEXT("RoadSpline"));
mSplineComponent->SetupAttachment(RootComponent);
//    SetRootComponent(mSplineComponent);

{
static ConstructorHelpers::FObjectFinder<UStaticMesh> ObjMesh(TEXT("StaticMesh'/Game/TrackGenerator/Props/RoadMesh.RoadMesh'"));
CameraMesh = ObjMesh.Object;
}

{
static ConstructorHelpers::FObjectFinder<UStaticMesh> ObjMesh(TEXT("StaticMesh'/Game/TrackGenerator/Props/L_GuardRail.L_GuardRail'"));
leftMesh = ObjMesh.Object;
}

{
static ConstructorHelpers::FObjectFinder<UStaticMesh> ObjMesh(TEXT("StaticMesh'/Game/TrackGenerator/Props/R_GuardRail.R_GuardRail'"));
rightMesh = ObjMesh.Object;
}

NumberOfSplinePoints = 0;
mCurrentIndex = 0;

}

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

}

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

}

void ARoadSpline::OnConstruction(const FTransform &Transform)
{
if (mSplineComponent == NULL) {
return ;
}
NumberOfSplinePoints = mSplineComponent->GetNumberOfSplinePoints();

int RoadDataNum = RoadDataArray.Num() ;

if (RoadDataNum < NumberOfSplinePoints) {
int addNum = NumberOfSplinePoints - RoadDataNum;
for (int i =0 ; i<addNum; i++) {
FSplineRoadData item;
RoadDataArray.Add( item );
}
}
else if( RoadDataNum > NumberOfSplinePoints )
{
int subNum = NumberOfSplinePoints - RoadDataNum;
for (int i =0 ; i<subNum; i++) {
RoadDataArray.Pop();
}
}

int lastIndex = LoopingTrack ? NumberOfSplinePoints - 1 : NumberOfSplinePoints - 2;
for ( ; mCurrentIndex <= lastIndex; mCurrentIndex++)
{
FSplineRoadData road_item = RoadDataArray[mCurrentIndex];
if (road_item.RightGuardRail)
{
USplineMeshComponent* splineMeshCom = AddTrackElement(mCurrentIndex, rightMesh);
RightSplineMeshArray.Add(splineMeshCom);
}
if (road_item.LeftGuardRail)
{
USplineMeshComponent* splineMeshCom = AddTrackElement(mCurrentIndex, leftMesh);
LeftSplineMeshArray.Add(splineMeshCom);

}
{
//            GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("list"));
USplineMeshComponent* splineMeshCom = AddTrackElement(mCurrentIndex, CameraMesh);
SplineMeshArray.Add(splineMeshCom);
}
}
for (; mPointIndex < NumberOfSplinePoints ; mPointIndex ++)
{
//        GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("point"));
UTextRenderComponent* renderCom = DrawTrackNumber( mPointIndex );
textArray.Add( renderCom );
}

for (int i = 0 ; i< textArray.Num(); i++)
{

UTextRenderComponent* renderCom = textArray[i];
if (renderCom) {
FVector LocalPosition,LocalTangent;
mSplineComponent->GetLocalLocationAndTangentAtSplinePoint(i,LocalPosition,LocalTangent);

LocalPosition.Z += 100;
FVector Scale3D(1.0,1.0,1.0);
LocalTangent *= -1;
FRotator rotator = LocalTangent.Rotation();
FTransform tranform( rotator,LocalPosition,Scale3D );
renderCom->SetRelativeTransform(tranform);
}

}

UpdateSplineMesh(SplineMeshArray);
UpdateSplineMesh(LeftSplineMeshArray);
UpdateSplineMesh(RightSplineMeshArray);

}

void ARoadSpline::UpdateSplineMesh(TArray<USplineMeshComponent*>& splineArray)
{
for (int i =0 ; i<splineArray.Num(); i++) {
USplineMeshComponent* segment = splineArray[i];

if (segment) {
FVector LocalStartPosition,LoccalStartTangent,LocalEndPosition,LocalEndTangent;
mSplineComponent->GetLocalLocationAndTangentAtSplinePoint(i,LocalStartPosition,LoccalStartTangent);
mSplineComponent->GetLocalLocationAndTangentAtSplinePoint(i+1, LocalEndPosition,
LocalEndTangent);
segment->SetStartAndEnd(LocalStartPosition, LoccalStartTangent,
LocalEndPosition, LocalEndTangent);
}
}
}

USplineMeshComponent* ARoadSpline::AddTrackElement(int index, UStaticMesh *mesh)
{

UStaticMesh* LocalTrackElementMesh = mesh;
int LocalCurrentTrackPoint = index;
int LocalNextTrackPoint = ( index + 1 ) % NumberOfSplinePoints;

FString text = FString::Printf(TEXT("%d,%d"),LocalCurrentTrackPoint,LocalNextTrackPoint);

GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, text);
FSplineRoadData roadItem = RoadDataArray[LocalCurrentTrackPoint];
FSplineRoadData nextRoadItem = RoadDataArray[LocalNextTrackPoint];

int LocalStartRoll = roadItem.TrackBank;
int LocalEndRoll = nextRoadItem.TrackBank;
FVector2D LocalEndScale(nextRoadItem.TrackWidth,nextRoadItem.TrackThickness);
FVector2D LocalStartScale(roadItem.TrackWidth,roadItem.TrackThickness);

USplineMeshComponent* const Segment = NewObject<USplineMeshComponent>(this);

if (Segment)
{
//      GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("add"));
Segment->SetStaticMesh(LocalTrackElementMesh);

Segment->SetStartRoll(LocalStartRoll,true);
Segment->SetEndRoll(LocalEndRoll);
Segment->SetStartScale(LocalStartScale);
Segment->SetEndScale(LocalEndScale);
Segment->SetMobility(EComponentMobility::Stationary);
if ( Collisions)
Segment->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
else
Segment->SetCollisionEnabled(ECollisionEnabled::NoCollision);

Segment->SetForwardAxis(ESplineMeshAxis::X);

Segment->SetupAttachment( RootComponent );
Segment->RegisterComponent();

return Segment;
}
return NULL;
}

UTextRenderComponent* ARoadSpline::DrawTrackNumber(int index)
{
FString indexStr = FString::Printf( TEXT( "%d" ),index);
FText TestHUDText = FText::FromString(indexStr);
UTextRenderComponent* renderCom = NewObject<UTextRenderComponent>(this);

if ( renderCom ) {
renderCom->SetupAttachment( RootComponent );
renderCom->RegisterComponent( );
renderCom->SetText( TestHUDText );
return renderCom;
}

return NULL;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Ue4-spline