.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SplineTraceActor.generated.h"
UCLASS()
class MZEDUCATION_API ASplineTraceActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASplineTraceActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
public:
//根组件;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "DefaultComponent")
class USceneComponent* Root;
//可编辑的Spline;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "DefaultComponent")
class USplineComponent* EditableSpline;
//用于显示的Spline;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "DefaultComponent")
class USplineComponent* DisplaybleSpline;
//用于存放生成的点的信息的数组;
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="DefaultValues")
TArray<FVector> Points;
//分割次数 点的密集程度
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "DefaultValues", meta = (ClampMin = "10", ClampMax = "45"))
int Times=10;
//函数序列
//ConstructionScript函数;
UFUNCTION(BlueprintCallable, Category = "ConstructionFunction")
virtual void OnConstruction(const FTransform& Transform) override;
//得到分割后每段的距离;
UFUNCTION(BlueprintCallable, Category = "CaculateDistance")
float GetPerDistance();
//得到发出射线的点的起始点和终止点
UFUNCTION(BlueprintCallable, Category = "CaculateDistance")
void GetTracePoint(float CurrentDistance, FVector& StartPointLoc, FVector& EndPointLoc);
};
.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "SplineTraceActor.h"
#include "Components/SplineComponent.h"
#include "Engine/EngineTypes.h"
#include "Engine/World.h"
#include "Components/TimelineComponent.h"
// Sets default values
ASplineTraceActor::ASplineTraceActor()
{
// 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;
Root = CreateDefaultSubobject<USceneComponent>(TEXT("RootCom"));
EditableSpline = CreateDefaultSubobject<USplineComponent>(TEXT("EditableSpline"));
DisplaybleSpline = CreateDefaultSubobject<USplineComponent>(TEXT("DisplaybleSpline"));
EditableSpline->bInputSplinePointsToConstructionScript = true;
DisplaybleSpline->bInputSplinePointsToConstructionScript = true;
RootComponent = Root;
EditableSpline->SetupAttachment(Root);
DisplaybleSpline->SetupAttachment(Root);
DisplaybleSpline->ClearSplinePoints(true);
}
// Called when the game starts or when spawned
void ASplineTraceActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ASplineTraceActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ASplineTraceActor::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
Points.Empty();
for (int i=0;i<Times;i++)
{
float dis = GetPerDistance()*i;
//UE_LOG(LogTemp, Warning, TEXT("dis:%f"), dis);
FVector StartPoint,EndPoint;
GetTracePoint(dis, StartPoint, EndPoint);
//UE_LOG(LogTemp, Warning, TEXT("点:%d,%d,%d"),StartPoint.X,StartPoint.Y,StartPoint.Z);
UWorld* world = GetWorld();
if (world)
{
FHitResult hitresult;
GetWorld()->LineTraceSingleByObjectType(hitresult, StartPoint, EndPoint, true);
FVector Hitpoint = hitresult.Location;
Points.Add(Hitpoint);
}
}
DisplaybleSpline->ClearSplinePoints(true);
for (int i=0;i<Points.Num();i++)
{
DisplaybleSpline->AddSplineWorldPoint(Points[i]);
//UE_LOG(LogTemp, Warning, TEXT("Construction函数,points:%d,points个数:%d"),Points[i].Y,Points.Num());
}
}
float ASplineTraceActor::GetPerDistance()
{
float perDistance = 0;
if (Times)
{
perDistance = (EditableSpline->GetSplineLength())/Times;
//UE_LOG(LogTemp, Warning, TEXT("%f:"), perDistance)
}
else
{
UE_LOG(LogTemp,Warning,TEXT("Times的值为空!"))
}
return perDistance;
}
void ASplineTraceActor::GetTracePoint(float CurrentDistance, FVector& StartPointLoc, FVector& EndPointLoc)
{
FVector Point = EditableSpline->GetLocationAtDistanceAlongSpline(CurrentDistance, ESplineCoordinateSpace::Local);
Point = FVector(Point.X, Point.Y, Point.Z + 1000);
StartPointLoc = GetActorLocation() + GetActorRotation().RotateVector(Point);
EndPointLoc = StartPointLoc + FVector(0, 0, -3000);
}