[UE4]自定義MovementComponent組件


自定義Movement組件 

目的:實現自定義軌跡如拋物線,線性,定點等運動方式,作為組件控制綁定對象的運動。

基類:UMovementComponent

過程:

1.創建UCustomMovementComponenet繼承UMovementComponent類,作為各種具體軌跡的父類,完成主要流程的實現。並提供接口給子類override實現具體計算過程。

2.實現子類軌跡計算過程。這里僅提供線性移動軌跡作為示例。


一、UCustomMovementComponent類

/**
 * class : UCustomMovementComponent
 * author : Jia Zhipeng
 * Base class of custom movement component
 */
UCLASS(ClassGroup = Movement, abstract, ShowCategories = (CustomMovement))
class CLIENT_API UCustomMovementComponent : public UMovementComponent
{
	GENERATED_UCLASS_BODY()

public:
	/*Initialize target position, must be called before TickComponent.
	**@param bFixedPoint : whether target position is fixed point or target component
	*/
	UFUNCTION(BlueprintCallable, Category = CustomMovement)
	virtual void SetTargetPosition(bool bFixedPoint, FVector PointLocation, USceneComponent* MoveTarget=nullptr);
	//Initialize params which will be used during computation, implementation in derived class.
	virtual void InitComputeParams() {};
	//Computation process, must be override in derived class.
	virtual void ComputeMovement(float DeltaTime, FVector& OutMoveDelta, FQuat& OutNewRotation) {};
	//Update process.
	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
	//Check whether should be stopped
	void CheckIsStop();

protected:
	FVector GetTargetPosition();	
	FVector GetHostPosition();
	//if bFixedPoint is true, use this location to update.
	FVector PointLocation;

	//The current target we are homing towards. Can only be set at runtime (when projectile is spawned or updating).
	TWeakObjectPtr<USceneComponent> MoveTarget;

	//If true, use fixed point to update location; else, use MoveTarget.
	uint32 bFixedPoint:1;

	//If true, stop TickComponent
	uint32 bStop:1;		
};

UCustomMovementComponent::UCustomMovementComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	bStop = false;
}
void UCustomMovementComponent::SetTargetPosition(bool bFixedPoint, FVector PointLocation, USceneComponent* MoveTarget)
{
	bStop = false;
	this->MoveTarget = MoveTarget;
	this->bFixedPoint = bFixedPoint;
	this->PointLocation = PointLocation;
	InitComputeParams();
}

void UCustomMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	//Tick parent method first, in order to know whether UpdatedComponent is null.
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	CheckIsStop();
	if (bStop)
		return;
	FVector OutMoveDelta;
	FQuat OutNewRotation;
//計算Location和Rotation的變化
	ComputeMovement(DeltaTime, OutMoveDelta, OutNewRotation);
//更改UpdatedComponent坐標值的調用方法
	MoveUpdatedComponent(OutMoveDelta, OutNewRotation, true);	//whether change orientation?
//UMovementComponent中注釋說在更改Velocity變量后需要調用該方法改變UpdatedComponent的Velocity。看源代碼后發現應該是其他如物理Body等需要使用該值。
	UpdateComponentVelocity();
}

void UCustomMovementComponent::CheckIsStop()
{
	if (!UpdatedComponent)
	{
		bStop = true;
		return;
	}
	//whether target is exist
	if (!bFixedPoint && MoveTarget == nullptr)
	{
		bStop = true;
		return;
	}
	//reach the target location then stop
	float LocationDifference = (GetTargetPosition() - UpdatedComponent->GetComponentLocation()).Size();
	if (LocationDifference < SMALL_NUMBER)
	{
		bStop = true;
		return;
	}
}

FVector UCustomMovementComponent::GetTargetPosition()
{
	if (bFixedPoint)
		return PointLocation;
	check(MoveTarget != nullptr);
	return MoveTarget->GetComponentLocation();
}

FVector UCustomMovementComponent::GetHostPosition()
{
	check(UpdatedComponent);
	return UpdatedComponent->GetComponentLocation();
}


二、ULinearMovementComponent類

/**
 * class : ULinearMovementComponent
 * author : Jia Zhipeng
 * Move from current position to target in a constant velocity.
 */
UCLASS(ClassGroup = Movement, meta = (BlueprintSpawnableComponent), ShowCategories = (CustomMovement))
class CLIENT_API ULinearMovementComponent : public UCustomMovementComponent
{
	GENERATED_UCLASS_BODY()
public:
	//Linear speed.
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = CustomMovement)
	float Speed;
	virtual void ComputeMovement(float DeltaTime, FVector& OutMoveDelta, FQuat& OutNewRotation) override;
};
ULinearMovementComponent::ULinearMovementComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	Speed = 0;
}

void ULinearMovementComponent::ComputeMovement(float DeltaTime, FVector& OutMoveDelta, FQuat& OutNewRotation)
{
	FVector OldVelocity = Velocity;
	check(UpdatedComponent);
	Velocity = (GetTargetPosition() - UpdatedComponent->GetComponentLocation()).GetSafeNormal() * Speed;
	OutMoveDelta = Velocity * DeltaTime;
	OutNewRotation = OldVelocity.ToOrientationQuat();//use OldVelocity.Rotation().Quarternion() before 4.11 release.
}


三、使用

1.在藍圖中添加新創建的LinearMovementComponent組件,並設置組件的初始參數如速度。


2.在使用該藍圖創建Actor時,設置MovementComponent的Target,SpawnActor時Initial Velocity沒有用。


4.效果



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM