hytopia-physics
HYTOPIA SDKゲームで、剛体や衝突判定、レイキャスト、力、物理演算に基づいたゲームプレイなどを実装したい場合に、PhysicsComponentやコライダーなどを活用して物理演算を組み込むのを支援するSkill。
📜 元の英語説明(参考)
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.
🇯🇵 日本人クリエイター向け解説
HYTOPIA SDKゲームで、剛体や衝突判定、レイキャスト、力、物理演算に基づいたゲームプレイなどを実装したい場合に、PhysicsComponentやコライダーなどを活用して物理演算を組み込むのを支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o hytopia-physics.zip https://jpskill.com/download/9066.zip && unzip -o hytopia-physics.zip && rm hytopia-physics.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/9066.zip -OutFile "$d\hytopia-physics.zip"; Expand-Archive "$d\hytopia-physics.zip" -DestinationPath $d -Force; ri "$d\hytopia-physics.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
hytopia-physics.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
hytopia-physicsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
HYTOPIA Physics & Collision
このスキルは、HYTOPIA SDK ゲームで物理演算と衝突判定を実装するのに役立ちます。
このスキルを使用する場面
このスキルは、ユーザーが以下のようなことをしたい場合に利用します。
- エンティティに物理演算(重力、速度、力)を追加したい
- オブジェクト間の衝突判定が必要
- ヒット検出のためのレイキャスティングについて知りたい
- 物理演算に基づいたゲームプレイ(投射物、爆発)を作成したい
- コライダー(ボックス、球、メッシュ)を設定する必要がある
- 物理マテリアル(摩擦、反発力)について知りたい
コアとなる物理演算の概念
エンティティへの物理演算の追加
import { Entity, PhysicsComponent, BoxCollider } from 'hytopia';
class PhysicsEntity extends Entity {
constructor() {
super();
this.addComponent(new PhysicsComponent({
mass: 1.0, // キログラム
gravity: { x: 0, y: -9.81, z: 0 },
linearDamping: 0.1, // 空気抵抗
angularDamping: 0.1,
useGravity: true
}));
// 衝突形状を追加
this.addComponent(new BoxCollider({
size: { x: 1, y: 1, z: 1 },
offset: { x: 0, y: 0.5, z: 0 }
}));
}
}
コライダーの種類
import { BoxCollider, SphereCollider, MeshCollider } from 'hytopia';
// ボックスコライダー
const box = new BoxCollider({
size: { x: 2, y: 1, z: 0.5 },
offset: { x: 0, y: 0, z: 0 }
});
// 球コライダー
const sphere = new SphereCollider({
radius: 0.5,
offset: { x: 0, y: 0.5, z: 0 }
});
// メッシュコライダー(モデルから)
const mesh = new MeshCollider({
modelUri: 'models/terrain.gltf',
convex: false // false = 正確なメッシュ, true = 凸包 (より高速)
});
力の適用
import { Entity, PhysicsComponent } from 'hytopia';
class Projectile extends Entity {
physics: PhysicsComponent;
constructor() {
super();
this.physics = new PhysicsComponent({
mass: 0.1,
useGravity: true
});
this.addComponent(this.physics);
}
launch(direction: Vector3, force: number) {
// インパルス(瞬間的な力)を適用
this.physics.applyImpulse(direction.multiply(force));
// または、継続的な力を適用
this.physics.applyForce(direction.multiply(force));
// トルク(回転)を適用
this.physics.applyTorque({ x: 0, y: 100, z: 0 });
}
}
レイキャスティング
基本的なレイキャスト
import { World } from 'hytopia';
// ある点からある方向へのレイキャスト
const result = world.raycast(
{ x: 0, y: 10, z: 0 }, // 原点
{ x: 0, y: -1, z: 0 }, // 方向 (正規化済み)
100 // 最大距離
);
if (result.hit) {
console.log('Hit at:', result.position);
console.log('Hit entity:', result.entity);
console.log('Hit normal:', result.normal);
console.log('Hit distance:', result.distance);
}
プレイヤーの視線レイキャスト
// プレイヤーは何を見ているか?
const raycast = world.raycast(
player.position,
player.lookDirection,
5 // リーチ距離
);
if (raycast.hit) {
if (raycast.block) {
// ブロックを見ている
console.log('Block:', raycast.block.type);
}
if (raycast.entity) {
// エンティティを見ている
console.log('Entity:', raycast.entity.id);
}
}
衝突判定
衝突イベント
import { Entity, CollisionComponent } from 'hytopia';
class CollidableEntity extends Entity {
constructor() {
super();
const collision = new CollisionComponent();
collision.onCollisionEnter = (other) => {
console.log('Started colliding with:', other.id);
if (other instanceof Projectile) {
this.takeDamage(10);
}
};
collision.onCollisionExit = (other) => {
console.log('Stopped colliding with:', other.id);
};
collision.onCollisionStay = (other) => {
// 衝突中に毎フレーム呼び出される
};
this.addComponent(collision);
}
}
衝突レイヤー
import { PhysicsComponent, CollisionLayer } from 'hytopia';
// 何と何が衝突するかを定義
const physics = new PhysicsComponent({
mass: 1,
collisionLayer: CollisionLayer.DEFAULT,
collisionMask: CollisionLayer.DEFAULT | CollisionLayer.PLAYER
});
// レイヤー: DEFAULT, PLAYER, ENEMY, PROJECTILE, TRIGGER, etc.
// プレイヤーは他のプレイヤーとは衝突しないが、敵とは衝突する
const playerPhysics = new PhysicsComponent({
collisionLayer: CollisionLayer.PLAYER,
collisionMask: CollisionLayer.DEFAULT | CollisionLayer.ENEMY | CollisionLayer.PROJECTILE
});
物理マテリアル
import { PhysicsMaterial } from 'hytopia';
const bouncyMaterial = new PhysicsMaterial({
friction: 0.5, // 0 = 滑りやすい, 1 = 粗い
restitution: 0.8, // 0 = 反発しない, 1 = 完全に反発する
density: 1.0 // 質量計算に影響
});
const iceMaterial = new PhysicsMaterial({
friction: 0.1,
restitution: 0.1
});
// コライダーに適用
const collider = new BoxCollider({
size: { x: 1, y: 1, z: 1 },
material: bouncyMaterial
});
ベストプラクティス
- シンプルなコライダーを使用する - Box/Sphere は Mesh よりも高速です
- 適切な質量を設定する - 現実的な値 (kg) が最適です
- レイヤーを賢く使用する - 衝突をフィルタリングしてパフォーマンスを向上させます
- スポーン前にレイキャストする - スペースが空いているか確認します
- 非アクティブなボディをスリープさせる - 静止オブジェクトの CPU を節約します
一般的なパターン
接地判定
function isGrounded(entity: Entity): boolean {
const raycast = world.raycast(
entity.position,
{ x: 0, y: -1, z: 0 },
0.1 // エンティティの真下の小さな距離
);
return raycast.hit && raycast.distance < 0.05;
}
// 使用例
if (isGrounded(player) && input.isPressed('space')) {
player.physics.applyImpulse({ x: 0, y: 10, z: 0 });
}
爆発力
function applyExplosion(center: Vector3, radius: number, force: number) {
// 半径内のすべてのエンティティを取得
const entities = world.getEntitiesInRadius(center, radius);
for (const entity of entities) {
const direction = entity.position.subtract(center).normalize(); 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
HYTOPIA Physics & Collision
This skill helps you implement physics and collision in HYTOPIA SDK games.
When to Use This Skill
Use this skill when the user:
- Wants to add physics to entities (gravity, velocity, forces)
- Needs collision detection between objects
- Asks about raycasting for hit detection
- Wants to create physics-based gameplay (projectiles, explosions)
- Needs to configure colliders (boxes, spheres, meshes)
- Asks about physics materials (friction, bounciness)
Core Physics Concepts
Adding Physics to Entity
import { Entity, PhysicsComponent, BoxCollider } from 'hytopia';
class PhysicsEntity extends Entity {
constructor() {
super();
this.addComponent(new PhysicsComponent({
mass: 1.0, // Kilograms
gravity: { x: 0, y: -9.81, z: 0 },
linearDamping: 0.1, // Air resistance
angularDamping: 0.1,
useGravity: true
}));
// Add collision shape
this.addComponent(new BoxCollider({
size: { x: 1, y: 1, z: 1 },
offset: { x: 0, y: 0.5, z: 0 }
}));
}
}
Collider Types
import { BoxCollider, SphereCollider, MeshCollider } from 'hytopia';
// Box collider
const box = new BoxCollider({
size: { x: 2, y: 1, z: 0.5 },
offset: { x: 0, y: 0, z: 0 }
});
// Sphere collider
const sphere = new SphereCollider({
radius: 0.5,
offset: { x: 0, y: 0.5, z: 0 }
});
// Mesh collider (from model)
const mesh = new MeshCollider({
modelUri: 'models/terrain.gltf',
convex: false // false = exact mesh, true = convex hull (faster)
});
Applying Forces
import { Entity, PhysicsComponent } from 'hytopia';
class Projectile extends Entity {
physics: PhysicsComponent;
constructor() {
super();
this.physics = new PhysicsComponent({
mass: 0.1,
useGravity: true
});
this.addComponent(this.physics);
}
launch(direction: Vector3, force: number) {
// Apply impulse (instant force)
this.physics.applyImpulse(direction.multiply(force));
// Or apply continuous force
this.physics.applyForce(direction.multiply(force));
// Apply torque (rotation)
this.physics.applyTorque({ x: 0, y: 100, z: 0 });
}
}
Raycasting
Basic Raycast
import { World } from 'hytopia';
// Raycast from point in direction
const result = world.raycast(
{ x: 0, y: 10, z: 0 }, // Origin
{ x: 0, y: -1, z: 0 }, // Direction (normalized)
100 // Max distance
);
if (result.hit) {
console.log('Hit at:', result.position);
console.log('Hit entity:', result.entity);
console.log('Hit normal:', result.normal);
console.log('Hit distance:', result.distance);
}
Player Look Raycast
// What is player looking at?
const raycast = world.raycast(
player.position,
player.lookDirection,
5 // Reach distance
);
if (raycast.hit) {
if (raycast.block) {
// Looking at a block
console.log('Block:', raycast.block.type);
}
if (raycast.entity) {
// Looking at an entity
console.log('Entity:', raycast.entity.id);
}
}
Collision Detection
Collision Events
import { Entity, CollisionComponent } from 'hytopia';
class CollidableEntity extends Entity {
constructor() {
super();
const collision = new CollisionComponent();
collision.onCollisionEnter = (other) => {
console.log('Started colliding with:', other.id);
if (other instanceof Projectile) {
this.takeDamage(10);
}
};
collision.onCollisionExit = (other) => {
console.log('Stopped colliding with:', other.id);
};
collision.onCollisionStay = (other) => {
// Called every frame while colliding
};
this.addComponent(collision);
}
}
Collision Layers
import { PhysicsComponent, CollisionLayer } from 'hytopia';
// Define what collides with what
const physics = new PhysicsComponent({
mass: 1,
collisionLayer: CollisionLayer.DEFAULT,
collisionMask: CollisionLayer.DEFAULT | CollisionLayer.PLAYER
});
// Layers: DEFAULT, PLAYER, ENEMY, PROJECTILE, TRIGGER, etc.
// Player doesn't collide with other players but collides with enemies
const playerPhysics = new PhysicsComponent({
collisionLayer: CollisionLayer.PLAYER,
collisionMask: CollisionLayer.DEFAULT | CollisionLayer.ENEMY | CollisionLayer.PROJECTILE
});
Physics Materials
import { PhysicsMaterial } from 'hytopia';
const bouncyMaterial = new PhysicsMaterial({
friction: 0.5, // 0 = slippery, 1 = rough
restitution: 0.8, // 0 = no bounce, 1 = perfect bounce
density: 1.0 // Affects mass calculation
});
const iceMaterial = new PhysicsMaterial({
friction: 0.1,
restitution: 0.1
});
// Apply to collider
const collider = new BoxCollider({
size: { x: 1, y: 1, z: 1 },
material: bouncyMaterial
});
Best Practices
- Use simple colliders - Box/Sphere are faster than Mesh
- Set appropriate mass - Realistic values (kg) work best
- Use layers wisely - Filter collisions to improve performance
- Raycast before spawning - Check if space is clear
- Sleep inactive bodies - Saves CPU for stationary objects
Common Patterns
Ground Check
function isGrounded(entity: Entity): boolean {
const raycast = world.raycast(
entity.position,
{ x: 0, y: -1, z: 0 },
0.1 // Small distance below entity
);
return raycast.hit && raycast.distance < 0.05;
}
// Usage
if (isGrounded(player) && input.isPressed('space')) {
player.physics.applyImpulse({ x: 0, y: 10, z: 0 });
}
Explosion Force
function applyExplosion(center: Vector3, radius: number, force: number) {
// Get all entities in radius
const entities = world.getEntitiesInRadius(center, radius);
for (const entity of entities) {
const direction = entity.position.subtract(center).normalize();
const distance = entity.position.distance(center);
const falloff = 1 - (distance / radius); // Stronger closer to center
if (entity.physics) {
entity.physics.applyImpulse(
direction.multiply(force * falloff)
);
}
}
}