Smooth Sync: Sync your Transforms Smoothly across the network

forumtitle.png

Link to Marketplace

Hey! I didn’t see any way to sync from client owned objects so I made this.

It’s a pretty simple setup. Just add the Smooth Sync component to your Actor and it will sync it’s movement from the owner to the non-owners or from the server to client if there is no net owner.

Videos:
See Smooth Sync in Action
Smooth Sync Overview

Smooth Sync differs from Unreal’s Replicate Movement in two key ways:

  1. Using custom interpolation, as described in detail here, it can be set up to your game’s specific needs.

  2. Allow client owned objects to determine the position of Actors. This removes the need for client side prediction (or “player prediction”) for certain Actors.

Look at all of those features! Easy to ignore a lot of them too, they are just there if you need them.

Interpolation and Extrapolation

Performs interpolation and extrapolation to handle lag.

Highly Configurable

Choose what you want to send and when you want to send it. Optionally compress floats to further reduce bandwidth. Customizable interpolation and extrapolation settings depending on your game’s needs.

Source Code

The full source code is provided so you can see everything with detailed comments.

Professional Support

We have a consistent record of prompt and effective support. Contact us via email or forums any time and we will work with you to resolve any issue.

We are game developers too so we know how important it is to have working products and to put out fixes fast.
Let me know if you have any suggestions or comments. I want to make Smooth Sync the best it can be!

Link to Marketplace

Documentation

2 Likes

Hey mate, so the quickest way to reproduce the basic server owned actor desyncing is the following:

Open a new top down template project.

Create new actor blueprint (Named Ball in this example), add a new “Sphere Component”, select the new added “Sphere Component” (below DefaultSceneRoot) and set collision of the sphere to “Physics Actor” and set “Simulate Physics” to true, set mass to 100(optional),

Set the blueprint to replicate, but not replicate movement.

Add the SmoothSync Component.

Select the SmoothSync Component and under the "Important category, set the checkbox “Set Owner to Server” to true.

Place an instance of the Ball actor in the level.

Compile, save, play in editor with dedicated server unchecked and move the player character to the ball, observe de-sync immediately when the ball has its first collision.

Having substepping enabled or disabled has no effect.

This scenario occurs when the actor is already placed in the map.

The same occurs when spawned in.

Spawn method as follows:

From the TopDownCharacter blueprint, Add an input node (in this case I just used the number key “1”).

Add new custom event, set to “Run On Server” and set Reliable to true.

From the 1 key executable output connect to the custom event.

From the custom event, add a “Spawn Actor From Class” Node and set the Class field to “Ball”

Get the Character Mesh component by dragging from the component list into the Event Graph.
Add a “Get World Location” node, and connect the “Mesh” Node to this.
Add a “+Vector” node, add 500 to the Z axis field, leave the X and Y as 0.
Add a make transform node, connect the “+Vector” node output to the Vector input on the “Make Transform” node, leave the other fields default (0 rotation, 1 scale).
Connect the transform output of the “Make Transform” node to the “Spawn Transform” input of the “SpawnActor Ball” node. (this will spawn the ball above the player character).

Compile, save, and Play In Editor with dedicated server unchecked and players set to more than 1 (haven’t had a chance to test dedicated setup yet).

Use the player character to push the ball around and observe de-sync on client after the ball has its first collision.

Tested on Windows 10 on 4.19.2 Source built editor.

Same occurs on non-source editor.

On the places where it has worked for me (namely having a trailer attached to a possessed vehicle via a physics constraint, with the trailer owner set to server and the vehicle owner set to the player on possession using a set owner node and switching the “Set Owner to Server” node to false on possession) there is no problem until a first collision occurs (or I think this may be the case).

Issues seem to arise on first collision with another actor?

Will try to put a couple of short videos together to demonstrate.

I’d rather not send my project files (100GB :slight_smile: )

Thanks in advance for your help with this.

Additional thought, when it does work (with trailer and vehicle) the physics is set to Kinematic on the wheels of both in their respective physics blueprints, maybe this has something to do with it? It does eventually de-sync though.

@GrumpyNZ
Thanks for getting back to me and with such great steps I could follow. No need for any videos, I can recreate the issue perfectly.

So it looks like the problem has to deal with setting up ownership. If you follow your first scenario with the ball in the scene, even Unreal’s “Replicate Movement” doesn’t sync any movement. There is no owner of the ball when using SmoothSync or when not using SmoothSync.

I’m fairly new to Unreal, that’s why I have “You must set up ownership in order to sync your Actors” near the top of the store page. So let me know if I’m just completely misunderstanding the issue but the Actor appears to have no owner so no information can possibly be sent over the network on this Actor.

I hesitated to put in the SetOwnerToServer variable while being so new to Unreal. In Unity, all objects are automatically owned by the server so I thought it would be helpful to recreate that, but it looks like there’s some scenarios that I wasn’t seeing. Let me know if you feel misled by seeing that variable in the image on the store page or me talking about the variable here or on the docs, but I’m probably just going to get rid of that variable all together.

Now after an object has an owner, SmoothSync will handle all movement and I will gladly work forever to fix any of those problems.

Hi , no that’s fine, the price is such that it doesn’t really bother me. Just one question, I’m just wondering if there’s a way we can get that functionality into this plugin?

If you are having trouble with it can I suggest you contact a man called Cedric, you can contact him via his webpage and he may be able to help you with integrating things with unreal (he’s a bit of a pro :slight_smile: )

Thanks for your quick response, I will follow the development of this project as I think it has massive potential and is a great idea.

Many thanks again.

This is exactly why this would be sooooooo great :slight_smile:

@GrumpyNZ
So I want to say the entire issue revolves around setting up the object incorrectly for Unreal networking. I think it’s because you are replicating the scene component and not the sphere itself.

This image shows how to place a sphere in your level so that it can be networked using Unreal’s networking. See this post for more information on why your sphere setup isn’t working.

Let me know how it goes or if you have any questions.

Oh excellent, will give it a go and get back to you. Thanks a bunch :slight_smile:

Works in this incredibly limited scope. Unfortunately the limitation to removing the scene component makes it entirely unusable. With a vehicle, how can we integrate it (or anything with a skeletal mesh component)?

Sorry, just a couple of things.

When the Set Server to owner checkbox is set, it’s just getting the first player controller, i.e. Playercontroller 0 in all cases.

When I manually set the owner via the set owner function and I feed it the player controller the ownership is still forced to get the first playercontroller regardless (I assume this is due to the GetPlayerController(GetWorld)0)) thing?)

Is this a problem because the playercontroller is only relevant to each client and not each other? Would it be perhaps better to set ownership using the playerstate?

Forgive me if i’m way off base here but i’m having trouble with increasing the scope of use for this.

Also, would you prefer I contact you via email or are you happy with the forums?

@GrumpyNZ
I’m not entirely sure what you are asking but you’ll probably want to uncheck the Set Owner To Server checkbox if you are trying to set owner as not server.

I’m not sure what the best way to set up ownership is for your situation but you’ll have to set up ownership in order to sync your Actors.

I use


if (setOwnerToServer && realObjectToSync->GetWorld()->IsServer())
    {
        realObjectToSync->SetOwner(UGameplayStatics::GetPlayerController(GetWorld(), 0));
    }

to set up ownership on the server.

You can increase the number to get other player controllers if they are connected. Only the server knows every client’s player controller. I’m not sure about using player states instead.

Forums are good for me.

Let me know if I misunderstood what you were asking or if you have more questions.

Been looking thought the code a bit and that had me confused - I’m not sure what you intended when you set that.
The only time you’d need to set the owner to a player controller, player state or similar is when you would need to replicate information directly from client to server/server to client.
From the look of it, there is a multi-cast involved at the moment, which doesn’t need an owner.
Yeah… so, bit confused :stuck_out_tongue:

@
I’m no expert in Unreal so let me know if I’m confusing anything.

Are you saying that setting owner to server is basically redundant since I can just use multi-cast to send from server regardless?

If you mean the entire project doesn’t need to set an owner, I’m very confused because I thought you needed to have the client as an owner to be able to send RPCs from the client to the server.

@ No, you don’t need an owner for a multi-cast to all clients.
That said, it will go to all clients, regardless of relevancy.
I’m not sure if that was intended or not.
Was going to pass the information via the regular replication system instead.
That way the game is not sending updates to players that can’t possibly see the actor/component being updated.

@
What are you saying no to? I still need ownership to send from clients to server as far as I understand.

I do understand that multi-cast can send from server to clients regardless of ownership though. I’ll think about automatically making the server act as the owner and control the position, but I liked the explicit nature of having to set up server ownership so that the user knows exactly who is controlling the position. It seems common to just have the server act as the owner in Unreal though so I’ll probably implement it in the next update. Thanks for the tip.

I’m pretty sure unreliable RPCs use NetCullDistanceSquared so I don’t think passing information through another system will do anything different for that.

@ Oops, yeah mean “No” as in “No you don’t need an owner” in response to “Are you saying that setting owner to server is basically redundant since I can just use multi-cast to send from server regardless?”.

Sorry about the confusion.

> “I’m pretty sure unreliable RPCs use NetCullDistanceSquared so I don’t think passing information through another system will do anything different for that.”

It was my understanding that it simply meant it may/may not make it to the client.
See Reliable vs Unreliable Function Call Replication.

@
Ah, I see. I’m still conflicted on if I want to sync to server automatically when there is no owner but I’ll definitely look into it.

I just tested NetCullDistanceSquared and it does not receive messages if they are passed the limit when using unrealiable RPCs.

Thank you for sharing that.
It is something I did not know and will hopefully come in handy for others :slight_smile:

Are you going to support 4.20?

@iCode
Good idea. I was starting small so as to have fewer chances at issues. I’ll put out some versions that aren’t 4.19 in the next few days, including 4.20.

I’ll message you when 4.20 is up on the store.

Something isn’t adding up.

Lets say there is a ball that players can walk into and it gets kicked around. This ball needs an owner for RPCs.

If there is 3 players, and the server sets a player as the owner, that owner replicates to all players and that player now owns the ball. That player can call RPCs. The rest can’t. That’s useless because they all need to sync it.

You can’t use RPCs for a system like this, it needs to be purely replication based. Even if you can multicast, you shouldn’t, it’s more bandwidth intensive and doesn’t get called as something becomes relevant like replication does.

Also… stuff lying around in the world, where you’d likely actually use this, isn’t owned. That’s the point.