自定义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. C#读写XML

    1.根据xml格式的string生成xml文件并保存到本地 /// <summary> /// 保存XML到磁盘 /// </summary> /// <param na ...

  2. Singleton in C++11 style

    #include <iostream> #include <memory> #include <mutex> class SingletonOld { static ...

  3. NGUI 屏幕自适应大屏与小屏(初始设定宽高为1280x720,能适应比其小或者更大的屏)

    具体细节可以参考另外一篇随笔! 以下提供的算法完成的事: 1.自适应1280x720分辨率以下的屏幕 2.自适应1280x720分辨率以上的屏幕 在我设定的要求内包括的分辨率大部分都测过了,背景图.全 ...

  4. lnode满,维护记录

    df  17% 正常 df -i 100% inode耗尽. | uniq -c 查出占用lnode最大的目录是 /var/spool/exim4/input 居然有15W多个小文件 exim4是邮件 ...

  5. 【摘】BPMN2.0-概要

    BPMN2.0-概要   原文地址:http://www.uml.org.cn/workclass/201206272.asp 作者:AliKevin2011,发布于2012-6-27   一.BPM ...

  6. winform 异步读取数据 小实例

    这几天对突然对委托事件,异步编程产生了兴趣,大量阅读前辈们的代码后自己总结了一下. 主要是实现 DataTable的导入导出,当然可以模拟从数据库读取大量数据,这可能需要一定的时间,然后 再把数据导入 ...

  7. Thinkpad 装 centos 7后发热量大处理

    原因:由于没有独立显卡驱动导致发热量大,禁用独立显卡去驱动即可. 步骤: 开机按 Fn+F1 进入BIOS. 选择 config 选项卡, 找到 Primary Display [SG] BIOS-- ...

  8. SpringMVC 400 Bad Request 问题

    摘要 SpringMVC 400 Bad Request 在提交表单时,发生400错误,并未进入save方法. @RequestMapping(value="/!save",met ...

  9. JAVA可移植性广泛应用

    一.JAVA作为一种编程语言:源代码可移植性 作为一种编程语言,JAVA提供了一种最简单同时也是人们最熟悉的可移植性–源代码移植.这意味着任意一个JAVA程序,不论它运行在何种CPU.操作系统或JAV ...

  10. javascript面向对象(1)

    主要内容: 在讲面向对象之前,我们先看一个示例: 类似这种情况大家都能够理解,但是,如果把代码改动一下,请再看一下: 为什么会这样? 如果把代码再改一下看看,如把变量改成b,则直接报错 JavaScr ...