UE的Gameplay框架(二) —— Actor和Component

2024-08-31 19:28

本文主要是介绍UE的Gameplay框架(二) —— Actor和Component,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这篇博客聊一下UE的Gameplay框架很重要的一部分 Actor 和 Component


文章目录

  • Actor
  • Component
    • SceneComponent
    • 注册组件
  • Actor生命周期
  • 参考资料


Actor

如UE文档所述,所有可以放入关卡的对象都是 Actor,比如摄像机、静态网格体、玩家起始位置。Actor 支持三维变换,例如平移、旋转和缩放。在 C++ 中,AActor是所有Actor的基类。

但这里的变换(位置、旋转和缩放)数据并不是直接作为 Actor 的属性保存起来,而是通过组件(准确的说是场景组件)给Actor提供了三维变换的功能。Actor 本身只提供了一些基础的属性和功能(比如网络同步、Tick、创建销毁、生命周期)的小baby,而组件则是让Actor成为有各种技能的成年人(移动、感知、渲染、物理)。

关于组件的内容放到下一节细说,下面简单介绍下 Actor 本身。

  • 创建 Actor:可以使用泛型 SpawnActor() 函数或它的一个特殊模板化版本进行操作,可以看到用模板的方法内部也是调用了上面传入UClass版本的 SpawnActor()
	/*** Spawn Actors with given transform and SpawnParameters* * @param	Class					Class to Spawn* @param	Location				Location To Spawn* @param	Rotation				Rotation To Spawn* @param	SpawnParameters			Spawn Parameters** @return	Actor that just spawned*/AActor* SpawnActor( UClass* InClass, FVector const* Location=NULL, FRotator const* Rotation=NULL, const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() );/** Templated version of SpawnActor that allows you to specify a class type via the 		template type */template< class T >T* SpawnActor( const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() ){return CastChecked<T>(SpawnActor(T::StaticClass(), NULL, NULL, SpawnParameters),ECastCheckedType::NullAllowed);}
  • Ticking:Ticking赋予了Actor生命,以规则间隔(每帧/设定的时间间隔)在一个actor或组件上运行一段代码或蓝图脚本。我们想要对于子类Actor每帧都要执行一定的操作,就可以重写 AActor 的 Tick。
    Ticking的高级用法就涉及到Tick组和Tick依赖关系了,这里不展开(博主也没完全掌握),可以看下官方文档

  • 网络同步:属性值和函数调用均可被复制,以便对客户端上游戏的状态进行完整控制,这里涉及到网络同步了,可以看下博主之前写过的有关网络同步的内容。

  • 销毁Actor:Actor通常不会被垃圾回收,因为场景对象保存一个Actor引用的列表。调用 Destroy() 即可显式销毁 Actor。这会将其从关卡中移除,并将其标记为"代销毁",这说明其在下次垃圾回收中被清理之前都将存在(挖个坑,后续好好研究下UE的内存管理和GC)。
    主要就是调用 World 里的 DestroyActor,内部是:

    1. 从World里的Actor列表里移除
    2. 将Attach该Actor的子Actor取消Attach(也就是不会销毁子Actor)
    3. 如果该Actor有Attach的父Actor,也将其从父Actor取消Attach
    4. 如果Actor有Owner,通知Owner其失去了一个孩子
    5. 通知NetDriver这个Actor要被销毁了
    6. Unregister该Actor所有的组件,取消他们的物理和渲染
    7. 标记Actor和其所有组件为PendingKill
    8. Unregister Actor和其组件的 Tick 函数
bool AActor::Destroy( bool bNetForce, bool bShouldModifyLevel )
{// It's already pending kill or in DestroyActor(), no need to beat the corpseif (!IsPendingKillPending()){UWorld* World = GetWorld();if (World){World->DestroyActor( this, bNetForce, bShouldModifyLevel );}else{UE_LOG(LogSpawn, Warning, TEXT("Destroying %s, which doesn't have a valid world pointer"), *GetPathName());}}return IsPendingKillPending();
}

Component


Component 给Actor提供各种能力,Actor可以看作是Components的容器。按UE官方文档所述,组件可以按照使用场景分为如下几个主要的类(这里也是存在明显的继承关系,比如Primitive组件自然可以有自己的三维变换,那么继承自Scene组件是很直观的):

  • Actor组件:(类 UActorComponent) 最适用于抽象行为,例如移动、物品栏或属性管理,以及其它非物理概念。Actor组件没有变换,即它们在场景中不存在任何物理位置或旋转,除了 Scene 组件继承自它,其实还有好多没有物理概念没有三维变换的组件继承自它,比如UMovementComponentAIComponent
  • 场景组件:(类 USceneComponent) 支持基于位置的行为,这类行为不需要几何表示。这包括弹簧臂、摄像机、物理力和约束(但不包括物理对象),甚至音频(有位置概念才能根据远近有不同的音量大小)。
  • Primitive组件:(类 UPrimitiveComponent) 是拥有几何表示的场景组件,通常用于渲染视觉元素或与物理对象发生碰撞或重叠。这包括静态或骨架网格体、Sprite或公告板、粒子系统以及盒体、胶囊体和球体碰撞体积。

SceneComponent

除了提供三维变换,SceneComponent还提供了在这一层的嵌套,所以其实对于Actor来说,Actor之间的嵌套也是在SceneComponent这一层实现的,我感觉这里的嵌套更多是为了实现相对于父节点的三维变换。

下面可以看到 AttachToActor 也是转发到 SceneComponent 这一层处理的

void AActor::AttachToActor(AActor* ParentActor, const FAttachmentTransformRules& AttachmentRules, FName SocketName)
{if (RootComponent && ParentActor){USceneComponent* ParentDefaultAttachComponent = ParentActor->GetDefaultAttachComponent();if (ParentDefaultAttachComponent){RootComponent->AttachToComponent(ParentDefaultAttachComponent, AttachmentRules, SocketName);}}
}
void AActor::AttachToComponent(USceneComponent* Parent, const FAttachmentTransformRules& AttachmentRules, FName SocketName)
{if (RootComponent && Parent){RootComponent->AttachToComponent(Parent, AttachmentRules, SocketName);}
}

注册组件

组件还有一个注册的概念,为了让Actor组件能够逐帧更新并影响场景,引擎必须注册这类组件。

如果在Actor产生过程中,作为Actor子对象自动创建了组件,则这类组件会自动注册。游戏期间创建的组件,需要我们手动使用 RegisterComponent 进行注册。

在注册组件的过程中,引擎会将组件与场景关联起来,让其可用于逐帧更新,并会调用如下 UActorComponent 函数:

  • OnRegister 在注册组件时,可以覆写此函数来添加代码
  • CreateRenderState 初始化组件的渲染状态
  • OnCreatePhysicsState 初始化组件的物理状态

与注册对应,我们想从更新、模拟和渲染过程中移除Actor组件,可以使用 UnregisterComponent 函数将其取消注册。

在组件取消注册时,将调用下面的 UActorComponent 函数:

  • OnUnregister 在取消注册组件时,可以覆写此函数来添加代码
  • DestroyRenderState 取消初始化组件的渲染状态
  • OnDestroyPhysicsState 取消初始化组件的物理状态

Actor生命周期


不管是LoadMapAddToWorld 这种从磁盘里加载Actors的方式,还是运行时 spawn 生成Actors,都会经历 PreInitialize Components -> InitializeComponents -> PostInitializeComponents -> BeginPlay 之后 Actors 就会开始 Ticking 了,如果游戏结束了或者Actor设定的生命周期时长到了或者被Destroy了或者发生了关卡迁移等,会触发 EndPlay 也代表Actor的生命周期要结束了,后续也会被标记为 PendingKill 然后从ULevel中的Actors array移除,等待被垃圾回收。


参考资料

《InsideUE4》GamePlay架构(一)Actor和Component
组件
Actors

这篇关于UE的Gameplay框架(二) —— Actor和Component的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124785

相关文章

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

Spring Framework系统框架

序号表示的是学习顺序 IoC(控制反转)/DI(依赖注入): ioc:思想上是控制反转,spring提供了一个容器,称为IOC容器,用它来充当IOC思想中的外部。 我的理解就是spring把这些对象集中管理,放在容器中,这个容器就叫Ioc这些对象统称为Bean 用对象的时候不用new,直接外部提供(bean) 当外部的对象有关系的时候,IOC给它俩绑好(DI) DI和IO

Sentinel 高可用流量管理框架

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应

利用Django框架快速构建Web应用:从零到上线

随着互联网的发展,Web应用的需求日益增长,而Django作为一个高级的Python Web框架,以其强大的功能和灵活的架构,成为了众多开发者的选择。本文将指导你如何从零开始使用Django框架构建一个简单的Web应用,并将其部署到线上,让世界看到你的作品。 Django简介 Django是由Adrian Holovaty和Simon Willison于2005年开发的一个开源框架,旨在简

Yii框架relations的使用

通过在 relations() 中声明这些相关对象,我们就可以利用强大的 Relational ActiveRecord (RAR) 功能来访问资讯的相关对象,例如它的作者和评论。不需要自己写复杂的 SQL JOIN 语句。 前提条件 在组织数据库时,需要使用主键与外键约束才能使用ActiveReocrd的关系操作; 场景 申明关系 两张表之间的关系无非三种:一对多;一对一;多对多; 在

laravel框架实现redis分布式集群原理

在app/config/database.php中配置如下: 'redis' => array('cluster' => true,'default' => array('host' => '172.21.107.247','port' => 6379,),'redis1' => array('host' => '172.21.107.248','port' => 6379,),) 其中cl