Spatial SwiftUI: Physical Metrics
Scaling entities to exact real world metrics.
Overview
SwiftUI has some features to calculate the number of points needed to represent real-world sizes. We can convert these points to values we can use in RealityKit to scale or size entities.
There are two related features here
- The Physical Metric property wrapper
- The Physical Metrics Converter, which we can get from the environment
We’ll create a box that is scaled to one foot on all sides. The variable oneFoot will be set with number of points needed to represent a single foot in length.
@PhysicalMetric(from: .feet) var oneFoot: Float = 1
print("one foot in points is: \(oneFoot)")This will print 414.528. As you can guess, that is not a suitable number to scale an entity in RealtyKit.
Let’s get the converter
@Environment(\.physicalMetrics) var physicalMetricsWe can use the converter to take the points in oneFoot and convert them to meters that we can use in the RealityKit scene.
Personal preference: Even if I need to present 3D content scaled as feet, I’d prefer to keep my scene content in meters.
let sizeInPhysicalMetric = physicalMetrics.convert(oneFoot, to: .meters)
subject.scale = .init(repeating: sizeInPhysicalMetric)
print("box has scale: \(sizeInPhysicalMetric) in meters")- We asked SwiftUI for points that represent one foot = 414.528
- We converted those points to meters = 0.3048
- Then we scaled our entity
It is important to point out that this scaling works because our box was created a 1 meter on all sides. It may be interesting to look at methods to use physical metrics to set the size of entities.
Example Code
struct Example080: View {
// Get the converter from the environment
@Environment(\.physicalMetrics) var physicalMetrics
// Set a variable that will calculate the points needed to represent one foot
@PhysicalMetric(from: .feet) var oneFoot: Float = 1
// Set up a subject entity
@State var subject: Entity = {
let mat = SimpleMaterial(color: .stepGreen, roughness: 0.2, isMetallic: false)
let box = ModelEntity(
mesh: .generateBox(width: 1, height: 1, depth: 1),
materials: [mat])
return box
}()
var body: some View {
RealityView { content in
content.add(subject)
// We can print the number of points to represent one foot
print("one foot in points is: \(oneFoot)")
// We'll convert from points to a size in meters and scale the subject
let sizeInPhysicalMetric = physicalMetrics.convert(oneFoot, to: .meters)
subject.scale = .init(repeating: sizeInPhysicalMetric)
print("box has scale: \(sizeInPhysicalMetric) in meters")
}
}
}Support our work so we can continue to bring you new examples and articles.

Follow Step Into Vision