Bootstrap

UE5中物体(instancemesh)沿样条线(spline)循环移动

 

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

#pragma once

#include "CoreMinimal.h"
#include "Components/SplineComponent.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MeshMovingOnSplineClass.generated.h"

/**
 * 
 */
UCLASS()
class TCPCONNENT_API UMeshMovingOnSplineClass : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable)
	static void MeshOnSplineMoving(int32 MeshCount,UInstancedStaticMeshComponent* InstancedStaticMesh,USplineComponent* spline,float Speed = 1);

	static FTransform SpawnTransform;
	static float InitSpeed;
	static FVector SplineVector;
	static FRotator SplineRotator;
	static FVector SplineScale;
	static FTransform UpdateTransform;
	
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "MeshMovingOnSplineClass.h"

#include "Components/InstancedStaticMeshComponent.h"

float UMeshMovingOnSplineClass::InitSpeed;
FTransform UMeshMovingOnSplineClass::SpawnTransform;
FVector UMeshMovingOnSplineClass::SplineVector;
FRotator UMeshMovingOnSplineClass::SplineRotator;
FVector UMeshMovingOnSplineClass::SplineScale = FVector(1,1,1);
FTransform UMeshMovingOnSplineClass::UpdateTransform;

void UMeshMovingOnSplineClass::MeshOnSplineMoving(int32 MeshCount, UInstancedStaticMeshComponent* InstancedStaticMesh,
	USplineComponent* spline, float Speed)
{
	if (InstancedStaticMesh->GetInstanceCount() < MeshCount)
	{		
		for (int i = InstancedStaticMesh->GetInstanceCount(); i < MeshCount; i++)
		{
			InstancedStaticMesh->AddInstance(SpawnTransform,true);
		}
	}

	InitSpeed = InitSpeed + Speed;
	for (int j = 0; j < MeshCount; j++)
	{
		float AA = spline->GetSplineLength() / MeshCount;
		float BB = j * AA;
		float CC = BB + InitSpeed;
		float DD = fmodf(CC,spline->GetSplineLength());

		SplineVector = spline->GetWorldLocationAtDistanceAlongSpline(DD);
		SplineRotator = spline->GetWorldRotationAtDistanceAlongSpline(DD);

		UpdateTransform.SetLocation(SplineVector);
		UpdateTransform.SetRotation(SplineRotator.Quaternion());
		UpdateTransform.SetScale3D(SplineScale);
		
		InstancedStaticMesh->UpdateInstanceTransform(j,UpdateTransform,true,true,false);
	}
}
if (InstancedStaticMesh->GetInstanceCount() < MeshCount)
	{
		for (int i = InstancedStaticMesh->GetInstanceCount(); i < MeshCount; i++)
		{
			InstancedStaticMesh->AddInstance(SpawnTransform, true);
		}
	}

	InitSpeed = InitSpeed + Speed;

	float AA;
	float BB;
	float CC;
	float DD;

	if (Speed >= 0)
	{
		// Speed为正数,向前循环移动逻辑
		for (int j = 0; j < MeshCount; j++)
		{
			AA = spline->GetSplineLength() / MeshCount;
			BB = j * AA;
			CC = BB + InitSpeed;
			DD = fmodf(CC, spline->GetSplineLength());

			SplineVector = spline->GetWorldLocationAtDistanceAlongSpline(DD);
			SplineRotator = spline->GetWorldRotationAtDistanceAlongSpline(DD);

			UpdateTransform.SetLocation(SplineVector);
			UpdateTransform.SetRotation(SplineRotator.Quaternion());
			UpdateTransform.SetScale3D(SplineScale);

			InstancedStaticMesh->UpdateInstanceTransform(j, UpdateTransform, true, true, false);
		}
	}
	else
	{
		// Speed为负数,向后循环移动逻辑
		for (int j = MeshCount - 1; j >= 0; j--)
		{
			AA = spline->GetSplineLength() / MeshCount;
			BB = (MeshCount - 1 - j) * AA;
			CC = spline->GetSplineLength() - (BB + (-InitSpeed));
			DD = fmodf(CC, spline->GetSplineLength());

			SplineVector = spline->GetWorldLocationAtDistanceAlongSpline(DD);
			SplineRotator = spline->GetWorldRotationAtDistanceAlongSpline(DD);

			UpdateTransform.SetLocation(SplineVector);
			UpdateTransform.SetRotation(SplineRotator.Quaternion());
			UpdateTransform.SetScale3D(SplineScale);

			InstancedStaticMesh->UpdateInstanceTransform(j, UpdateTransform, true, true, false);
		}
	}

正反方向循环移动

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

#pragma once

#include "CoreMinimal.h"
#include "Components/SplineComponent.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"


/**
 * 
 */
UCLASS()
class TANKCARBIG_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintCallable)
	static void MeshOnSplineMoving(int32 MeshCount,UInstancedStaticMeshComponent* InstancedStaticMesh,USplineComponent* spline,float Speed = 1);
 
	static FTransform SpawnTransform;
	static float InitSpeed;
	static FVector SplineVector;
	static FRotator SplineRotator;
	static FVector SplineScale;
	static FTransform UpdateTransform;
	
	
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyBlueprintFunctionLibrary.h"
#include "Components/InstancedStaticMeshComponent.h"

float UMyBlueprintFunctionLibrary::InitSpeed;
FTransform UMyBlueprintFunctionLibrary::SpawnTransform;
FVector UMyBlueprintFunctionLibrary::SplineVector;
FRotator UMyBlueprintFunctionLibrary::SplineRotator;
FVector UMyBlueprintFunctionLibrary::SplineScale = FVector(1,1,1);
FTransform UMyBlueprintFunctionLibrary::UpdateTransform;

void UMyBlueprintFunctionLibrary::MeshOnSplineMoving(int32 MeshCount,
	UInstancedStaticMeshComponent* InstancedStaticMesh, USplineComponent* spline, float Speed)
{
	if (InstancedStaticMesh->GetInstanceCount() < MeshCount)
	{
		for (int i = InstancedStaticMesh->GetInstanceCount(); i < MeshCount; i++)
		{
			InstancedStaticMesh->AddInstance(SpawnTransform, true);
		}
	}

	InitSpeed = InitSpeed + Speed;

	for (int j = (Speed >= 0? 0 : MeshCount - 1);
		 (Speed >= 0 && j < MeshCount) || (Speed < 0 && j >= 0);
		 j += (Speed >= 0? 1 : -1))
	{
		float AA = spline->GetSplineLength() / MeshCount;
		float BB;
		float CC;
		float DD;

		if (Speed >= 0)
		{
			// Speed为正数,向前循环移动逻辑
			BB = j * AA;
			CC = BB + InitSpeed;
			DD = fmodf(CC, spline->GetSplineLength());
		}
		else
		{
			// Speed为负数,向后循环移动逻辑
			// 考虑Speed绝对值较大时的情况,先计算理论上的累计偏移量
			float totalOffset = (-InitSpeed) + ((MeshCount - 1 - j) * AA);
			// 处理循环,确保总偏移量在样条线长度范围内
			totalOffset = fmodf(totalOffset, spline->GetSplineLength());
			// 计算实际位置,从样条线末尾往前推
			CC = spline->GetSplineLength() - totalOffset;
			DD = fmodf(CC, spline->GetSplineLength());

			BB = (MeshCount - 1 - j) * AA;
		}

		// 获取当前实例在样条线上的位置和旋转
		SplineVector = spline->GetWorldLocationAtDistanceAlongSpline(DD);
		SplineRotator = spline->GetWorldRotationAtDistanceAlongSpline(DD);

		// 设置更新实例的变换
		UpdateTransform.SetLocation(SplineVector);
		UpdateTransform.SetRotation(SplineRotator.Quaternion());
		UpdateTransform.SetScale3D(SplineScale);

		// 更新实例的变换
		InstancedStaticMesh->UpdateInstanceTransform(j, UpdateTransform, true, true, false);
	}
}

;