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; }
相关文章推荐
- 使用服务组件体系结构构建 SOA 解决方案——第 1 部分
- 关于构建一个使用EJB组件的新系统
- 使用Java构建高伸缩性组件
- 使用rpcgen构建分布式程序的一个简单例子
- 如何使用ECSide列表组件构建列表(内附源码)
- 使用XUL在Firefox/Mozilla构建的RIA例子
- 使用组件构建Android应用程序
- 使用代码分离构建自定义组件
- 使用代码分离构建自定义组件
- 使用组件构建Android应用程序
- 使用ChilkatDotNet组件构建自己的搜索引擎
- 构建简单的 C++ 服务组件,第 2 部分: 通过服务组件体系结构使用 Python、Ruby 和 Web 服务
- Flex 3使用代码分离构建自定义组件
- JTable表格组件使用例子
- Flex4之使用ActionScript构建组件
- 例子二:使用servicemix-camel组件
- 构建高性能网站的14条法则:使用Gzip压缩组件
- Flex 3快速入门: 构建高级用户界面 使用 Repeater 组件
- 例子三:使用servicemix-cxf-bc组件代理WebService
- 使用组件构建Android应用程序