Ue4 Actor同步与序列化

Ue4 Actor同步与序列化

主要讨论的是服务器Actor同步到客户端的过程,和序列化的过程。

1. 基本概念

服务器在NetDiver的TickFlush里面,每一帧都会去执行ServerReplicateActors来同步Actor的相关内容,大多数 actor 复制操作都发生在 UNetDriver::ServerReplicateActors 内。在这里,服务器将收集所有被认定与各个客户端相关的 actor,并发送那些自上次(已连接的)客户端更新后出现变化的所有属性。

UChannel::ReplicateActor 将负责把 actor 及其所有组件复制到连接中。其大致流程如下:

  • 确定这是不是此 actor 通道(channel)打开后的第一次更新
    • 如果是,则将所需的特定信息(初始方位、旋转等)序列化
  • 确定该连接是否拥有这个 actor
    • 如果没有,而且这个 actor 的角色是 ROLE_AutonomousProxy,则降级为 ROLE_SimulatedProxy
  • 复制这个 actor 中已更改的属性
  • 复制每个组件中已更改的属性
  • 对于已经删除的组件,发送专门的删除命令

总之,大体上Actor同步的逻辑就是在TickFlush里面去执行ServerReplicateActors,然后进行前面说的那些处理。最后对每个Actor执行ActorChannel::ReplicateActor将Actor本身的信息,子对象的信息,属性信息封装到Bunch并进一步封装到发送缓存中,最后通过Socket发送出去。

2. Actor同步与序列化的基本数据结构

  • FObjectReplicator
    属性同步的执行器,每个Actorchannel对应一个FObjectReplicator,每一个FObjectReplicator对应一个对象实例。设置ActorChannel通道的时候会创建出来。

  • FRepState
    针对每个连接同步的历史数据,记录同步前用于比较的Object对象信息,存在于FObjectReplicator里面。

  • FRepLayOut
    同步的属性布局表,记录所有当前类需要同步的属性,每个类或者RPC函数有一个。

  • FRepChangedPropertyTracker
    属性变化轨迹记录,一般在同步Actor前创建,Actor销毁的时候删掉。

  • FReplicationChangelistMgr
    存放当前的Object对象,保存属性的变化历史记录

  • NetworkGUID

    在UObject类同步中标记作用。

  • FOutBunch

    序列化主要的数据结构。

  • SendBunch

    由Connection拥有,最后同步封装到的bunch中。

    在这里插入图片描述

    一个Actorchannel类其实对应着一个FObjectReplicator,属于属性同步最重要的类。

    通俗点而言,FObjectReplicator是一个属性同步的执行者,FRepLayout是参照表,FRepState是追踪者,FReplicationChangelistMgr是实际数据存放者,记录属性的变化过程。


3. Actor同步初始化

3.1 初始化前的准备

当Actor同步时如果发现当前的Actor没有对应的通道,就会给其创建一个通道并执行SetChannelActor。这个SetChannelActor所做的工作就是属性同步的关键所在。

在SetChannelActor主要负责做了几件事。

  1. 构建了FObjectReplicator;
  2. 构建了FRepLayout;
  3. 构建FRepState;
  4. 构建FReplicationChangelistMgr;
  5. 为当前Actor创建NetWorkGUID。

在这里插入图片描述

或者也可以参考这个图

参考图片

3.2 SerializeNewActor


// in  UActorChannel::ReplicateActor() DataChannel.cpp 2626

// ----------------------------------------------------------
// If initial, send init data.
// ----------------------------------------------------------
if( RepFlags.bNetInitial && OpenedLocally )
{
	Connection->PackageMap->SerializeNewActor(Bunch, this, Actor);
	WroteSomethingImportant = true;
	Actor->OnSerializeNewActor(Bunch);
}

序列化一个新的Actor的主要过程如下:

在这里插入图片描述

序列化出一个新的Actor分两种,一种是静态Actor,一种是动态Actor。

何为静态,何为动态呢?

bool FNetGUIDCache::IsDynamicObject( const UObject* Object )
{
	check( Object != NULL );
	check( Object->IsSupportedForNetworking() );

	// Any non net addressable object is dynamic
	return !Object->IsFullNameStableForNetworking();
}

/** IsNameStableForNetworking means an object can be referred to its path name (relative to outer) over the network */
bool UObject::IsNameStableForNetworking() const
{
	return HasAnyFlags(RF_WasLoaded | RF_DefaultSubObject) || IsNative() || IsDefaultSubobject();
}

/** IsFullNameStableForNetworking means an object can be referred to its full path name over the network */
bool UObject::IsFullNameStableForNetworking() const
{
	if ( GetOuter() != NULL && !GetOuter()->IsNameStableForNetworking() )
	{
		return false;	// If any outer isn't stable, we can't consider the full name stable
	}

	return IsNameStableForNetworking();
}

通过代码来看,如果该同步的Actor是HasAnyFlags(RF_WasLoaded | RF_DefaultSubObject) || IsNative() || IsDefaultSubobject(),也就是说如果Actor是已经加载到地图了,或者是CDO对象,或者是原生的对象,则它是静态的对象。

  1. 如果是静态的对象,序列化的过程,则不需要序列化三维信息,但是需要序列化其OuterGUIDPathName。因为客户端需要找到该UObject绑定NetGUID。(因此就通过其Outer和自身的PathName来找到该UObject)。

  2. 如果是动态的对象的话,则不需要其Outer的GUID和路径。而是通过一个Archetype并通过序列化一些基本的三维信息和速度信息来在客户端Spawn一个Archetype,并赋予它一些三维信息和速度,使它和原来的Actor看起来一模一样。

3.3 Actor属性同步

Actor的同步主要实现在UActorChannel::ReplicateProperties函数中。

在这里插入图片描述

首先在Update函数中更新StaticBuff,并且与UObject进行比较,判断是否发生变化,如果发生变化,添加进Changed列表中。在ReplicateProperties的时候根据Changed列表来对属性进行同步,如果Changed列表为空的话,则不同步,返回false。

4. 封装到SendBuff中

封装FOutBunch的过程中主要在UActorChannel::SendBunch中实现。

在这里插入图片描述

SendBunch主要发送的Bunch有两种。

一种是在AppendExportBunches中获取到ExportBunches(这个Bunch中存储的内容是前面序列化该UObjectGUIDPathName)。

另一种则是在SerializeNewActor中同步过来的ActorGUID和三维信息和ReplicatedProperties中属性同步的信息还有ReplicatedSubobject子组件的信息。

两种最后存储在OutgoingBunches中,经过PreBunch处理后,再SendRawBunch,存储到SendBuffer中。

PlayerController为例:

在这里插入图片描述

AppendExportBunches中所存储的内容的大小为1369bits。存储的内容主要是GUID和PathName。

在这里插入图片描述

而这部分存储的内容就是ActorGUID,三维信息,还有属性同步组件同步的信息。

在这里插入图片描述

以PlayerController为例,第一部分存储的内容主要是。

在这里插入图片描述

思考: 上述第一部分序列化,最主要的带宽消耗来自于PathName,虽然是在Actor初始化的时候才需要同步这部分内容,但是如果需要大量SpawnActor的时候,是否会影响到同步的效果?并且,因为与同步路径的长度相关,尤其是UMapPackageName是每一个Actor初始化同步的时候都需要序列化。如果减少路径的命名长度是否会优化呢?

Ue4.20

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: b'ue4 actor component'是Unreal Engine 4中的一个组件,可以附加到Actor上,并添加自定义功能,例如碰撞检测、动画控制和游戏逻辑。这样,多个Actor可以共享同一个组件,从而简化代码和提高效率。 ### 回答2: UE4 Actor Component是一个非常重要的功能模块,它可以让我们为UE4引擎中的游戏角色添加自定义的行为和功能,而不需要修改原有的游戏代码。使用Actor Component,我们可以将游戏角色所拥有的行为和功能拆分成一个个独立的模块,并可以独立开发、测试、优化和修改,从而提高游戏的可维护性和开发效率。以下是Actor Component的主要特性: 1. 重用性:可以将Actor Component应用到不同的游戏角色中,从而将相同的行为和功能重用。 2. 灵活性:可以根据需要添加或移除Actor Component,从而增强游戏角色的行为和功能。 3. 可拆分性:可以将复杂的游戏角色拆分成更小、更简单的组件,从而降低代码复杂度和维护成本。 4. 可扩展性:通过继承Actor Component类,我们可以创建自己的定制组件,从而增强游戏的定制化程度。 使用Actor Component开发游戏可以大大简化代码开发过程,加快开发时间,减少错误和bug,提高代码的可读性和可维护性。Actor Component是UE4引擎的一个重要特性,也是开发高质量游戏的不可或缺的工具之一。 ### 回答3: UE4(Unreal Engine 4)是一款功能强大的游戏开发引擎,其中的Actor和Component模块是构建游戏对象的重要组成部分之一。Actor是在游戏场景中的一个物体,而Component是Actor对象的一部分,经常用于添加特定功能和属性。UE4Actor Component能够帮助游戏开发人员在游戏中实现更多的交互和动态效果。 UE4 Actor Component的设计思路是将不同的组件将Actor划分为不同的模块,使其更加简单易用和灵活。通过UE4 Actor Component,开发人员可以根据自己的需求将多个组件组合在一个Actor中,从而实现更复杂的游戏特效等功能。 UE4 Actor Component提供了很多常见的组件,如动画组件、碰撞器组件、模型组件、声音组件等,以及多种自定义组件。其中,动画组件是游戏开发中最常用的组件之一,可以使游戏中的角色动作更加真实,使动画更加流畅。碰撞器组件则可以增加游戏中的碰撞检测效果,模型组件可以快速地在场景中添加物体,声音组件则可以为游戏增加更多音效。 UE4 Actor Component的另一个优势是可以通过连接多个组件来创建更为复杂的组件。通过将一个组件附加到另一个组件上,可以将两个组件的功能融合在一起,从而实现更多不同的游戏特效。例如,一个具有紫外线视觉效果的球体可以通过将光线源附加到它的子组件上来实现,这样就可以使球体在场景中发出紫外线光线。 总之,UE4中的Actor Component是游戏开发中非常重要的一部分,它能够提供丰富多彩的特效和功能,游戏开发人员可以通过组合不同的组件来实现自己的游戏开发需求。因此,学习UE4 Actor Component对于游戏开发人员来说是非常有必要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值