jpskill.com
🛠️ 開発・MCP コミュニティ

hytopia-events

HYTOPIA SDKを使ったゲームで、プレイヤーの行動やゲーム内イベント、チャットコマンド、入力操作などに対応し、イベントリスナーやゲームのライフサイクルを管理することで、ゲームをよりインタラクティブにするSkill。

📜 元の英語説明(参考)

Helps handle events and input in HYTOPIA SDK games. Use when users need to respond to player actions, game events, chat commands, or input handling. Covers event listeners, chat commands, player input, and game lifecycle events.

🇯🇵 日本人クリエイター向け解説

一言でいうと

HYTOPIA SDKを使ったゲームで、プレイヤーの行動やゲーム内イベント、チャットコマンド、入力操作などに対応し、イベントリスナーやゲームのライフサイクルを管理することで、ゲームをよりインタラクティブにするSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o hytopia-events.zip https://jpskill.com/download/9062.zip && unzip -o hytopia-events.zip && rm hytopia-events.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/9062.zip -OutFile "$d\hytopia-events.zip"; Expand-Archive "$d\hytopia-events.zip" -DestinationPath $d -Force; ri "$d\hytopia-events.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して hytopia-events.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → hytopia-events フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

HYTOPIA イベント & 入力

このスキルは、HYTOPIA SDK ゲームにおけるイベントと入力を処理するのに役立ちます。

このスキルを使うべき時

このスキルは、ユーザーが以下のようなことをしたい場合に利用します。

  • プレイヤーの行動やゲームイベントに応答したい
  • チャットコマンドを処理する必要がある
  • プレイヤーの入力(キーボード、マウス、タッチ)について知りたい
  • カスタムイベントを作成したい
  • ゲームのライフサイクルイベント(開始、終了、プレイヤーの参加/離脱)を処理する必要がある
  • イベントの優先順位付けまたはキャンセルについて知りたい

コアイベントの概念

イベントリスナー

import { World, Player } from 'hytopia';

// プレイヤーの参加をリッスン
world.onPlayerJoin = (player: Player) => {
  console.log(`${player.username} joined!`);
  player.sendMessage('Welcome to the game!');
};

// プレイヤーの離脱をリッスン
world.onPlayerLeave = (player: Player) => {
  console.log(`${player.username} left!`);
};

// プレイヤーのチャットをリッスン
world.onPlayerChat = (player: Player, message: string) => {
  console.log(`${player.username}: ${message}`);
  return true; // メッセージをブロックするには false を返す
};

チャットコマンド

import { World, Player } from 'hytopia';

world.onPlayerChat = (player: Player, message: string) => {
  if (message.startsWith('!')) {
    const args = message.slice(1).split(' ');
    const command = args[0];

    switch (command) {
      case 'help':
        player.sendMessage('Available commands: !spawn, !teleport, !kit');
        break;
      case 'spawn':
        player.setPosition({ x: 0, y: 100, z: 0 });
        player.sendMessage('Teleported to spawn!');
        break;
      case 'kit':
        giveStarterKit(player);
        break;
      default:
        player.sendMessage(`Unknown command: ${command}`);
    }

    return false; // 他のプレイヤーにコマンドをブロードキャストしない
  }

  return true; // 通常のチャットを許可
};

プレイヤー入力

import { Player, Input } from 'hytopia';

// プレイヤー入力を処理
player.onInput = (input: Input) => {
  if (input.isPressed('space')) {
    // ジャンプ
    player.applyImpulse({ x: 0, y: 10, z: 0 });
  }

  if (input.isPressed('e')) {
    // インタラクト
    handleInteraction(player);
  }

  if (input.mouseDelta.x !== 0) {
    // マウスが水平方向に移動
    player.rotation.y += input.mouseDelta.x * 0.1;
  }
};

カスタムイベント

import { EventEmitter } from 'hytopia';

// カスタムイベントエミッターを作成
const gameEvents = new EventEmitter();

// イベントタイプを定義
interface GameEvents {
  'player-kill': { killer: Player; victim: Player };
  'game-start': { map: string };
  'game-end': { winner: Player };
}

// イベントをリッスン
gameEvents.on('player-kill', ({ killer, victim }) => {
  killer.sendMessage(`You eliminated ${victim.username}!`);
  victim.sendMessage(`You were eliminated by ${killer.username}!`);
});

// イベントを発行
gameEvents.emit('player-kill', { killer: player1, victim: player2 });

入力処理のパターン

移動入力

player.onInput = (input: Input) => {
  const moveSpeed = 5;
  const moveDirection = new Vector3(0, 0, 0);

  if (input.isPressed('w')) moveDirection.z += 1;
  if (input.isPressed('s')) moveDirection.z -= 1;
  if (input.isPressed('a')) moveDirection.x -= 1;
  if (input.isPressed('d')) moveDirection.x += 1;

  if (moveDirection.length() > 0) {
    moveDirection.normalize().multiply(moveSpeed);
    player.velocity.x = moveDirection.x;
    player.velocity.z = moveDirection.z;
  }
};

マウス/クリック処理

player.onInput = (input: Input) => {
  // 左クリック
  if (input.isMousePressed(0)) {
    const raycast = world.raycast(player.position, player.lookDirection, 5);
    if (raycast.hit && raycast.entity) {
      // エンティティを攻撃
      raycast.entity.takeDamage(10);
    }
  }

  // 右クリック
  if (input.isMousePressed(1)) {
    // ブロックを配置またはアイテムを使用
    useHeldItem(player);
  }
};

ゲームライフサイクルイベント

import { Game } from 'hytopia';

const game = new Game();

game.onStart = () => {
  console.log('Game started!');
  // ゲームの状態を初期化
};

game.onEnd = () => {
  console.log('Game ended!');
  // クリーンアップ、状態を保存
};

game.onTick = (deltaTime: number) => {
  // フレームごとにゲームロジックを更新
  updateGameTimer(deltaTime);
  checkWinConditions();
};

ベストプラクティス

  1. イベントハンドラーを短く保つ - 複雑なロジックは関数に委譲する
  2. false を返してキャンセル - 必要に応じてデフォルトの動作を防止する
  3. 型付きイベントを使用 - カスタムイベントのインターフェースを定義する
  4. リスナーをクリーンアップ - エンティティが消滅したらリスナーを削除する
  5. 高速な入力をデバウンス - クールダウンでスパムを防止する

よくある間違い

  • チャットハンドラーでブール値を返すのを忘れない
  • コマンドを処理するときにすべてのチャットをブロックしない(通常のメッセージには true を返す)
  • プレイヤーがフレームの途中で切断した場合、入力が null になる可能性があることを忘れない
  • クライアント側の入力だけに頼らない - サーバーで検証する
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

HYTOPIA Events & Input

This skill helps you handle events and input in HYTOPIA SDK games.

When to Use This Skill

Use this skill when the user:

  • Wants to respond to player actions or game events
  • Needs to handle chat commands
  • Asks about player input (keyboard, mouse, touch)
  • Wants to create custom events
  • Needs to handle game lifecycle events (start, end, player join/leave)
  • Asks about event prioritization or cancellation

Core Event Concepts

Event Listeners

import { World, Player } from 'hytopia';

// Listen for player join
world.onPlayerJoin = (player: Player) => {
  console.log(`${player.username} joined!`);
  player.sendMessage('Welcome to the game!');
};

// Listen for player leave
world.onPlayerLeave = (player: Player) => {
  console.log(`${player.username} left!`);
};

// Listen for player chat
world.onPlayerChat = (player: Player, message: string) => {
  console.log(`${player.username}: ${message}`);
  return true; // Return false to block message
};

Chat Commands

import { World, Player } from 'hytopia';

world.onPlayerChat = (player: Player, message: string) => {
  if (message.startsWith('!')) {
    const args = message.slice(1).split(' ');
    const command = args[0];

    switch (command) {
      case 'help':
        player.sendMessage('Available commands: !spawn, !teleport, !kit');
        break;
      case 'spawn':
        player.setPosition({ x: 0, y: 100, z: 0 });
        player.sendMessage('Teleported to spawn!');
        break;
      case 'kit':
        giveStarterKit(player);
        break;
      default:
        player.sendMessage(`Unknown command: ${command}`);
    }

    return false; // Don't broadcast command to other players
  }

  return true; // Allow normal chat
};

Player Input

import { Player, Input } from 'hytopia';

// Handle player input
player.onInput = (input: Input) => {
  if (input.isPressed('space')) {
    // Jump
    player.applyImpulse({ x: 0, y: 10, z: 0 });
  }

  if (input.isPressed('e')) {
    // Interact
    handleInteraction(player);
  }

  if (input.mouseDelta.x !== 0) {
    // Mouse moved horizontally
    player.rotation.y += input.mouseDelta.x * 0.1;
  }
};

Custom Events

import { EventEmitter } from 'hytopia';

// Create custom event emitter
const gameEvents = new EventEmitter();

// Define event types
interface GameEvents {
  'player-kill': { killer: Player; victim: Player };
  'game-start': { map: string };
  'game-end': { winner: Player };
}

// Listen for events
gameEvents.on('player-kill', ({ killer, victim }) => {
  killer.sendMessage(`You eliminated ${victim.username}!`);
  victim.sendMessage(`You were eliminated by ${killer.username}!`);
});

// Emit events
gameEvents.emit('player-kill', { killer: player1, victim: player2 });

Input Handling Patterns

Movement Input

player.onInput = (input: Input) => {
  const moveSpeed = 5;
  const moveDirection = new Vector3(0, 0, 0);

  if (input.isPressed('w')) moveDirection.z += 1;
  if (input.isPressed('s')) moveDirection.z -= 1;
  if (input.isPressed('a')) moveDirection.x -= 1;
  if (input.isPressed('d')) moveDirection.x += 1;

  if (moveDirection.length() > 0) {
    moveDirection.normalize().multiply(moveSpeed);
    player.velocity.x = moveDirection.x;
    player.velocity.z = moveDirection.z;
  }
};

Mouse/Click Handling

player.onInput = (input: Input) => {
  // Left click
  if (input.isMousePressed(0)) {
    const raycast = world.raycast(player.position, player.lookDirection, 5);
    if (raycast.hit && raycast.entity) {
      // Attack entity
      raycast.entity.takeDamage(10);
    }
  }

  // Right click
  if (input.isMousePressed(1)) {
    // Place block or use item
    useHeldItem(player);
  }
};

Game Lifecycle Events

import { Game } from 'hytopia';

const game = new Game();

game.onStart = () => {
  console.log('Game started!');
  // Initialize game state
};

game.onEnd = () => {
  console.log('Game ended!');
  // Cleanup, save state
};

game.onTick = (deltaTime: number) => {
  // Update game logic every frame
  updateGameTimer(deltaTime);
  checkWinConditions();
};

Best Practices

  1. Keep event handlers short - delegate to functions for complex logic
  2. Return false to cancel - prevent default behavior when needed
  3. Use typed events - define interfaces for custom events
  4. Clean up listeners - remove listeners when entities despawn
  5. Debounce rapid inputs - prevent spamming with cooldowns

Common Mistakes

  • Don't forget to return boolean in chat handler
  • Don't block all chat when handling commands (return true for normal messages)
  • Don't forget input can be null if player disconnects mid-frame
  • Don't rely on client-side input alone - validate on server