自定义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.效果


posted on 2016-03-03 14:31  Corgi  阅读(4261)  评论(0编辑  收藏  举报