skills/hytopia-assets/SKILL.md
Helps manage assets in HYTOPIA SDK games. Use when users need to load models, textures, audio, or UI elements. Covers asset loading, HytopiaUI, models, textures, sounds, and asset optimization.
npx skillsauth add abstrucked/hytopia-skills hytopia-assetsInstall 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 manage assets and UI in HYTOPIA SDK games.
Documentation: https://dev.hytopia.com/sdk-guides/assets
Use this skill when the user:
import { Model, Entity } from 'hytopia';
class Character extends Entity {
constructor() {
super();
this.model = new Model({
modelUri: 'models/character.gltf',
scale: 1.0,
rotation: { x: 0, y: 0, z: 0 }
});
}
}
// Load with animation
const animatedModel = new Model({
modelUri: 'models/player.gltf',
animationUri: 'animations/player-idle.gltf',
loopAnimation: true
});
import { Model, BlockType } from 'hytopia';
// Default models included with SDK
const defaultModels = {
player: 'hytopia:models/player.gltf',
cube: 'hytopia:models/cube.gltf',
sphere: 'hytopia:models/sphere.gltf'
};
// Default block textures
const defaultBlocks = {
grass: BlockType.GRASS,
dirt: BlockType.DIRT,
stone: BlockType.STONE,
wood: BlockType.WOOD,
leaves: BlockType.LEAVES
};
import { BlockType, Material } from 'hytopia';
// Create block with custom texture
const customBlock = new BlockType({
id: 'my-mod:custom-block',
name: 'Custom Block',
textureUri: 'textures/custom-block.png',
material: new Material({
roughness: 0.8,
metalness: 0.0
})
});
import { Audio, Entity } from 'hytopia';
class SoundEntity extends Entity {
playSound() {
// One-shot sound
this.playAudio({
uri: 'sounds/explosion.mp3',
volume: 1.0,
pitch: 1.0,
spatial: true, // 3D positional audio
range: 20 // Audible within 20 units
});
}
playMusic() {
// Looping background music
this.playAudio({
uri: 'music/background.mp3',
volume: 0.5,
loop: true,
spatial: false // Global audio
});
}
}
// Play at location
world.playAudioAtPosition(
{ x: 0, y: 10, z: 0 },
{ uri: 'sounds/ambient.mp3', volume: 0.3, range: 30 }
);
// Stop specific sound
entity.stopAudio('sounds/explosion.mp3');
// Stop all sounds on entity
entity.stopAllAudio();
// Fade out
entity.fadeAudio('music/background.mp3', 0, 2000); // Fade to 0 over 2 seconds
import { Player, UI } from 'hytopia';
// Send UI to player
player.sendUI({
type: 'panel',
id: 'hud',
position: { x: 0.5, y: 0.9 }, // Normalized screen position
anchor: 'center-bottom',
children: [
{
type: 'text',
id: 'score',
text: 'Score: 0',
style: { fontSize: 24, color: '#ffffff' }
},
{
type: 'bar',
id: 'health',
value: 100,
max: 100,
style: {
width: 200,
height: 20,
backgroundColor: '#333333',
fillColor: '#ff0000'
}
}
]
});
// Update specific element
player.updateUI('score', {
text: `Score: ${player.getData('score')}`
});
player.updateUI('health', {
value: player.getData('health'),
max: 100
});
// Remove UI
player.removeUI('hud');
player.sendUI({
type: 'panel',
id: 'menu',
children: [
{
type: 'button',
id: 'start-btn',
text: 'Start Game',
onClick: 'start-game'
},
{
type: 'button',
id: 'settings-btn',
text: 'Settings',
onClick: 'open-settings'
}
]
});
// Handle clicks
player.onUIEvent = (event) => {
if (event.elementId === 'start-btn') {
startGame(player);
} else if (event.elementId === 'settings-btn') {
openSettings(player);
}
};
assets/
├── models/
│ ├── characters/
│ ├── items/
│ └── environment/
├── textures/
│ ├── blocks/
│ ├── ui/
│ └── effects/
├── audio/
│ ├── sfx/
│ ├── music/
│ └── ambient/
└── ui/
├── hud.json
├── menu.json
└── inventory.json
import { AssetManager } from 'hytopia';
// Preload critical assets
await AssetManager.preload([
'models/player.gltf',
'textures/crosshair.png',
'sounds/jump.mp3'
]);
// Load on demand
function loadLevel(levelId: string) {
return AssetManager.loadBatch([
`levels/${levelId}/terrain.gltf`,
`levels/${levelId}/skybox.png`
]);
}
player.sendUI({
type: 'image',
id: 'crosshair',
position: { x: 0.5, y: 0.5 },
anchor: 'center-center',
source: 'textures/crosshair.png',
style: { width: 32, height: 32 }
});
function showDamageIndicator(player: Player, damage: number) {
player.sendUI({
type: 'text',
id: 'damage-text',
position: { x: 0.5, y: 0.4 },
anchor: 'center-center',
text: `-${damage}`,
style: {
fontSize: 36,
color: '#ff0000',
fontWeight: 'bold'
}
});
// Remove after delay
setTimeout(() => player.removeUI('damage-text'), 1000);
}
function showLoadingScreen(player: Player) {
player.sendUI({
type: 'panel',
id: 'loading',
fullScreen: true,
style: { backgroundColor: '#000000' },
children: [
{
type: 'text',
text: 'Loading...',
style: { fontSize: 48, color: '#ffffff' }
},
{
type: 'progress',
id: 'loading-bar',
value: 0,
max: 100,
style: { width: 400, height: 20 }
}
]
});
}
function updateLoadingProgress(player: Player, percent: number) {
player.updateUI('loading-bar', { value: percent });
if (percent >= 100) {
player.removeUI('loading');
}
}
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.