• [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.效果


  • 相关阅读:
    CCNP-----企业网三层架构——BCMSN
    Redis 的 GEO 特性将在 Redis 3.2 版本释出
    CentOS6.5上源码安装MongoDB3.2.1
    beanstalkd
    php7---redis
    MongoDB学习笔记(入门)
    MongoDB学习笔记(数据操作)
    MongoDB学习笔记(索引)
    CentOS 安装MongoDB
    爬虫----Web_WeChat
  • 原文地址:https://www.cnblogs.com/corgi/p/5405451.html
Copyright © 2020-2023  润新知