はじめに
ゲーム開発では、「ゲーム画面の中にもう一つ別の画面を作りたい」という場面があります。ゲーム内のテレビやモニター画面、ミニマップ、キャラクター選択画面のプレビュー、あるいは鏡にゲーム世界が映り込む表現——これらは「ビューポートの中にビューポート」を作る仕組みです。そうした複雑な描画を実現するのがSubViewportノードです。
SubViewportを使えば、独立した別のカメラで別のシーンを描画し、その結果をテクスチャとしてゲーム世界に埋め込むことができます。この記事では、SubViewportの基本的な使い方、セットアップ、そして実践的な活用法を詳しく解説します。
SubViewportとは?
SubViewportは、メインゲーム画面とは独立した描画領域を作るノードです。内部に独自のカメラを持ち、独立したシーンを描画した結果を「テクスチャ」として出力できます。これをSubViewportContainerに配置したり、ViewportTextureを使ってゲーム世界のオブジェクトに貼り付けたりすることで、ゲーム内の「画面」を実現します。
ゲーム画面の中に、もう一つ別のテレビやモニターが映っているイメージです。その「テレビ画面」の中では、メインゲーム画面とは別の映像が映っており、独自のカメラで制御されています。
継承ツリー:
SubViewport → Viewport → Node
Viewportを継承しており、独立した描画コンテキストを持ちます。通常、SubViewportをシーンツリーに配置し、その内部に2Dシーン(Camera2DやSprite2Dなど)を構築します。

このノードを使うべき場面
- ゲーム内のモニター・テレビ画面:セキュリティカメラの映像、テレビの放映内容。画面内に別のシーンを映す。
- ミニマップ(俯瞰カメラ):メインカメラとは別の位置から全体を俯瞰。敵の位置も一目瞭然。
- キャラクター選択画面のプレビュー:選んだキャラクターが3Dで回転しながら表示される場面。
- リアルタイムポータル・鏡:鏡に別の場所が映り込む、ポータルの先が見える表現。
別のノードが適切な場面:
- 単純なUI(スコア表示、ボタン)はCanvasLayerの方がシンプル。
- 単一のカメラでゲーム全体を描画する場合はCamera2Dで十分。
- 複雑な3D表現はSubViewportではなく、Engine全体のMultiplayerやネットワーク機能を検討。
主なプロパティと機能
| プロパティ・メソッド | 型 | 役割 |
|---|---|---|
size |
Vector2i | サブビューポートの解像度。(1024, 768)など。テクスチャ出力サイズに直結 |
render_target_update_mode |
UpdateMode enum | DISABLED/ONCE/WHEN_VISIBLE/ALWAYS。描画頻度を制御(パフォーマンス最適化に重要) |
transparent_bg |
bool | trueで背景透明。falseで背景色は使う。ミニマップ等では透明が便利 |
get_texture() → ViewportTexture |
ViewportTexture | サブビューポートの描画結果をテクスチャとして取得 |
world_2d |
World2D | サブビューポート内の2D物理世界。独立した物理シミュレーション |
GDScript コード例1:ミニマップの実装
extends Node2D
# SubViewportとその中のCamera2D
@onready var minimap_viewport = $CanvasLayer/SubViewportContainer/SubViewport
@onready var minimap_camera = $CanvasLayer/SubViewportContainer/SubViewport/Camera2D
var player: Node2D
func _ready():
player = get_tree().get_first_node_in_group("player")
# ミニマップのカメラを初期化
if minimap_camera:
minimap_camera.zoom = 0.1 # 俯瞰用に縮小
func _process(delta):
# ミニマップのカメラをプレイヤーに追従させる
if player and minimap_camera:
minimap_camera.global_position = player.global_position
GDScript コード例2:ゲーム内モニター画面の実装
extends Node
# SubViewportをテクスチャとして取得し、Sprite2Dに貼り付け
@onready var monitor_viewport = $SubViewport
@onready var monitor_sprite = $Monitor/MonitorScreen # Sprite2Dノード
func _ready():
# サブビューポートの描画結果をテクスチャ化
var viewport_texture = monitor_viewport.get_texture()
# Sprite2Dに貼り付け
if monitor_sprite:
monitor_sprite.texture = viewport_texture
# 解像度を設定
monitor_viewport.size = Vector2i(512, 384)
func _process(delta):
# サブビューポート内のカメラを制御(例:セキュリティカメラのパン)
var sub_camera = monitor_viewport.get_camera_2d()
if sub_camera:
sub_camera.global_position = Vector2(
sin(Time.get_ticks_msec() * 0.001) * 100,
0
)

もっと使いこなす:カスタマイズできるパラメータ
| パラメータ・テクニック | 変えると何が起きるか |
|---|---|
render_target_update_mode = DISABLED |
描画を停止。フレームレートが向上するが、映像は更新されない。セキュリティカメラのフリーズなど |
render_target_update_mode = ONCE |
1フレームだけ描画。静的なプレビュー画像に最適。メモリ効率良好 |
render_target_update_mode = WHEN_VISIBLE |
SubViewportContainerが画面に見える時だけ描画。パフォーマンスと見た目のバランスが良い |
render_target_update_mode = ALWAYS |
毎フレーム描画(デフォルト)。最も正確だが負荷が大きい |
transparent_bg = true |
背景を透明にして、その下のUIが見える。複数SubViewportの重ね合わせが可能 |
size を小さく設定 |
低解像度で描画。パフォーマンス向上。ミニマップなどでは十分な品質 |
まとめ
SubViewportは、ゲーム画面内に独立した「別の画面」を作り出すノードです。ミニマップ、ゲーム内モニター、鏡などのエフェクトなど、モダンなゲーム開発に欠かせない表現を実現できます。render_target_update_modeを活用すればパフォーマンスを最適化し、複数のSubViewportを組み合わせることで、より複雑で美しいビジュアルが表現できます。
- SubViewportは独立した描画領域で、独自のカメラを持つ
- size で解像度、render_target_update_mode でパフォーマンスを制御
- get_texture()で描画結果をテクスチャとして取得し、ゲーム世界に埋め込める
次回は、2D空間を効率的にタイル状に管理するTileMapについて詳しく解説します。ドット絵ゲームやマップベースのゲーム開発に不可欠なノードです。
シリーズ:Godot 4 ノード解説
- 001〜035:各種基本ノード
- 036〜075:UI・入力ノード
- 076〜085:アニメーション・制御ノード
- 086:Path2D
- 087:PathFollow2D
- 088:NavigationAgent2D
- 089:CanvasLayer
- 090:SubViewport(この記事)
- 091:TileMap
この記事はGodot 4.xをもとに執筆しています。


コメント