Level Snapshots - Missing viewport visibility and layer visibility

Hey all,

It would seem as if still in the latest version of level snapshots in 5.6, viewport visibility is not saved into the snapshot. This can cause visual continuity issues, due to most users assuming this affects the visibility of the asset.

The same seems to be true for layer visibility.

Thanks,

Connor

Steps to Reproduce

  • Take Level Snapshot
  • Change visibility of object using the viewport visibility eye button in the outliner
  • Take another Level Snapshot
  • The snapshot will not detect a difference

Layer visiblity, do the same steps above but change layer visibilty.

Hi Connor Ling,

Sorry about the delay. I’m looking into this now and should get back to you soon.

Best regards,

Vitor

Hi Connor Ling,

The behavior you described is by design. The visibility state controlled by the Eye Icon in the Outliner tab, Layers tab and Data Layers tab is not saved either on Level Snapshots or on the Level/Actor/DataLayer Asset itself, and is also not respected in runtime (e.g. PIE). It is meant as a quick visual aid to help examine a scene, select and edit some actor that is behind another one etc.

The correct way to make persistent changes to actor visibility is to check or uncheck the “Visible” flag on renderable actor components, or the “Hidden in Game” flag for entire actors at runtime.

I understand this can cause some confusion at first, I was also surprised when I first saved a level with some visibilities disabled only to later reload it and find everything visible again. But this is definitely by design. If it helps, it is possible to right click the Eye Column header on the Outliner and hide it completely, so that the source of confusion is gone.

Let me know if this clears things up.

Best regards,

Vitor

Hey Vitor,

For me, when using level snapshots within a virtual production context, it results in alot of confusion from the artists perspective when the outliner visibility is a lot easier to access and most would assume that this does the same thing. (Although we digged into the code and understand it does not).

We can tool our way around it, just feels to a degree like reinventing the wheel, haha.

May be worth making this more clear in doucmentation or within the tool, as it’s a very easy way to create visual differences within a virtual production setting and using level snapshots.

Thanks!

Connor

Hey Vitor,

Yes of course and don’t get me wrong, the editor usecase makes complete sense. But as Level snapshots has been introduced in the last few years within a virtual production context and the Level snapshots editor is specific to editor usecases (Granted it will restore properties over multi-user to “In-Game” instances, but you do not get the editor window), it feels confusing to the user that as far as level snapshots is concerned the scene is in the same state, even though i could have viewport inconsistencies that can be saved into the level (The scene outliner visibility will save into the level, so can cause inconsistencies).

It feels like the fix honestly would be to wrap some checks in an if only editor data check and then check for properties like “bHiddenInViewport” and only restore what the saved property was for the editors, alternatively flag that it’s different as to what it was in the snapshot but do not restore it’s state. From a user POV, it’s confusing that an actor variable can be different that can be saved into a level, but not displayed in level snapshots.

Aside from that though, your solution is a great option and i’ll give that a try! Thanks for taking the time to write that out and test it.

Connor

Hi Connor,

I completely understand. I will mention this with Epic staff, but since the behavior of the editor visibility toggles has always been like this, and since UE has been commonly used for Virtual Production for a while now, I would expect this to have been thoroughly taken into consideration by now. For example, note that the Stage App (docs, course) contains an Outliner-like UI that does include a column for controlling the “Hidden in Game” flag of actors in the scene.

If you choose to tool around it, I believe it should be fairly simple to implement an Editor Utility Widget to show a list of actors along with a toggle for their visibility.

Alternatively, you could extend the Outliner itself and add your own “hidden in game” column to it. If this interests you, you could base your implementation on class FSceneOutlinerGutter, which is the current editor visibility “eye” column, and/or on class FDisplayClusterLightCardOutlinerHiddenInGameColumn, which also controls the “hidden in game” actor property. I tried this myself to validate the idea, and here’s the code I ended up with:

`class FHiddenInGameColumn : public ISceneOutlinerColumn
{
public:
FHiddenInGameColumn (ISceneOutliner& SceneOutliner)
{
WeakOutliner = StaticCastSharedRef(SceneOutliner.AsShared());
}

static FName GetID()
{
static FName ColumnName(“Hidden in Game”);
return ColumnName;
}

virtual FName GetColumnID() override
{
return GetID();
}

virtual SHeaderRow::FColumn::FArguments ConstructHeaderRowColumn() override
{
return SHeaderRow::Column(GetColumnID())
.FixedWidth(24.0f)
.HAlignHeader(HAlign_Left)
.VAlignHeader(VAlign_Center)
.HAlignCell(HAlign_Center)
.VAlignCell(VAlign_Center)
.DefaultTooltip(FText::FromName(GetColumnID()))
.HeaderContentPadding(FMargin(4.0f, 0.0f, 0.0f, 0.0f))
[
SNew(SImage)
.ColorAndOpacity(FSlateColor::UseForeground())
.Image(FAppStyle::Get().GetBrush(“Level.VisibleIcon16x”))
];
}

virtual const TSharedRef ConstructRowWidget(FSceneOutlinerTreeItemRef TreeItem, const STableRow& Row) override
{
if (TreeItem->IsValid() && TreeItem->IsA())
{
TSharedPtr ActorItem = StaticCastSharedRef(TreeItem);
AActor* Actor = ActorItem->Actor.Get();
if (Actor)
{
return SNew(SButton)
.ButtonStyle(FAppStyle::Get(), “NoBorder”) // Optional: No border for cleaner icon look
.ContentPadding(0) // Optional: tighter layout
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
.OnClicked_Lambda(
Actor
{
bool bShouldHide = !Actor->IsHidden();

Actor->Modify();
Actor->SetActorHiddenInGame(bShouldHide); // Hidden in Game
Actor->SetIsTemporarilyHiddenInEditor(bShouldHide); // Hidden in Editor Temporarily
Actor->bHiddenEd = bShouldHide; // Hidden in Editor at Startup

return FReply::Handled();
})
[
SNew(SImage)
.Image_Lambda(
Actor
{
return FAppStyle::GetBrush(Actor->IsHidden()
? “Level.NotVisibleIcon16x” // Closed eye
: “Level.VisibleIcon16x”); // Open eye
})
];
}
}
return SNullWidget::NullWidget;
}

private:
TWeakPtr WeakOutliner;
};

void FMyEditorModule::StartupModule()
{
FSceneOutlinerModule& SceneOutlinerModule = FModuleManager::LoadModuleChecked(“SceneOutliner”);

SceneOutlinerModule.RegisterDefaultColumnType(
FSceneOutlinerColumnInfo(ESceneOutlinerColumnVisibility::Visible, 1)
);
}`This worked pretty well, but there was one thing I was not completely happy with: after applying a Level Snapshot, the in-editor visibility toggle of all actors seems to be reset to “visible”. I could not find a callback (besides Tick) I could use to update them. But the runtime visibility gets applied correctly.

Best regards,

Vitor

I see, maybe Level Snapshots could be made to store and restore the current “HiddenInEditor” state (even though it is a transient property), or at least apply the “HiddenAtStartup” state when restored. I will check with Epic and hopefully they will chime in here or give me some feedback to bring back to you.

Vitor