Build 3D scenes in FXGL — enable experimental 3D mode, set up Camera3D with free-look or follow-entity modes, load OBJ models via AssetLoader, spawn 3D entities with Model3D views, create built-in 3D primitives (Cuboid, Prism, Torus, Cylinder, Cone), add a six- face Skybox, animate 3D entities with AnimationBuilder, implement 3D collision with PhysicsComponent3D, build a third-person camera, and create Minecraft-style voxel worlds. Use this skill when building a 3D game, a 3D level, a first-person or third- person view, a 3D model viewer, or any JavaFX 3D scene within FXGL.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Build 3D scenes in FXGL — enable experimental 3D mode, set up Camera3D with free-look or follow-entity modes, load OBJ models via AssetLoader, spawn 3D entities with Model3D views, create built-in 3D primitives (Cuboid, Prism, Torus, Cylinder, Cone), add a six- face Skybox, animate 3D entities with AnimationBuilder, implement 3D collision with PhysicsComponent3D, build a third-person camera, and create Minecraft-style voxel worlds. Use this skill when building a 3D game, a 3D level, a first-person or third- person view, a 3D model viewer, or any JavaFX 3D scene within FXGL.
@OverrideprotectedvoidinitSettings(GameSettings settings) {
settings.setWidth(1280);
settings.setHeight(720);
settings.setTitle("My 3D Game");
settings.setExperimental3D(true); // required for 3D scene
}
Camera3D Setup
@OverrideprotectedvoidinitGame() {
// Get the 3D cameraCamera3Dcamera= getGameScene().getCamera3D();
// Position (X right, Y up, Z toward viewer)
camera.getTransform().setTranslate(0, -5, -20);
// Field of view
camera.setFieldOfView(60);
// Clip planes — objects outside this range are not rendered
camera.setNearClip(0.1);
camera.setFarClip(5000.0);
}
// Six face images: front, back, top, bottom, left, right// All must be the same size (power-of-two resolution recommended)import com.almasb.fxgl.scene3d.Skybox;
// Place face images in assets/textures/skybox/Skyboxskybox=newSkybox(
getAssetLoader().loadImage("skybox/front.png"),
getAssetLoader().loadImage("skybox/back.png"),
getAssetLoader().loadImage("skybox/top.png"),
getAssetLoader().loadImage("skybox/bottom.png"),
getAssetLoader().loadImage("skybox/left.png"),
getAssetLoader().loadImage("skybox/right.png"),
500.0// skybox size — must exceed far clip to avoid visible edges
);
getGameScene().addGameView(skybox);
// Skybox automatically follows the camera — no manual update needed
Lighting
@OverrideprotectedvoidinitGame() {
// Ambient light — illuminates everything equallyAmbientLightambient=newAmbientLight(Color.color(0.3, 0.3, 0.3));
// Point light — illuminates from a positionPointLightpointLight=newPointLight(Color.WHITE);
pointLight.setTranslateX(0);
pointLight.setTranslateY(-10);
pointLight.setTranslateZ(-5);
// Add lights to the scene's 3D root
getGameScene().getRoot3D().getChildren().addAll(ambient, pointLight);
}
Animating 3D Entities
// Rotate a 3D entity around the Y axis
animationBuilder()
.duration(Duration.seconds(3))
.repeatInfinitely()
.rotate(planetEntity)
.from(0)
.to(360)
.axis(newPoint3D(0, 1, 0)) // Y axis
.buildAndPlay();
// Translate along Z axis (move toward viewer)
animationBuilder()
.duration(Duration.seconds(2))
.interpolator(Interpolators.SMOOTH.EASE_BOTH())
.translate(entity)
.from(newPoint3D(0, 0, -50))
.to(newPoint3D(0, 0, 0))
.buildAndPlay();
// 3D uses FXGL's own axis-aligned bounding box intersection (not Box2D)// Entities need BoundingBoxComponent populated with a 3D boxEntityprojectile= entityBuilder()
.at(x, y, z)
.bbox(BoundingShape.box3D(0.5, 0.5, 0.5))
.collidable()
.with(newProjectileComponent(direction, 20))
.buildAndAttach();
Entitytarget= entityBuilder()
.at(tx, ty, tz)
.bbox(BoundingShape.box3D(2, 2, 2))
.collidable()
.build();
onCollisionBegin(EntityType.BULLET, EntityType.ENEMY, (bullet, enemy) -> {
bullet.removeFromWorld();
enemy.getComponent(HPComponent.class).damage(25);
});
Minecraft-Style Voxel World
privatestaticfinalintTILE=1; // 1 unit per voxelprivatevoidbuildChunk(int[][][] grid) {
for (intx=0; x < grid.length; x++) {
for (inty=0; y < grid[x].length; y++) {
for (intz=0; z < grid[x][y].length; z++) {
if (grid[x][y][z] == 0) continue;
Cuboidcube=newCuboid(TILE, TILE, TILE);
cube.setMaterial(getMaterialForType(grid[x][y][z]));
entityBuilder()
.at(x * TILE, y * TILE, z * TILE)
.view(cube)
.bbox(BoundingShape.box3D(TILE, TILE, TILE))
.collidable()
.buildAndAttach();
}
}
}
}
// Place / remove voxel on click via raycastingprivatevoidplaceVoxel(MouseEvent e) {
// Cast ray from camera through screen point — manual intersection test// FXGL 3D: use PickResult from JavaFX scene picking
getGameScene().getRoot3D().addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
PickResultpick= event.getPickResult();
if (pick.getIntersectedNode() != null) {
Point3Dpoint= pick.getIntersectedPoint();
// Snap to grid and spawn new blockintgx= (int) Math.round(point.getX());
intgy= (int) Math.round(point.getY());
intgz= (int) Math.round(point.getZ());
spawnBlock(gx, gy, gz);
}
});
}
Gotchas
setExperimental3D(true) is required — without it the getGameScene().getCamera3D()
call returns null and 3D entities are not rendered in 3D space.
JavaFX 3D requires hardware acceleration — on headless servers or older GPUs,
3D rendering falls back to software rendering, which is extremely slow. Test early.
Y axis is inverted vs. 2D — in JavaFX 3D, Y increases downward in 2D but the 3D
coordinate system has Y pointing up. Camera moves use the 3D convention.
Box2D physics is 2D only — PhysicsComponent with Box2D does not work in 3D space.
Use manual bounding box collision or JavaFX 3D pick events for 3D collision.
OBJ loading requires MTL adjacent to OBJ — FXGL's OBJ loader resolves material files
relative to the OBJ path. Both files must be in assets/models/.
Skybox size must exceed camera.setFarClip() — if the skybox cube is smaller than the
far clip, you'll see black corners where the skybox ends.
animationBuilder().rotate() on 3D entities needs axis(new Point3D(x,y,z)) — the 2D
single-angle form only rotates around Z. Pass the axis explicitly for 3D rotation.
PointLight scope in JavaFX 3D — by default a PointLight illuminates everything in the
scene. Use light.setScope() to restrict illumination to specific nodes if you have many lights.
Voxel worlds with thousands of cubes — each Cuboid is a separate JavaFX Node. Above
~10,000 nodes, JavaFX's scene graph slows significantly. Use instanced rendering or chunk
culling (only spawn visible chunks).