原创内容,转载请注明出处。
创建一个基于Actor的蓝图,可以看到左侧可以覆盖一些方法,针对这些方法在代码层面做一个介绍。
如下图,写这篇文章的目的其实希望大家知道引擎原生提供的一些方法,能够更快的写逻辑。
防止各位同仁自造轮子。
Actor事件列表
1.Actor生命周期
1>BeginPlay
刚开始Spawn出来后调用的
源码分析链接:
2>Tick
每帧执行
3>EndPlay
被销毁之前执行,下面是EndPlay的原因枚举。我在截图的Print中也有介绍
/** Specifies why an actor is being deleted/removed from a level */
UENUM(BlueprintType)
namespace EEndPlayReason
{
enum Type
{
/** When the Actor or Component is explicitly destroyed. */
Destroyed,
/** When the world is being unloaded for a level transition. */
LevelTransition,
/** When the world is being unloaded because PIE is ending. */
EndPlayInEditor,
/** When the level it is a member of is streamed out. */
RemovedFromWorld,
/** When the application is being exited. */
Quit,
};
}
4>Destroyed
被销毁之后执行
从Actor的生命周期开始到结束,可以发现顺序为
1>BeginPlay
2>Tick(一直执行, 为了方便截图,我在Tick后加了一个Doonce所以打印了一次)
3>EndPlay(包含原因)
4>Destroy(如果是被销毁的话)
2.Actor交互
1>ActorOnClicked
Actor被点击
描述:
1>Actor被点击。
当有Actor接受到鼠标点击事件去做什么事情的需求,可以用这个事件
如何使用举例:
1>Actor加一个带碰撞的物体, 比如Mesh,并确保其具有Block,如果是Overlap/NoCollision不行, 如图。
有了这个可以做很多有意思的事情,可以避免我们用LineTrace去写很多乱七八糟的逻辑来实现这个功能
2>GetPlayerController()->bShowMouseCursor = true; (只是示意,不能通过编译,具体请看下图蓝图写法)
3>GetPlayerController()->bEnableClickEvents= true;(只是示意,不能通过编译,具体请看下图蓝图写法)
效果如下图
Actor点击之后的调用堆栈,如下图
其实最底层就是windows的消息机制,再到UE4 ……再到组件的ActorOnClick,
然后组件的OnOwnerActor也会也就是AActor类会接收到这个ActorOnClick了,其他下面几个方法也是类似的调用机制
2>ActorOnReleased
Actor被点击后松开
描述:
1>Actor被点击后松开。
和ActorOnReleased对应,当有Actor接受到鼠标点击事件并再松开鼠标去做什么事情的需求,可以用这个事件
如何使用举例:
1>Actor加一个带碰撞的物体, 比如Mesh,并确保其具有Block,如果是Overlap/NoCollision不行, 如1中的图。
有了这个可以做很多有意思的事情,可以避免我们用LineTrace去写很多乱七八糟的逻辑来实现这个功能
2>GetPlayerController()->bShowMouseCursor = true; (只是示意,不能通过编译,具体请看上图蓝图写法)
3>GetPlayerController()->bEnableClickEvents= true;(只是示意,不能通过编译,具体请看上图蓝图写法)
3>ActorBeginOverlap
与某个Actor发生了重叠事件
描述:
1>与某个Actor发生了重叠事件
当有某个物体和Actor发生重叠事件的时候要做事情的需求,可以用这个事件
如何使用举例:
1>确保我们的物体,比如Mesh,确保其具有Ovelap的功能,如下图。
PS:补充如果想让Mesh又能重叠又能通过鼠标触发,按照下面设置就可以
效果如下图
4>ActorEndOverlap
与某个Actor发生了重叠离开事件
描述:
1>与某个Actor发生了重叠离开事件
和ActorBeginOverlap对应,当有某个物体和Actor发生重叠事件并离开重叠区域的时候要做事情的需求,可以用这个事件
如何使用举例:
1>确保我们的物体,比如Mesh,确保其具有Ovelap的功能,请看3中的图。
5>ActorBeginCursorOver
Actor被Hover
描述:
1>Actor被Hover,就理解UMG上的你的UButton被Hover了一个意思
当有鼠标滑动到某个Actor上的时候做什么事情的需求的时候,可以用这个事件
如何使用举例:
1>Actor加一个带碰撞的物体, 比如Mesh,并确保其具有Block就可以,如果是Overlap/NoCollision不行, 如1中的图就可以, 也可以看下图。
**主要是要确保Collision Responses中的TraceResponses属性为Block就可以**
有了这个可以做很多有意思的事情,可以避免我们用LineTrace去写很多乱七八糟的逻辑来实现这个功能
2>GetPlayerController()->bShowMouseCursor = true; (只是示意,不能通过编译,具体请看上图蓝图写法)
3>GetPlayerController()->bEnableMouseOverEvents= true;(只是示意,不能通过编译,具体请看上图蓝图写法)
4>不设置bEnableClickEvents也是可以触发Over和EndOver的。
效果图如下
6>ActorEndCursorOver
Actor被UnHover
描述:
1>Actor被UnHover,就理解UMG上的你的UButton被UnHover了一个意思
和ActorBeginCursorOver相对应,当有鼠标滑动到某个Actor上的时候再离开做什么事情的需求的时候,可以用这个事件
如何使用举例:
1>Actor加一个带碰撞的物体, 比如Mesh,并确保其具有Block就可以,如果是Overlap/NoCollision不行, 如1中的图就可以, 也可以看5中的ActorBeginCursorOver图。
**主要是要确保Collision Responses中的TraceResponses属性为Block就可以**
有了这个可以做很多有意思的事情,可以避免我们用LineTrace去写很多乱七八糟的逻辑来实现这个功能
2>GetPlayerController()->bShowMouseCursor = true; (只是示意,不能通过编译,具体请看上图蓝图写法)
3>GetPlayerController()->bEnableMouseOverEvents= true;(只是示意,不能通过编译,具体请看上图蓝图写法)
4>不设置bEnableClickEvents也是可以触发Over和EndOver的。
3.视角相关的两个方法OnBecomeViewTarget/OnEndViewTarget
1>OnBecomeViewTarget
视角为这个Actor
描述:当视角为这个Actor的时候会打印该Log
如实使用举例:
1>按1键存储现在的视图Actor,并以DemoActor为新视角,如下图PlayerController->SetViewTargetWithBlend()
2>还有一种通过命令行的触发方式,但是我没找到怎么返回的命令. ViewActor <ctorDisplayName>
现象:如下图
大家有知道ViewActor 对应命令的可以评论告诉我谢谢。
1>OnEndViewTarget
视角退出这个Actor
描述:当视角退出这个Actor的时候会打印该Log
如实使用举例:
1>按2键返回新的视角,如OnBecomeViewTarget图
4.重置OnReset()介绍
描述:当初始化关卡时候,会调用
5.伤害相关函数 Hit/AnyDamage/PointDamage/RadialDamage
1>Hit/OnActorHit
1>**Hit**事件蓝图中重写的
1)确保其Mesh具有Block信息,也就是说你的Mesh一定要有碰撞或者具有其他可提供碰撞的物体(比如BoxComponent等)
3)假如Mesh开启simulate physics的话,当你的角色碰撞你的Mesh的时候会发现一个有趣的现象,
就是你可以推着Mesh移动。并且在OnHit的返回参数里面Self Moved会变成True
2>OnActorHit可以对单个的actor进行event添加,在场景编辑器器中右键AddEvents->OnActorHit
如果你想触发OnActor事件的话, 必须要满足下面的条件
(1)Simulation Generates Hit Events 必须开启
(2)两个Mesh之间必须有一个Simulate Physics为true
(3)确保Mesh是有碰撞信息的,不能为NoCollision.二者必须有一个是具有Block,另外一个可以为Overlap。为Overlap的不会产生OnActrHit, Block的Mesh会产生。
(4)Mesh不能用复杂碰撞作为碰撞信息,如上图。两个Mesh都不允许。
我用Character测试的时候,发现比较特殊。就是角色不用打开上面的俩条件,也会触发OnActorHit。
2>AnyDamage
调用上述几种伤害造成的方法都会打印即可产生伤害, BaseDamage需要>0, 才会触发
ApplyDamage的使用方法
1>参数:AActor* DamagedActor:DamagedActor哪个Actor被作用伤害
2>参数:float BaseDamage:BaseDamage伤害数值
3>参数:AController* EventInstigator:负责造成这种伤害的控制器(例如,玩家谁开枪)
4>参数:AActor* DamageCauser:真正造成伤害的演员(例如,爆炸的手榴弹)
5>参数:TSubclassOf<class UDamageType> DamageTypeClass:描述所造成的损害的类。
你可以继承自UDamageType类创建一个蓝图或者C++类。作为参数传递进去。
DamageType旨在定义和描述一种特殊形式的损害,并提供一个途径。用于定制对各种来源的损害的响应。
例如,游戏可以使用DamageType_Fire来点燃受损的演员。 DamageTypes永远不会被实例化,应该被当作静态代码的不可变数据持有者功能。它们永远不应该是有状态的。
6>返回值:最终对DamagedActor造成的实际伤害
3>PointDamage/点伤害
如何触发?如下图
ApplyPointDamage的使用方法
点伤害参数介绍
1>参数:AActor* DamagedActor:DamagedActor哪个Actor被作用伤害
2>参数:float BaseDamage:BaseDamage伤害数值
3>参数:const FVector& HitFromDirection:方向命中来自哪?
4>参数:const FHitResult& HitInfo:描述命中的碰撞或跟踪结果,可以搭配LineTrace使用
5>参数:AController* EventInstigator:负责造成这种伤害的控制器(例如,玩家谁开枪)
6>参数:AActor* DamageCauser:真正造成伤害的演员(例如,爆炸的手榴弹)
7>参数:TSubclassOf<class UDamageType> DamageTypeClass:描述所造成的损害的类。
你可以继承自UDamageType类创建一个蓝图或者C++类。作为参数传递进去。
DamageType旨在定义和描述一种特殊形式的损害,并提供一个途径。用于定制对各种来源的损害的响应。
例如,游戏可以使用DamageType_Fire来点燃受损的演员。 DamageTypes永远不会被实例化,应该被当作静态代码的不可变数据持有者功能。它们永远不应该是有状态的。
6>返回值:最终对DamagedActor造成的实际伤害
4>RadialDamage
ApplyRadialDamage的使用方法(没有衰减)
半径伤害 不带有衰减
1>参数:float BaseDamage:BaseDamage伤害数值
2>参数:const FVector& Origin:伤害起源的中心点
3>参数:float DamageRadius:从起源算起的伤害半径,画一个圆
4>参数:TSubclassOf<class UDamageType> DamageTypeClass:描述所造成的损害的类。
你可以继承自UDamageType类创建一个蓝图或者C++类。作为参数传递进去。
DamageType旨在定义和描述一种特殊形式的损害,并提供一个途径。用于定制对各种来源的损害的响应。
例如,游戏可以使用DamageType_Fire来点燃受损的演员。 DamageTypes永远不会被实例化,应该被当作静态代码的不可变数据持有者功能。它们永远不应该是有状态的。
5>参数:const TArray<AActor*>& IgnoreActors:忽略的Actors
6>参数:AActor* DamageCauser = NULL:真正造成伤害的Actor(例如,爆炸的手榴弹)。这个actor不会被损坏,也不会阻挡损坏。
7>参数:AController* InstigatedByController = NULL:造成这种伤害的控制器(例如,投掷手榴弹的玩家)
8>参数:bool bDoFullDamage = false:如果为真,伤害不缩放从原点的距离
9>参数:ECollisionChannel DamagePreventionChannel = ECC_Visibility:如果在源头和受害者之间有什么东西阻塞了该通道上的跟踪,损害将不会应用到受害者
10>返回值:如果至少有一个物体收到了伤害,则返回true,反之false;
ApplyRadialDamageWithFalloff的使用方法(有衰减)
具有衰减的半径伤害,位于中心的伤害越大,半径以外的伤害越小。
1>参数:float BaseDamage:BaseDamage伤害数值
2>参数:float MinimumDamage:最小伤害数值
3>参数:const FVector& Origin:伤害起源的中心点
4>参数:float DamageInnerRadius:从起源算起的伤害半径,画一个圆,没有衰减的伤害区域
5>参数:float DamageOuterRadius:从起源算起的伤害半径,画一个圆,有衰减的伤害区域
6>参数:float DamageFalloff:衰减指数的损害从DamageInnerRadius到DamageOuterRadius。让DamageOuterRadius>DamageInnerRadius就能看到效果了,这俩数字的中间这个范围会根据这个系数衰减。
7>参数:TSubclassOf<class UDamageType> DamageTypeClass:描述所造成的损害的类。
你可以继承自UDamageType类创建一个蓝图或者C++类。作为参数传递进去。
DamageType旨在定义和描述一种特殊形式的损害,并提供一个途径。用于定制对各种来源的损害的响应。
例如,游戏可以使用DamageType_Fire来点燃受损的演员。 DamageTypes永远不会被实例化,应该被当作静态代码的不可变数据持有者功能。它们永远不应该是有状态的。
5>参数:const TArray<AActor*>& IgnoreActors:忽略的Actors
6>参数:AActor* DamageCauser = NULL:真正造成伤害的Actor(例如,爆炸的手榴弹)。这个actor不会被损坏,也不会阻挡损坏。
7>参数:AController* InstigatedByController = NULL:造成这种伤害的控制器(例如,投掷手榴弹的玩家)
8>参数:bool bDoFullDamage = false:如果为真,伤害不缩放从原点的距离
9>参数:ECollisionChannel DamagePreventionChannel = ECC_Visibility:如果在源头和受害者之间有什么东西阻塞了该通道上的跟踪,损害将不会应用到受害者
10>返回值:如果至少有一个物体收到了伤害,则返回true,反之false;
6.Actor Touch相关函数
触屏相关函数,可用在windows触屏,mobile触屏上。
前提需要开启一下PlayerController上面的bEnableTouchEvents和bEnableTouchOverEvents
1>BeginInputTouch
描述:触屏点击中了actor。
触发条件:需要开启PlayerController上面的bEnableTouchEvents,bEnableTouchEvents=true
2>EndInputTouch
描述:触屏点击中了actor,并且在actor焦点上离开。
触发条件:需要开启PlayerController上面的bEnableTouchEvents,bEnableTouchEvents=true
3>TouchEnter
描述:触屏的时候滑动的时候接触到了这个actor
触发条件:需要开启PlayerController上面的bEnableTouchOverEvents,bEnableTouchOverEvents=true
4>TouchLeave
描述:触屏的时候滑动的时候接触到了这个actor,并且离开
触发条件:需要开启PlayerController上面的bEnableTouchOverEvents,bEnableTouchOverEvents=true
现象如下图
文章持续完善中,有问题请大家指正。
谢谢!创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 (๑◕ܫ←๑)