[UE4]自定义MovementComponent组件


转自:http://www.cnblogs.com/corgi/p/5405451.html

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

优质内容筛选与推荐>>
1、谈谈我对JS闭包的理解
2、D - 一二三
3、awk
4、.NET 控件的认识。
5、品牌之品牌效应


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn