Contents

Controlling the layout behavior of a reality view

Choose a strategy for sizing frames and centering 3D content.

Overview

When you use Model3D to display a 3D model, the view automatically sizes its frame to fit the visible content, and centers that content within the frame. When your project outgrows Model3D and you switch to RealityView for more control over your entities, you lose that automatic sizing and centering behavior. By default, a RealityView takes up as much space as SwiftUI offers, and doesn’t adjust the position of its content.

The realityViewLayoutBehavior(_:) modifier gives you control over how a RealityView sizes its frame and positions its content. You apply the modifier to your RealityView and pass in a RealityViewLayoutOption value that specifies the behavior you want. Choose from three options: fixedSize to match the behavior of Model3D, centered to center content within a flexible frame, or flexible to keep the default behavior.

Size the frame to fit the content

The most common use of realityViewLayoutBehavior(_:) is to make a RealityView behave like Model3D. Apply the modifier with fixedSize to set the frame of the RealityView equal to the visual bounds of its entity content and center that content within the frame.

RealityView { content in
    if let model = try? await Entity(named: modelName) {
        content.add(model)
    }
}
.realityViewLayoutBehavior(.fixedSize)

With fixedSize, the RealityView calculates the visual bounds of all the entities you add in the make closure, and creates a frame that tightly wraps that content. This is especially useful when you display a RealityView alongside other SwiftUI views because the frame accurately represents the size of the 3D content.

Center content within a flexible frame

When you display multiple RealityView instances side by side, each containing a different model, fixedSize produces frames of different sizes. If you want consistent frame sizes across your views while still centering the content, use centered instead:

HStack {
    RealityView { content in
        if let model = try? await Entity(named: "SmallRobot") {
            content.add(model)
        }
    }
    .realityViewLayoutBehavior(.centered)

    RealityView { content in
        if let model = try? await Entity(named: "LargeRobot") {
            content.add(model)
        }
    }
    .realityViewLayoutBehavior(.centered)
}

With centered, each RealityView keeps its default flexible frame that takes up as much space as SwiftUI provides, but shifts the visual content to the center of that frame. This gives you uniform frame sizes with centered content, regardless of each model’s dimensions.

Understand the performance tradeoff

The realityViewLayoutBehavior(_:) modifier calls visualBounds(recursive:relativeTo:excludeInactive:) to measure the content after the make closure runs. This call has a performance cost, so the modifier computes the layout only once — after make completes. It doesn’t recompute the layout when the update closure runs. The layout also doesn’t account for any entities you add to the RealityView during an update call.

If you need the layout to account for all of your content, add your entities in the make closure rather than deferring them to update.

See Also

SwiftUI scene presentation