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