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

[UE4]自定义MovementComponent组件的更多相关文章

  1. SSIS自定义数据流组件开发(血路)

    由于特殊的原因(怎么特殊不解释),需要开发自定义数据流组件处理. 查了很多资料,用了不同的版本,发现各种各样的问题没有找到最终的解决方案. 遇到的问题如下: 用VS2015编译出来的插件,在SSDTB ...

  2. Android Studio开发基础之自定义View组件

    一般情况下,不直接使用View和ViewGroup类,而是使用使用其子类.例如要显示一张图片可以用View类的子类ImageView,开发自定义View组件可分为两个主要步骤: 一.创建一个继承自an ...

  3. 【转】Android学习基础自定义Checkbox组件

    原文网址:http://forum.maiziedu.com/thread-515-1-1.html heckbox组件是一种可同时选中多项的基础控件,即复选框,在android学习中,Checkbo ...

  4. Swift - 继承UIView实现自定义可视化组件(附记分牌样例)

    在iOS开发中,如果创建一个自定义的组件通常可以通过继承UIView来实现.下面以一个记分牌组件为例,演示了组件的创建和使用,以及枚举.协议等相关知识的学习. 效果图如下:    组件代码:Score ...

  5. vue2入坑随记(二) -- 自定义动态组件

    学习了Vue全家桶和一些UI基本够用了,但是用元素的方式使用组件还是不够灵活,比如我们需要通过js代码直接调用组件,而不是每次在页面上通过属性去控制组件的表现.下面讲一下如何定义动态组件. Vue.e ...

  6. 仿照wtform自定义Form组件

    仿照wtforms自定义Form组件 1.wtforms 点击查看源码分析及使用方法 2.自定义Form组件 #!usr/bin/env python # -*- coding:utf-8 -*- f ...

  7. Python自定义分页组件

    为了防止XSS即跨站脚本攻击,需要加上 safe # 路由 from django.conf.urls import url from django.contrib import admin from ...

  8. 自定义Form组件

    一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...

  9. vue里在自定义的组件上定义的事件

    事件分为原生事件和自定义事件. vue里在自定义的组件上定义的事件,都被认为是自定义事件,必须用$emit()来触发. 这也是子组件向父传值的原理. 如果想作为原生事件,需要在原生事件后面加上.nat ...

随机推荐

  1. iOS 上架被拒原因保存

    一.后台一直在获取用户的定位,需要给用户电池消耗提示 Your app uses the Location Background mode but does not include the requi ...

  2. js中的call与apply深入浅出

    首先明确call()与apply()最大的区别,除了名字不同以外,就是参数不一样,call的参数需要一一列出,apply的第二个及其以后的参数需要组成一个数组传进来. 这两个函数的调用者不是对象,而是 ...

  3. Activity之间传递参数(四)

    --------siwuxie095 获取Activity的返回参数 1.首先修改两个布局文件,都修改为 LinearLayout 布局, 添加orientation属性为:vertical. (1) ...

  4. 微信企业号-JS-SDK图像接口

    使用JS-SDK需要进行四步  主要是步骤二和步骤三,步骤二需要配置,步骤三具体使用相关接口,这里以使用图像接口为例 php页面代码主要用来完成步骤二,也就是配置接口 public function ...

  5. jQuery Mobile 表单基础

    jQuery Mobile 会自动为 HTML 表单添加优异的便于触控的外观. jQuery Mobile 表单结构 jQuery Mobile 使用 CSS 来设置 HTML 表单元素的样式,以使其 ...

  6. Gevent协程

    协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来 ...

  7. DBlink与同义词

    DBLink就是数据库链接,而同义词就已经具体到某个用户下的表了 原文链接:http://www.linuxidc.com/Linux/2013-01/77579.htm 这里所需要的信息: 从MM库 ...

  8. .net加密解密

    .net加密概述 .net加密编程模型 .net加密解密类

  9. winrar命令行加压解密

    加密的操作 Rar.exe a -P123 test1.rar test.txt 其中参数a表示添加文件或文件夹到压缩包中,-P参数表示是带密码的加密 Rar.exe e -P123 test1.ra ...

  10. c#一个泛型控制Textbox 和label 控件 泛型方法。

    class ControlHelper { public static void ShowOnTxtLbl<T>(T control, string mess) where T : Sys ...