skills/hytopia-lighting/SKILL.md
Helps configure lighting in HYTOPIA SDK games. Use when users need ambient light, sun/directional light, point lights, spot lights, or day/night cycles. Covers Light class, shadows, and performance optimization.
npx skillsauth add abstrucked/hytopia-skills hytopia-lightingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill helps you configure lighting in HYTOPIA SDK games.
Documentation: https://dev.hytopia.com/sdk-guides/lighting
Use this skill when the user:
HYTOPIA supports five light types:
| Type | Description | Shadows | Performance | |------|-------------|---------|-------------| | Ambient | Base world lighting | No | Cheap | | Sun/Directional | Single directional source | Yes | Cheap | | Point | Emits from a point in all directions | Yes | Expensive | | Spot | Cone-shaped emission | Yes | Expensive | | Emissive | From blocks (coming soon) | No | N/A |
Base lighting that affects the entire world.
import { World } from 'hytopia';
// Set ambient light color and intensity
world.setAmbientLight({
color: { r: 0.3, g: 0.3, b: 0.4 }, // Slight blue tint
intensity: 0.5
});
// Bright daytime ambient
world.setAmbientLight({
color: { r: 1, g: 1, b: 1 },
intensity: 0.8
});
// Dark nighttime ambient
world.setAmbientLight({
color: { r: 0.1, g: 0.1, b: 0.2 },
intensity: 0.2
});
Single light source that affects the entire world with shadows.
import { World } from 'hytopia';
// Set sun position and color
world.setSunLight({
position: { x: 100, y: 200, z: 50 }, // Direction FROM this point
color: { r: 1, g: 0.95, b: 0.8 }, // Warm sunlight
intensity: 1.0
});
// Sunset lighting
world.setSunLight({
position: { x: 50, y: 20, z: 0 }, // Low sun
color: { r: 1, g: 0.5, b: 0.2 }, // Orange
intensity: 0.8
});
// Moonlight
world.setSunLight({
position: { x: -50, y: 100, z: 30 },
color: { r: 0.6, g: 0.7, b: 1 }, // Cool blue
intensity: 0.3
});
Emit light in all directions from a point. Use sparingly - expensive!
import { Light, LightType } from 'hytopia';
// Create point light
const torchLight = new Light({
type: LightType.POINT,
position: { x: 10, y: 5, z: 10 },
color: { r: 1, g: 0.7, b: 0.3 }, // Warm fire color
intensity: 2.0,
range: 15 // Light falloff distance
});
world.addLight(torchLight);
// Dynamic light following entity
const playerLight = new Light({
type: LightType.POINT,
color: { r: 1, g: 1, b: 1 },
intensity: 1.5,
range: 10
});
// Attach to entity
playerLight.setTrackedEntity(player.entity);
world.addLight(playerLight);
Cone-shaped lights. Use sparingly - expensive!
import { Light, LightType } from 'hytopia';
// Create spot light
const spotlight = new Light({
type: LightType.SPOT,
position: { x: 0, y: 20, z: 0 },
target: { x: 0, y: 0, z: 0 }, // Point light looks at
color: { r: 1, g: 1, b: 1 },
intensity: 3.0,
range: 30,
angle: 45, // Cone angle in degrees
penumbra: 0.5 // Soft edge (0 = hard, 1 = very soft)
});
world.addLight(spotlight);
// Flashlight attached to player
const flashlight = new Light({
type: LightType.SPOT,
color: { r: 1, g: 1, b: 0.9 },
intensity: 2.5,
range: 25,
angle: 30,
penumbra: 0.3
});
flashlight.setTrackedEntity(player.entity);
world.addLight(flashlight);
import { World } from 'hytopia';
class DayNightCycle {
private world: World;
private timeOfDay: number = 0; // 0-24 hours
constructor(world: World) {
this.world = world;
}
update(deltaTime: number) {
// Advance time (adjust speed as needed)
this.timeOfDay += deltaTime * 0.001; // 1 real second = 1 game hour
if (this.timeOfDay >= 24) this.timeOfDay = 0;
this.updateLighting();
}
updateLighting() {
const hour = this.timeOfDay;
// Calculate sun position
const sunAngle = ((hour - 6) / 12) * Math.PI; // 6am = horizon, noon = top
const sunY = Math.sin(sunAngle) * 200;
const sunX = Math.cos(sunAngle) * 200;
// Determine lighting based on time
if (hour >= 6 && hour < 18) {
// Daytime
const intensity = Math.sin(sunAngle) * 0.8 + 0.2;
this.world.setSunLight({
position: { x: sunX, y: Math.max(sunY, 10), z: 0 },
color: this.getSunColor(hour),
intensity
});
this.world.setAmbientLight({
color: { r: 0.6, g: 0.7, b: 0.8 },
intensity: 0.4 + intensity * 0.3
});
} else {
// Nighttime
this.world.setSunLight({
position: { x: -100, y: 100, z: 50 },
color: { r: 0.5, g: 0.6, b: 0.8 },
intensity: 0.15
});
this.world.setAmbientLight({
color: { r: 0.1, g: 0.1, b: 0.2 },
intensity: 0.2
});
}
}
getSunColor(hour: number): { r: number, g: number, b: number } {
if (hour < 7 || hour > 17) {
// Sunrise/sunset - orange
return { r: 1, g: 0.5, b: 0.2 };
} else if (hour < 9 || hour > 15) {
// Morning/evening - warm
return { r: 1, g: 0.85, b: 0.7 };
} else {
// Midday - white
return { r: 1, g: 0.98, b: 0.95 };
}
}
}
class FlickeringLight {
private light: Light;
private baseIntensity: number;
constructor(light: Light, baseIntensity: number = 2.0) {
this.light = light;
this.baseIntensity = baseIntensity;
}
update() {
// Random flicker
const flicker = 0.8 + Math.random() * 0.4; // 0.8 to 1.2
this.light.setIntensity(this.baseIntensity * flicker);
}
}
class PulsingLight {
private light: Light;
private time: number = 0;
private minIntensity: number;
private maxIntensity: number;
private speed: number;
constructor(light: Light, min: number, max: number, speed: number) {
this.light = light;
this.minIntensity = min;
this.maxIntensity = max;
this.speed = speed;
}
update(deltaTime: number) {
this.time += deltaTime * this.speed;
const t = (Math.sin(this.time) + 1) / 2; // 0 to 1
const intensity = this.minIntensity + t * (this.maxIntensity - this.minIntensity);
this.light.setIntensity(intensity);
}
}
function createExplosionFlash(position: Vector3) {
const flash = new Light({
type: LightType.POINT,
position,
color: { r: 1, g: 0.8, b: 0.3 },
intensity: 10,
range: 30
});
world.addLight(flash);
// Fade out
let intensity = 10;
const fadeInterval = setInterval(() => {
intensity -= 0.5;
if (intensity <= 0) {
clearInterval(fadeInterval);
world.removeLight(flash);
} else {
flash.setIntensity(intensity);
}
}, 16);
}
// Good: Few dynamic lights
const torchLight = new Light({ type: LightType.POINT, range: 10 });
const playerLight = new Light({ type: LightType.POINT, range: 8 });
// Bad: Too many dynamic lights
for (let i = 0; i < 50; i++) {
world.addLight(new Light({ type: LightType.POINT })); // Don't do this!
}
// Better: Use ambient + sun for general lighting
world.setAmbientLight({ color: { r: 0.4, g: 0.4, b: 0.5 }, intensity: 0.6 });
world.setSunLight({ position: { x: 100, y: 200, z: 50 }, intensity: 1.0 });
// Then add only 2-3 point lights for important effects
development
Helps build and manage worlds in HYTOPIA SDK. Use when users need to create terrain, place blocks, manage chunks, or work with the world editor integration. Covers blocks, chunk loading, world generation, and build.hytopia.com workflow.
tools
Helps create and use plugins in HYTOPIA SDK games. Use when users need to add NPM packages, create reusable modules, or extend game functionality. Covers plugin requirements, installation, and best practices.
development
Helps implement physics and collision in HYTOPIA SDK games. Use when users need rigid bodies, collision detection, raycasting, forces, or physics-based gameplay. Covers PhysicsComponent, colliders, raycasting, and physics simulation.
development
Helps save and load persistent data in HYTOPIA SDK games. Use when users need to save player progress, leaderboards, game state, or any data that persists across sessions. Covers PersistenceManager, global data, and player data.