Educational iOS AR app that places a scaled solar system in the real world and shows scientific information when a planet is tapped.
- Splash screen with
solarsystem.jpgand "Explore AR" button - Place solar system on a detected surface (raycast)
- 10 celestial bodies (Sun, Mercury, Venus, Earth, Moon, Mars, Jupiter, Saturn, Uranus, Neptune)
- Planet rotation (spin) and orbital motion
- Tap a planet to view a detailed info card (name, description, key facts)
- Parallel texture loading for faster placement
- macOS with Xcode 14+ (RealityKit / ARKit)
- iOS device running iOS 15+ for AR testing (physical device required)
- Assets in Assets.xcassets:
solarsystem(background),SunMap,MercuryMap,VenusMap,EarthMap,MoonMap,MarsMap,JupiterMap,SaturnMap,UranusMap,NeptuneMap - Camera permission in
Info.plist(NSCameraUsageDescription)
- Copy the project folder to your Mac and open
ContentView.swiftproject in Xcode. - Confirm all texture assets are present in
Assets.xcassetswith the exact names used above. - Ensure
Info.plistcontainsNSCameraUsageDescription. - Connect an iPhone, select it as the run destination, then Build & Run.
- On first run allow camera access. Tap a real-world horizontal surface to place the solar system. Tap a planet to show info.
ContentView.swift- Splash:
SplashScreenView - AR UI:
ARSolarSystemView - Data:
ARViewModel.getPlanetInfo(for:) - AR bridge:
ARViewContainer.makeUIView(...) - AR logic:
ARViewContainer.Coordinator—placeSolarSystem,createPlanets,createPlanet,updatePlanets
- Splash:
- EXC_BREAKPOINT on material or
generateSphere:- Ensure RealityKit operations run on main thread: wrap entity creation inside
await MainActor.run { ... }. - Use
PhysicallyBasedMaterialand apply materials after creating theModelEntity. - Use
try? MeshResource.generateSphere(radius:)and guard fallback. - Use
ShapeResource.generateSpherefor collision shapes (fast).
- Ensure RealityKit operations run on main thread: wrap entity creation inside
- Slow placement:
- Confirm textures load in parallel via
async let. - Use lower-res textures if device is slow.
- Confirm textures load in parallel via
- Tap not detected:
- Ensure
CollisionComponent(shapes:)andInputTargetComponent()are set on the ModelEntity.
- Ensure
- Local (relative to anchor):
entity.position - World (AR world coordinates):
entity.convert(position: entity.position, to: nil)
Example helper (add to ARViewModel or Coordinator for debugging):
func worldPosition(of name: String) -> SIMD3<Float>? {
guard let entity = planetEntities[name] else { return nil }
return entity.convert(position: entity.position, to: nil)
}- AR requires a physical iOS device; simulator will not show AR content.
- Keep texture sizes reasonable to reduce memory and load time.
- All RealityKit creation must happen on main thread to avoid crashes.
- MIT