Coder Social home page Coder Social logo

metaworking / channeld-ue-plugin Goto Github PK

View Code? Open in Web Editor NEW
121.0 5.0 28.0 42.44 MB

Enables distributed simulation with Unreal Engine's dedicated servers. 为虚幻引擎专用服务器提供分布式模拟能力的开源插件.

License: Apache License 2.0

Batchfile 0.83% C# 0.63% C++ 97.67% C 0.87%
dedicated-server plugin relay-server replication seamless unreal unreal-engine

channeld-ue-plugin's People

Contributors

augkit avatar indiest avatar laughxing avatar lee97 avatar meth-yzh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

channeld-ue-plugin's Issues

Implement the Entity Channel and the New Spatial Channel

Corresponding to channeld's Entity Channel feature.

Things to implement in ChanneldUE:

  • Use the new data structure for the spatial channels;
  • Codegen for the entity channel data;
  • New spawn/destory logic;
  • New handover logic;
  • Interest management for the entities;
  • Well-Known Object (a.k.a. AlwaysRelevant)
  • EntityAOI

Question about struct FCopy_XXX generation

Hi, not sure if I should put this in discussion or here.
I have question about code generation for struct FCopy_XXXXX.
What is the purpose of making FCopy instead of using the original structure?
I believe the generation is also problematic since the code generation relies on Reflection system, and UE's reflection system will only recognize the UPROPERTY member variables.
For example, this is one of the struct generated for Gameplay Ability System.


struct FCopy_FGameplayAbilitySpec
{
	FCopy_FGameplayAbilitySpecHandle Handle;
TObjectPtr<UGameplayAbility> Ability;
int32 Level;
int32 InputID;
uint8 ActiveCount;
bool InputPressed;
bool RemoveAfterActivation;
bool PendingRemove;
bool bActivateOnce;
FCopy_FGameplayAbilityActivationInfo ActivationInfo;
FCopy_FGameplayTagContainer DynamicAbilityTags;
TArray<TObjectPtr<UGameplayAbility>> NonReplicatedInstances;
TArray<TObjectPtr<UGameplayAbility>> ReplicatedInstances;
FCopy_FActiveGameplayEffectHandle GameplayEffectHandle;

};

But FGameplayAbilitySpec have other variable that are not using any UPROPERTY specifier.

	/** Handle to GE that granted us (usually invalid) */
	UPROPERTY(NotReplicated)
	FActiveGameplayEffectHandle	GameplayEffectHandle;

	/** Passed on SetByCaller magnitudes if this ability was granted by a GE */
	TMap<FGameplayTag, float> SetByCallerTagMagnitudes;

Probably it's not an issue in this particular struct since SetByCallerTagMagnitudes is located at the end of the struct, but if it's in between other UPROPERTIES, then it will cause the memory offset for all properties after SetByCallerTagMagnitudes to be wrong, and the value will be invalid/corrupted.

Is my understanding is correct? Am I missing some details?

能不能来张架构图

来张架构图来说明UE客户端 ChannelId UE服务端1 UE服务端2 之间是怎么交互的,这样方便在未深入细节前就对整个架构有个理解 。

FUnrealObjectPropertyDecorator GetCPPType

Hi,

Why the code is like this:

FString FUnrealObjectPropertyDecorator::GetCPPType()
{
	return TEXT("UObject*");
}

Instead of

FString FUnrealObjectPropertyDecorator::GetCPPType()
{
	return OriginalProperty->GetCPPType();
}

I feel the current code is maybe error prone, since TObjectPtr or TWeakObjectPtr both are translated to UObject*.
There's no guarantee both are saving UObject* directly.
I haven't read through their implementation, but it seems TWeakObjectPtr is not saving pointer value, instead if it save ObjectIndex to query GUObjectArray.

Support multiple replicated SceneComponent in one Actor

PR #48 added support to multiple replicated ActorComponents in one Actor. However, if the ActorComponents are SceneComponent, it won't work, as the SceneComponentStates still share the same NetGUID (Actor).

To make it work, we need to:

  1. Add the compName field for all the states of the ActorComponent that inherit SceneComponent;
  2. Generate the ComponentStates message to aggregate all the component state mentioned above, and map them by the compName

The design above should have some performance issue, as the component states are wrapped in two levels of map in the Global channel data, and to avoid that, there's another design:

  1. Use the Actor NetGUID + Component Name to globally index the actor component;
  2. So the component state map in the Global channel data should be like this: map<string, unrealpb.SceneComponentState> sceneComponentStates

Add "CrossServer" RPC flag

As of v0.6, cross-server RPC is supported via routing the server RPC (EFunctionFlags::FUNC_NetServer) to the authoratative server.

The implementation has a drawback: it exposes the RPC that should only be used by servers to the clients.

To fix this, ChanneldUE should extend the EFunctionFlags to support server-to-server-only RPC.

Ideally, the new function flag can be used both in C++ and Blueprint without modifying the engine.

Stakeholder: @laughxing

Support the cross-server handover of Physics Bodies

As of v0.5.0, the cross-server handover of Physics Bodies is not supported. When a physics body moves across the server border, it loses the states like the linear velocity, hence stops at the border.

The implementation should handover the necessary states of FBodyInstance without replicating them to the client.

Implement StaticMeshComponentReplicator

The genereated StaticMeshComponentReplicator's StaticMesh property is not replicated properly, causing its owning actor flicker all the time. We should implement the StaticMeshComponentReplicator's manually.

自动生成代码结构体对齐

复现方式:
添加一个NetMulticast的UFunction如下
image

在服务器多次调用,在客户端会出现Crash。

原因:
FTransform中的FQuat添加了对齐,MS_ALIGN(16) struct FQuat(见Quat.h)
而自动生成代码的FCopy_FQuat没有添加。导致FTransformFCopy_FTransform对齐不一致。
image

在写入到参数结构体时,参数结构体的偏移是UE结构体的偏移,而实际创建的结构是以FCopy_XXX为基础的。
正常情况写入FTransform参数的偏移应该是以自动生成代码为准,偏移为4,结果是用的UE结构体的偏移,16。导致写入时写越界了,覆盖了系统中其它变量的内存的值,导致crash。

Consider unmapped NetworkGUID in the generated replicator

For now, the situation of NetworkGUID unmapped is not considered in the generated replicator, causing the replicator keeps sending invalid UnrealObjectRef in the channel data update.

The proper code should follow the example of replicating AActor::Owner in FChanneldActorReplicator.

SyncNetId两个服Object匹配问题

空间频道中,是通过Path(调用Actor->GetPathName获得)和netguid做匹配的,这里会有两个问题:
(1)path是否在两个Server能保持一致(或唯一)
(2)两个服同步发起时机是否一致(能否保证服务器在调用SyncNetID时,当前场景的对象是没有动态创建对象的情况,
目前看在收到订阅GlobalChannel结果后发起的,如果这个时候服务器执行过Spawn逻辑,那么两边可能不一致)

UE 5.1 - Server cransh due to failed to register generated channel data message

Server log:

LogChanneld: Error: Failed to register channel data type by name: channeldgenpb.GlobalChannelData1127707765
LogChanneld: Error: Failed to register channel data type by name: channeldgenpb.SubworldChannelData11277077
LogChanneld: Registered unrealpb.SpatialChannelData for channel type 4
LogChanneld: Error: Failed to register channel data type by name: channeldgenpb.EntityChannelData1127707765

Customizable Channel Data Message

What

As of v0.5, the genereated Channel Data Message (named DefaultChannelData in the proto file) contains ALL the replication states that used the project. A typical DefaultChannelData mesage looks like this:

message DefaultChannelData {
    map<uint32, channeldgenpb.BP_TestRepPlayerController_CState> bP_TestRepPlayerController_CStates = 1;
    map<uint32, channeldgenpb.BP_TestRep_CState> bP_TestRep_CStates = 2;
    channeldgenpb.BP_RepGameState_CState bP_RepGameState_CStates = 3;
    map<uint32, channeldgenpb.BP_TestNPC_CState> bP_TestNPC_CStates = 4;
    map<uint32, unrealpb.SceneComponentState> sceneComponentStates = 5;
    map<uint32, unrealpb.CharacterState> characterStates = 6;
    map<uint32, unrealpb.ControllerState> controllerStates = 7;
    unrealpb.GameStateBase gameStateBase = 8;
    map<uint32, unrealpb.PawnState> pawnStates = 9;
    map<uint32, unrealpb.PlayerControllerState> playerControllerStates = 10;
    map<uint32, unrealpb.PlayerState> playerStates = 11;
    map<uint32, unrealpb.ActorComponentState> actorComponentStates = 12;
    map<uint32, unrealpb.ActorState> actorStates = 13;
}

In a project that uses the Global and Spatial channel, the Global channel data should only contains the GameStateBase and derived state; the Spatial channel data should only contains the Character, PlayerController, PlayerState, and other spatial-related states:

message GlobalChannelData {
    channeldgenpb.BP_RepGameState_CState bP_RepGameState_CStates = 1;
    unrealpb.GameStateBase gameStateBase = 2;
}

message SpatialChannelData {
    map<uint32, channeldgenpb.BP_TestRepPlayerController_CState> bP_TestRepPlayerController_CStates = 1;
    map<uint32, channeldgenpb.BP_TestRep_CState> bP_TestRep_CStates = 2;
    map<uint32, channeldgenpb.BP_TestNPC_CState> bP_TestNPC_CStates = 3;
    map<uint32, unrealpb.SceneComponentState> sceneComponentStates = 4;
    map<uint32, unrealpb.CharacterState> characterStates = 5;
    map<uint32, unrealpb.ControllerState> controllerStates = 6;
    map<uint32, unrealpb.PawnState> pawnStates = 7;
    map<uint32, unrealpb.PlayerControllerState> playerControllerStates = 8;
    map<uint32, unrealpb.PlayerState> playerStates = 9;
    map<uint32, unrealpb.ActorComponentState> actorComponentStates = 10;
    map<uint32, unrealpb.ActorState> actorStates = 11;
}

Why do we need this feature

  • To better support singleton state in the non-global channel data. For example, if each Subworld channel has a ChatState, without this feature, all the ChatState in the Subworld channels has to be put in a map in the DefaultChannelData, which makes the data access and merge troublesome;
  • To make the channel data more friendly to read and debug;
  • Less fields in the channel data means more efficient in terms of marshal and merge.

How to use this feature

An In-editor UI should be provided to specified which state should be generated for which channel type's data message(s).

In-Editor Cloud Deployment for Testing

What

An In-Editor automation tool should be provided for packaging, uploading and deploying the UE project on the cloud.

The deployment targets a Kubernates cluster. The cluster should be set up beforing using the tool.

For the first iteration, the tool only supports the Alicloud.

Why is this tool needed

  • During the testing, the developers usually perform the packaking, uploading, configuration, and lauching repeatedly. Some steps take time to finish, making the deployment time difficult to control;
  • Multiple environments makes the deployment even more difficult to manage

How to use this tool

  • Log into the k8s cluster
  • Log into the docker registry
  • One-click packaging and uploading
  • One-click start/stop the servers

property memory offset caculation error

there's some code like this:

// Character.h
#if WITH_EDITORONLY_DATA
	/** Component shown in the editor only to indicate character facing */
	UPROPERTY()
	TObjectPtr<UArrowComponent> ArrowComponent;
#endif

some property is replicated using pointer to their memory location. when we package the game, the memory offset will be different.

Explore the solutions to support ELifetimeCondition and handover properties

What

As of v0.6, ChanneldUE doesn't support replicated properties with ELifetimeCondition - ALL properties are replicated between all interested servers and clients.

Some states that should be only replicated between the spatial servers (e.g. the FBodyInstance) are also replicated to the clients as long as the states exist in the channel data.

This task is to find and design the way(s) to resolve these problems.

Why

  • Some properties are not needed to be replicated the owner/proxy side. Avoiding the replication can save the bandwidth;
  • Some properties are not meant to be known to the client / simulated proxy. The replication should avoided in order to protect the privacy. For example: the APlayerController

ChanneldCookCommandlet.cpp

Is there any specific implementation that will differ to the original CookCommandlet?
I'm thinking to use the original CookCommandlet if there's no difference since this ChanneldCookCommandlet have compilation issue on UE5.

Failed to generate the replicator for PlayerState

Steps to reproduce:

  1. Comment out the registeration code of FChanneldPlayerStateReplicator in ChanneldUE.cpp
  2. Comment out the line of APlayerState::StaticClass() in ReplicatorGeneratorUtils.h
  3. Comment out the line with APlayerState::StaticClass() in ReplicatorCodeGenerator.cpp
  4. The built-in replicator should be bypassed. Now re-build and run the UE project
  5. Make sure the /Script/Engine.PlayerState exists in at least one of the channel data
  6. Generate the replication code. There should be compilation error says bReplicationBytesChanged doesn't exist.

Implement ChanneldWorldSettings

What

A place to store the settings of the view class, server groups, and channeld launch args individually for each map.

Why

In a project with multiple maps that have different channel settings (e.g. the demos project), opening and testing different maps in the editor can be troublesome - if a developer forgets to set the view class, the server groups, or the channeld launch args properly every time opening a map, s/he may fail to run the map.

How

Save the settings per map. WorldSettings is instantiated per map, and can be extended easily.

Things to discover:

  • Is it able to get the WorldSettings instance from the editor code?
  • Add #if WITH_EDITORONLY_DATA for the server groups and channeld launch args and see if they are saved and loaded properly

Optimize UnrealObjectRef

UnrealObjetRef carries a NetworkGUID to reference an UObject between UE clients and servers. A Fully Exported UnrealObjectRef (FER) also contains the outer object chain and serialized bunch, in order to spawn the actor. Depending on the length of the outer object chain, the size of a serialized UnrealObjectRef varies from 100 to 300 bytes.

FERs exists in both spatial and entity channel data. Whenever a connection subscribes to an entity channel, or a handover happens, FERs are sent to the interested sides, and the network traffic overhead is considerable.

To improve the network traffic, ChanneldUE should have its own framework to replace UE's SerializeNewActor. The classPath field was an attempt, but it doesn't work in some scenarios. An ideal solution would be building a type map and maintain the map distributedly. In that way, only the type key is need in the UnrealObjetRef to spawn actors in most cases.

Performance Stress

I plan to conduct a performance stress test on the channeld UE plugins to see how many client connections can be supported. Has anyone done similar work before and would like to discuss it? How to conduct effective and reasonable testing, and what are the test results

[BUG] A Batch of Clients Disconnect

What happened:
I am doing Performance Stress Test #53, but often encounter situations where a batch of clients disconnect.
The following is the error log of the ue client

LogChanneld: Error: Failed to send packet to channld, msgTypes: 102, 102,, send/full size: -1/134, last packet size: 129. 
logNet: UNetDriver::TickDispatch: Very log time between tick. DeltaTime: 0.03, Realtime: 19.72, channeldNetDriver_2147482580

image

The following is the error log of the ue server

LogChanneld: Error: Failed to send packet to channld, msgTypes: 8, , send/full size: -1/68, last packet size: 63. 
LogChanneld: Error: Failed to send packet to channld, msgTypes: 8, , send/full size: -1/68, last packet size: 63. 
LogChanneld: Error: Failed to send packet to channld, msgTypes: 8, , send/full size: -1/68, last packet size: 63. 
LogChanneld: Error: Failed to send packet to channld, msgTypes: 8, , send/full size: -1/68, last packet size: 63. 

image

The following is the error log of the channld service

WARN channld/channel.go:384 spend too long handling messages, will delay the left to the next tick {"channelType:" "GOBAL", "channeld:" 0, "duration":"20.6272ms“, remaining: "111"}
WARN channld/channel.go:384 spend too long handling messages, will delay the left to the next tick {"channelType:" "GOBAL", "channeld:" 0, "duration":"20.6272ms“, remaining: "879"}
WARN channld/channel.go:384 spend too long handling messages, will delay the left to the next tick {"channelType:" "GOBAL", "channeld:" 0, "duration":"20.6272ms“, remaining: "448"}
WARN channld/channel.go:607  packet is going to be oversized {"connType": "SERVER", "connId": 1, "packetSize":65584, "msgType":102, msgSize": 49, "msgNum"1107, "msgInQueue": 128}

My deployment topology is following the architecture of https://github.com/metaworking/channeld/blob/release/doc/architecture.png

I run multiple ue clients on one virtual machine 01(windows) , one ue server on virtual machine 02(windows), and the channld service run on virtual machine 03(windows)

What you expected to happen:
I hope the clients can stay connected without disconnection, otherwise I cannot conduct the testing

Environment:

  • Channld version: 0.6.0
  • Channld-UE Plugin version: 0.6.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.