5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MetaHorizonのWorldsDesktopEditorを用いた、デフォルトスクリプト(Default)とローカルスクリプト(Local)の違いについて

5
Last updated at Posted at 2025-12-16

【Meta Horizon】デフォルトスクリプトとローカルスクリプトの違いと所有権の管理

Meta Horizon WorldsのDesktop Editorを用いた開発において、特に重要な概念である「デフォルトスクリプト(Default)」と「ローカルスクリプト(Local)」の違い、およびそれに関連する所有権の挙動について紹介します。

スクリプトの種類と特徴

Worlds Desktop EditorではTypeScriptを用いて開発を行いますが、スクリプトには実行環境の異なる2つのタイプが存在します。

1. デフォルトスクリプト (Default)

新規にスクリプトを作成すると、標準でこの設定になります。

  • 実行環境: 常にサーバーで実行されます。
  • 特徴: ワールドに接続している全ユーザーに対して送受信が可能です。
  • 注意点: プレイヤーの入力がサーバーを経由して返ってくるため、操作に対して遅延(レイテンシ)が発生します

2. ローカルスクリプト (Local)

スクリプトの設定画面から「Local」を指定することで利用可能です。

  • 実行環境: エンティティの所有者(オーナー)の端末で実行されます。
  • 特徴:
    • 所有者への反映には遅延がなく、リアルタイムな応答が可能です。
    • エンティティの状態を所有者ごとに独立させることができます。
    • 所有権の移動(破棄→再生成というプロセスを経る)が可能です。
  • 注意点: 各プレイヤーに対して共通して動作させたいロジック(グローバルなゲーム進行管理など)には向きません。

イベント通信の使い分け

スクリプト間のイベント連携(イベントドリブン)には、スクリプトの種類と所有者によって使い分けが必要です。

送信元 送信先 推奨されるイベント 条件
Default / Local Default / Local LocalEvent 所有者が同じ場合のみ
Default Local NetworkEvent サーバー ⇔ クライアント間通信となるため
Local Default NetworkEvent クライアント ⇔ サーバー間通信となるため

カスタムUIとスクリプトの関係

カスタムUIはどちらのスクリプトタイプでも実装可能ですが、基本的にはローカルスクリプトでの作成を推奨します。

  • 理由: カスタムUIで動的な表示・スタイル制御を行う「Binding」機能は、頻繁に使用すると処理遅延の原因になります。
  • 影響:
    • Localの場合: 自身のスクリプト(自分のUI)にのみ影響します。
    • Defaultの場合: サーバー負荷となり、他のデフォルトスクリプトの処理まで遅延させる恐れがあります。

※ 全ユーザーに共通のUIを表示したい場合を除き、Local設定にしましょう。

スクリーンショット 2025-12-03 181851.png

ハマりポイント:親子関係にあるエンティティの所有権

Meta Horizonの仕様において、親エンティティの所有権を変更しても、子エンティティの所有権は自動的に変更されません

これが原因で、親エンティティの所有権だけを変更しても、その子として配置されているローカルスクリプト(カスタムUIなど)が表示されない・動作しないという問題が発生します。

スクリーンショット 2025-12-03 181708.png

❌ うまくいかない例

親エンティティの所有権のみを変更しているため、子エンティティがついてきません。

preStart() {
  this.connectCodeBlockEvent(
    this.entity,
    hz.CodeBlockEvents.OnPlayerEnterWorld,
    (player: hz.Player) => {
      if (this.props.localEntity) {
        // 親だけ変更しても子は変わらない
        this.props.localEntity.owner.set(player);
      }
    }
  );
}

スクリーンショット 2025-12-03 174756.png

⭕ うまくいく例(再帰的な所有権の変更)

子エンティティも含めて、再帰的に所有権を設定する処理を実装します。

static propsDefinition = {
  localEntity: { type: hz.PropTypes.Entity },
};

preStart() {
  this.connectCodeBlockEvent(
    this.entity,
    hz.CodeBlockEvents.OnPlayerEnterWorld,
    (player: hz.Player) => {
      if (this.props.localEntity) {
        // 再帰処理を呼び出す
        this.setOwnershipRecursive(this.props.localEntity, player);
      }
    }
  );
}

// 再帰的に所有権を変更するヘルパー関数
setOwnershipRecursive(targetEntity: hz.Entity, newOwner: hz.Player) {
  // 1. 自分自身の所有権を変更
  targetEntity.owner.set(newOwner);

  // 2. 子エンティティを取得し、それぞれに対して同じ処理(再帰)を行う
  const children = targetEntity.children.get();
  children.forEach(child => {
    this.setOwnershipRecursive(child, newOwner);
  });
}

スクリーンショット 2025-12-03 175117.png

補足:Asset利用時のヒント

ローカルスクリプトは、ログインしたユーザーとセットでエンティティを利用するケースが多いため、PropTypes.Assetで指定したアセットを spawnAsset で動的に生成し、その生成したエンティティに対して所有権を渡す実装パターンも有効です。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?