How do I force replication of property, even if value doesn't changed?

How do I force replication on property ?

I want to replicate property, with each replication tick, regardless, of whether that property was changed or not.
It’s fairly simple struct with one float and one vector. And I need it to be always replicated, to upadte some cosmetic stuff on client.

Right now, client is completely desynced, because updates do not arrive, when there is no changed to property (and there won’t be always changed in property, but there should be always updates on UI).

Well it will just replicate, property, when value on it changes ;).

I want to replicate it even if value haven’t changed.

The only thing I replicate are Damage value and Location.
And if you shoot non moving actor with constant damage, then value never change ;).
But you still want to show this damage on Client.

But client doesn’t know if any damage has been applied, because he do not get any notification, because property was not replicated.

Try this (Engine version 4.1):

Add Replicated tag to your propety:

UPROPERTY(Replicated, Category="CategoryName")
FStructType StructPropertyName;

Define replication in cpp file:

void AYourClass::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(AYourClass, StructPropertyName);
}

Header definition is not needed for this method. Hope this help.
Details: WIKI

I’m having a hard time understanding the sense in this. If no values are changing how is the replication of the same value going to “update some cosmetic stuff”? Are you replicating using a function on the clients and your cosmetic updating code is in there?

Could you elaborate on “constant damage” please?

Ah, I see. Do you need to replicate damage this way? Usually you replicate the players health to all the clients and do all the damage related work on the server… there is really no need to replicate a “doDamage” value.

The reason I’m discussing this with you so much is because this situation sounds odd and there might be a better way to implement it.

1 Like

Damage value doesn’t change.

If you really want to do it this way, as per our conversation through comments, you could use a Server or Client RPC (remote procedure call).

You create a function that gets called on the server from the client, and another that gets called on the clients from the server. Just call this from your Tick function.

THIS is the main page for functions and their specifiers from the docs.

THIS is the Server RPC information from the docs.

THIS is the Client RPC information from the docs.

Edit: the Client RPC might not do what you want… The function is only executed on the client that owns the Object the function belongs to. I’m not sure if this fits your implementation. If not, there might be no way to do what you want without modifying the engine source. Need clarification on this though.

Edit2: Take a look at this for damage info LINK

Yeah, now I see your point (comments) :slight_smile:

I need to replicate damage, because I want to give client chance to display it directly. It’s only replicated to player who caused it.

I’m not using unreal build damage system. I have written my own from scratch ;).

Besides, I still would like to know, if it is possible to force replication on property, just for the sake of knowing it.

I would research this a bit man. Damage in UE4

I already had tried this, and it’s not what I needed.
My issues is that when doing Client RPC might be out of sync.
When properties do change, there is no way to predict when, they will be replicated to client, and RPC all might force client to work on oudated data, untill next replication tick.

That is why you want to use RepNotifies on in such case.

It’s the same issue ;). The only difference is that Multicast is call on all clients which are relevant, to actor. And I really don’t need that.

If I would wan’t to call it on all clients I would still want to use RepNotify, just with without any replication conditions.

Edit: the Client RPC might not do what you want… The function is only executed on the client that owns the Object the function belongs to.

You can use NetMulticast and the it will be called by all clients.

There is another special type of RPC function type called Multicast. Multicast RPCs are designed to be called from the server, and then executed on the server as well as all currently connected clients. To declare a multicast function, you simply use the NetMulticast keyword: 

See ****** for more info.

So I read through all of your comments and other answers. I think I have an idea for you to think about for your unique case, consider this:

Stay ahead of the calculation by pre-calculating the damage for the next interval. So right after damage is applied, calculate your next damage and presend it. So basically, send from the server to the client, 1) time for the next damage tick, and that next damage amount.

That is the general gist, of the idea. There is alot more to do with it, but if you understand that core idea, it can help with sync issues. I use a similar technique for keeping animation events timed from server to client in an another project.

Hope that helps. :wink:

Make a struct that wraps the damage value and replicate the struct instead. The struct should have two vars:
-damage value
-replication counter

The damage value is whatever type of damage variable you were trying to replicate before - only now, its nested inside a struct.
The replication counter is a uint8 rolling counter that you increment each time you want to force a replication to occur. This way, it doesnt matter if the damage value is the same from one time to the next and you will always get your onreps.

Be warned of using RPCs - they are good for certain things, but if the client disconnects for ever a split second, the RPCs can be permanently lost. Replication on the other hand will always flood back in when they reconnect so it is much more robust.

Another problem with replication that you may have to deal with. Just because a replicated var changes during the frame doesn’t mean it gets sent over right away. It may have to wait in line behind higher priority reps. Or even if it does go out the same frame you made the change, it will only reflect the latest change. If the var changed twice during the frame, the first of those two changes will be lost. So you need a way of ensuring that every change made gets repped over, regardless of how many get bundled together. I’m sure there are a number of ways this could be done but one way that comes to mind is to use a map for collecting the changes and an array for replicating the changes. For this method, you’ll need to make the uint8 on the struct a UPROPERTY() - no other vars should be uproperties or they’ll also be used to check if the struct is dirty.

On the struct, make a map of uint8 to damage values and an array of damage values.
When damage occurs, you increment the uint8 counter and add a copy of the resulting uint8 and the damage value to the map.
In your structs custom NetSerialize fn, if the archive is saving you clear the array and add all the map’s damage values to the array.

To be continued…

Continued…

Also if archive is saving, clear the map.

Archive the array and only the array. (Should be done whether archive is saving or loading)

If archive is loading, deduce the correct number for the uint8 counter by incrementing it once for each item in the array.

Now all clients will have access to all fired damage events inside the OnRep. The common case may be just one damage event per, but there may be cases where you get 2 or 3 bundled, no problem! Each time the OnRep fires, you know each damage value in the array on that struct represents a new damage event! You could even iterate through them all and fire off client responses to the damage, in order!

Hope this helps!

Also, on second thought, you could probably skip the map and just use the array.