Rendertargets and multiplayer..?

Hey. I’ve made a simple character pane which spawns a rendertarget actor and uses the 2DSceneCaptureComponent to display it on a widget. However I’m having trouble with it functioning as intended in a multiplayer environment… of course! x)

I followed this simple tutorial for the widget:

My issue is that I have a drag-to-rotate logic on the character pane widget. When the rendertarget actor is rotated inside the widget, it rotates in the world as the actor as well. So when the client and/or server interact with the widget, the same actor’s rotation is displayed on both sides. Here is a demonstration of the problem:

I create the widget and spawn the rendertarget actor from player controller, as owning client:

In the widget, I get a reference on construct. I believe the issue is in this part of the code:

Instead of getactorofclass, what can I use to get the owned rendertarget actor for the playercontroller? I’m kinda new to multiplayer logic and getting widgets to work as intended has really been painful.

If anyone could help, I’d really appreciate it!

1 Like

Hi,

When the rendertarget actor is rotated inside the widget, it rotates in the world as the actor as well.

it seems to me that you want to have this whole logic per client, independent from all other clients. If that is correct, then you should not replicate any of the logic.

If rotating the rendertarget actor on one client, replicates to another client, then I guess that means you have replication in there somewhere that you would need to remove (since it seems to me you don’t want this to replicate / sync between clients).


And by the way, widgets never replicate, they only exist locally. So you can’t have any RPCs or replicated variables in them, they won’t do anything.

2 Likes

Thanks for the tips! I’m creating the widget/spawning the render-target actor from playercontroller, which should be unique for every client. As far as I’m aware I also am not replicating anything as well. :sweat_smile: I feel like the issue is in the widget it self. To be able to rotate the actor I get a reference to it on Construct via getActorOfClass and then use that reference on the rotation logic. I think that’s making it rotate on both server/client. However I do not know how I can get a reference to the spawned render-target actor while using the the owner/relevancy logic.

TLDR; Each client technically gets their own RenderTarget Actor which is used in the UI for the 3D display, however I’m not sure how I can reference each actor separately for my rotation logic. I tried doing it like this but doesn’t seem to work :confused:

1 Like

To be able to rotate the actor I get a reference to it on Construct via getActorOfClass and then use that reference on the rotation logic.

Could you check there that if you use GetAllActorsOfClass (instead of GetActorOfClass), that it only contains one element? Cause if that actor is not replicating and you only spawn it locally, then there should only be one of it and it should make this here

However I do not know how I can get a reference to the spawned render-target actor while using the the owner/relevancy logic.

irrelevant since there is only ever one of them :slight_smile:

1 Like

Could you check there that if you use GetAllActorsOfClass (instead of GetActorOfClass), that it only contains one element? Cause if that actor is not replicating and you only spawn it locally, then there should only be one of it and it should make this here

Yeah I checked and it just spits out a single array element. I’m confused! :sweat_smile:

irrelevant since there is only ever one of them :slight_smile:

Hmm. I don’t seem to understand why there is one. When I’m calling spawnActor from each playerController, shouldn’t there be two of them? Is it because they’re not replicated? I’m still trying to wrap my head around networking…

When I’m calling spawnActor from each playerController, shouldn’t there be two of them?

No, unless you spawn it on the server and it replicates, you will only get one :slight_smile:

Each client has their own world and runs their own simulation of it, and you use replication to sync them (as far as you need). That sync always happens through the server. Clients can only communicate with the server via RPC RunOnServer but not with each other, and the server can send things to clients via replication.

That means, that everything that should be known to all clients, needs to go through / happen on the server. If you spawn anything on a client (regardless whether that actor is marked replicated or not), the server and therefore the other clients will never know about.


Could you show your logic to rotate the character in the widget?

2 Likes

Oh man. Of course it has to be executed on server for all to see! I’m sleep deprived… x)

However I’m still not sure how to achieve what I want. I actually believe I want the spawned actor to be local - so in the end, different actors for all clients - which don’t need to be replicated. However whichever client creates the widget last has control of the spawned actor, therefore my simple rotation logic.

Could you show your logic to rotate the character in the widget?

Here, of course:




Edit: I also don’t really understand what is happening on here:

Server creates widget + spawns actor. Then, if client does the same server cannot use the rotation logic and sees what the client does (as in rotating the 3d render). However if I check wireframe on Server I can see the actor below ground that it supposedly has to see and have reflected on the widget.

Could you try to use one rendertarget for the server and a different one for the client (via e.g. IsServer set them to use different render targets)? Cause since you’re not running two separate instances (like connecting two computers), it may be that they’re both writing to the exact same render target texture and then you just display the same render target twice (once on server and once on client).

At least that’s what happened when I just tried it with the same render target.

1 Like

The thing is, the project I’m working on isn’t max 2 players, it can go up to 8 so I don’t know if creating different render targets for every one is the best way to go about this. However, just to test, I also tried doing that but it seems the behave the same way. But again, I’ll re-check and let you know! Appreciate your help here =]

The thing is, the project I’m working on isn’t max 2 players, it can go up to 8

As far as I know this reusing of the render target won’t happen if you run on several computers (maybe even if you run several standalone instances). So it should only be a problem in testing it when running several instances in the same process. So trying to use two different rendertargets is more just to test that this is actually the reason you get this behavior, cause then you could just ignore it :slight_smile:

I also tried doing that but it seems the behave the same way

In my simple test case it worked (after showing twice the same image when both were rendering to the same rendertarget). Did you swap the rendertarget also in the material (e.g. using two different materials) and the material then in the widget (for testing I created two rendertargets, materials and widgets)?

2 Likes

In my simple test case it worked (after showing twice the same image when both were rendering to the same rendertarget). Did you swap the rendertarget also in the material (e.g. using two different materials) and the material then in the widget (for testing I created two rendertargets, materials and widgets)?

Ahh nope. I just duplicated the render target actor. I will try swapping the material as well. Thanks a lot for the tips. I will let you know in a moment!

1 Like

Hey man. I created new material + widget and called separately for client and server and it seems to work. I will test with more players later on but you have been super helpful. Appreciate it! Have a great day/night. :smile:

Edit: Also without server check and duplication, just running Standalone, as you said, was working. Lmao :rofl:

1 Like

Try unchecking the ‘run under one process’ checkbox in the Play advanced settings and see if that fixes it. I have this issue also, but for time’s sake I keep PIE sessions in one process and just develop around it as it works fine when the game is packaged. Running under one process can cause issues so it’s good to keep in mind when developing multiplayer stuff, but the speed convenience makes up for it.

3 Likes

That’s another great tip. Thanks, will definitely do that!

Found a solution that worked for me. VERY DOUBTFUL THIS IS SHIPPABLE. But seemingly passable for proto! Took me hours to figure out, wanted to pass on the knowledge. Our theory is that when you’re doing PIE, multiple scene captures with the same render texture will all write to the same place, effectively overwriting each other.

If you don’t want to do ‘run under one process’, we were able to solve this by dynamically making a render texture.

In this case, we wanted to render 3D elements in each client’s hud. This reddit post roughly goes over how we made it work:

In short:
Your material should take in the render texture as a parameter
You’ll need to be able to get a reference to the object with your material on it.
You’ll also need to get a hold of your scene capture 2d component.

  • In BP, CreateRenderTarget2D.
  • Then find whatever has your material on it (your scope, your widget, etc…) and do GetDynamicMaterial.
  • On the dynamic material, SetTextureParameterValue, plugging in your newly created render target.
  • Go back to your SceneCaptureComponent2D, set TextureTarget to be your new render target
2 Likes

Im at my wits end with this exact same problem … the solution presented does not work ive tried many different variant of ideas and im limited to ue 4.15.3 …

Any suggestion on what to do to Fix this issue. Honestly this feel more like a bug then a feature at this point.

1 Like

Read thoroughly thru this post. I’m sure there is something you are missing, because I got it working. But I’m not sure about 4.15.3… Best of luck

i tried everything but its still bound to one process scene capture rather then unique … like you i make sure i was on client not on server … so there is two different copies of the scene target but its only showing for one … im not sure what im doing wrong … i tried different ways when i tried the fix way … it was like the scene capture stop working and only saved the previous picture. Ill upload a picture of what i have so far see if you can see the issue

you wouldnt happent to have a screenshot on what you did in blueprint

If you’re talking about my solution, here’s the blueprint snippet that makes and sets the render texture: example_dynamic_render_target posted by anonymous | blueprintUE | PasteBin For Unreal Engine 4

Here’s the material blueprint for my capture material (with the render texture parameter) capture_material posted by anonymous | blueprintUE | PasteBin For Unreal Engine 4