No announcement yet.

How do I make Actors invisible, client side only? [SOLVED]

  • Filter
  • Time
  • Show
Clear All
new posts

    How do I make Actors invisible, client side only? [SOLVED]

    In our top-down mod I need to make all Actors behind the avatar invisible. This is entirely a client-side thing - like any rendering effect.

    However, Actor::bHidden is a replicated variable, so the effect only works on the server. (ie. clients can only see Actors that the server player is currently watching)

    I need the rest of Actor to replicate normally - can I avoid the replication of a specific variable?

    Can you see any other way for me to make Actors invisible, client side only?

    An ugly hack would be to (on each machine, in every tick):

    1. save the current bHidden-value for every Actor we care about
    2. Change the bHidden-value to whatever we need
    3. Let the game world render
    4. Restore the bHidden value for every actor we touched and optionally, set bNetDirty=false to really get the point across and avoid replication.

    However, this requires that we can run code pre- & post rendering, and that we can reset the values prior to replication. Since replication is done after a tick, this means we want to do the resetting in Tick()

    Is that possible? There is a UTHUD::PostRender-hook and there is a PlayerController::PreRender(Canvas Canvas). I don't know if these (pre/post) refer to the gameworld-rendering though, it seems unlikely. And they're probably not guaranteed to be run within a tick?

    Unless you guys have some suggestions for me, I'll try this out tomorrow.


      I wonder if you could do it with a Material Instance Constant... have a parameter on each actor's material associated to its opacity and modify that param based on whether it falls within the player's view angle or not. Have a timer going every 0.2 seconds or so (so it's not so intensive as tick()), and if an actor is in the player's view angle and its opacity is not 100, set it to 100. Also, for all the other actor's visible but not in the view angle, set the opacity to 0 if not already (could do some fadeout effect or something).


        Thank you Archasis, that's a great idea! I'll look into it bis morgen.

        Back when I was only testing for Pawns, I tried applying an invisible material to the Pawn (and any attachments ie; weapons). However, material changes are also replicated, so it wasn't useful.

        If all Actors have materials and we can modify those, it just might work.


          Here's an screenshot of what it's like, when playing locally.

          The blue footsteps denote someone moving behind us. I haven't got an effect for the gun-shot sound yet, so we don't see the Flac cannon being fired.

          Ignore the portrait in the corner, I was experimenting with something unrelated.


            I've been struggling with this as well. It makes doing a team-based stealth game pretty difficult. Assassins in our game can stealth and we'd like to handle it much the same way that World of Warcraft does (our game is 3rd person):

            While stealthed, you and teammates can partially see your own model but enemies cannot see your model at all unless they "detect" you.... which is on a player by player basis.

            I have yet to find a way to handle invisibility/visibility on a player by player basis.


              I can't seem to find any materials in the Actor-class. I assume not all actors have materials? Archasis - can you give me any examples of Material-members in Actor or some of the more common subclass? (eg. Projectile, would be particularly useful)

              Another idea I just had: one could apply scaling to actors, so they're too small to be seen. That's still a replicated variable, but only if 'Role==ROLE_Authority' - perhaps something we can play with?

              If we really have to hack it - would this work?
              We set bSkipActorPropertyReplication to true (virtually no replication is done) on all dynamic actors. Subclass actor with 'ActorNoRep' and create everything we need as new classes under that. Create and implement our own replicated properties, with repnotify so we can apply the settings we still care about to the parent (original) Actor-class? It's a horrifying job though. :/


                Sorry, I'm being stupid. bHidden is also under 'Role==ROLE_Authority'.

                So basically, if the server just didn't participate in the stealth game (ie. was dedicated and never ran these test for itself), the client would be left alone after the initial replication of this property?


                  This is what happens in the engines update loop:

                  1. recieve values from the server / send my stuff to the server
                  2. render the game world
                  3. run tick() to update the game state

                  Notice that replication always happens after a tick, and only for values that has actually changed since last time it was replicated.

                  My hope was to do this:

                  1. receive / send information
                  2.1. event PreRender() - make stuff invisible
                  2.2. render the game world
                  3. Reset visibility again at the end of Tick(), so replication never notices it was changed.

                  I tried this today, but changes applied in PreRender is never noticed in the game world. It seems that PreRender isn't in context of the game world, but probably to the HUD drawing.

                  Too bad. :/


                    The replication statement in Actor is:
                    if ( (!bSkipActorPropertyReplication || bNetInitial) && (Role==ROLE_Authority) && bNetDirty )
                    So I tried setting Actor::bNetDirty to False on every Actor we've touched - directly after the call to SetVisible, and then again at the end of Tick (in case it was changed from some other place in between).

                    But it didn't help, we still only get what the server sees. :/

                    I've exhausted all of my ideas at this point. I couldn't figure out how to get a material from Actor (nor Pawn), or how I adjust Opacity of materials through UnrealScript. If you guys have any input, it would be much appreciated.


                      // set when any attribute is assigned a value in unrealscript, reset when the actor is replicated
                      var transient   bool    bNetDirty;
                      So we see bNetDity is not a constant and is always changing during execution.

                      I would recommend you to look inside the steath parts that already in UT3
                      (you could search here).

                      Also if you want invis. like shown in this trailer, let me know.


                        All stealth code I've seen applies a material to Pawns. This works well if the Pawn should be invisible for everyone - like the trailer you linked, or the Stealth Arena mod Zeo posted a while back.

                        The problem I'm trying to solve, is that an Actor can be visible to only one client, but invisible for all the rest. That is - everything is default not visible, and will only become visible for me, if I watch it. (if it falls within FOV, like the Flac shards in the screenshot above)

                        As it is - with replication from the server controlling Actor visibility and materials - when the server sees any actor, it becomes visible to all clients.


                          Originally posted by BertBurt View Post
                          can you give me any examples of Material-members in Actor or some of the more common subclass?
                          Actors that are visible in-game typically have a mesh, which is a component assigned to the actor class. For example, Pawns have a SkeletalMeshComponent which has a mesh that can have materials assigned to it. Actors themselves do not have a "material" property, their components do. If you look through UTPawn.uc, take a gander at functions like SetSkin(), SetInvisible(), SetBodyMatColor(), SetInfoFromFamily(), and so on. Also look at UTPawn's Mesh variable, which is assigned a SkeletalMeshComponent 'WPawnSkeletalMeshCompooent' in the DefaultProperties. Hope that helps.


                            Look - the issue is:

                            How can we make a Pawn look like one thing to Group A of players while looking like something else to Group B of players?

                            We know how to make players look invisible, bright, dark, smoky, etc. The problem is, whatever a pawn looks like at any given moment in the game, it looks that way to everyone.


                              Archasis suggestion is that instead of attaching a new material (which is always replicated), we might change one little property (opacity) of the current material. This small change might go unreplicated.

                              It seems like a very reasonable plan, since most material-related work in the code does some form detach/re-attach or set flags - I assume to notify the replication framework that something has changed. We could bypass those steps and keep our small changes local.

                              I still need to actually get hold of a relevant Pawn material and set the opacity to test this theory though. I tried a quick-n-dirty thing yesterday by (instead of setting invisibility) setting the Pawn's mesh rendering mode to "wireframe" and disabling shadows, but these settings never took any visible effect.

                              Either I did something wrong, or the server overwrote my small change, or the mesh needs to be re-attached for rendering to update. Testing every possibility takes so much time and effort.