同じステージを2人で歩き回り、一方はスイッチを押し、もう一方は開いた扉を通る。そんな協力プレイを、1台のPCで試してみましょう。
UE5には、プレイヤーの人数に応じて画面を分ける仕組みがあります。今回はThird Personテンプレートに2人目を加え、1Pはキーボードとマウス、2Pはゲームパッドで操作できるようにします。最後に、それぞれの画面の左上へ名前とHPバーを出します。

この記事でわかること
- 1つのゲーム画面を左右に分け、2人で別々に歩く
- キーボードとゲームパッドを別のプレイヤーへ割り当てる
- 1P・2Pそれぞれの画面に、自分用のUIを表示する
世界は1つ、見る位置は2つ
画面を分割しても、ステージが2つに増えるわけではありません。同じステージを、2台のカメラでそれぞれ映します。 1Pが箱の裏へ回り込めば、2Pの画面からはその姿が隠れます。箱も、2人のキャラクターも、同じ世界に存在しています。

このとき、UEでは次の3つをプレイヤーごとに扱います。
| 名前 | 今回の役割 |
|---|---|
| Local Player | このPCで参加しているプレイヤー。画面を分ける単位になる |
| Player Controller | そのプレイヤーの入力を受け取り、操作するキャラクターを管理する |
| Pawn | 実際にステージ内を動く体。今回はThird Personのキャラクター |
「Controller」という名前でも、Player Controllerは手に持つゲームパッドそのものではありません。 キーボードで遊ぶ1Pにも、ゲームパッドで遊ぶ2Pにも、それぞれPlayer Controllerがありま す。
Create Local Player は、このゲームに参加者を1人追加するノードです。Third Personテンプレートのキャラクターとカメラを使えば、追加したプレイヤーも自分のキャラクターを映しながら動けます。C++の関数名は CreatePlayer なので、資料によっては「Create Player」と表記されています。
2人で遊ぶ準備をする
今回は、Windows版のUE5.5以降で作った、BlueprintのThird Personテンプレートを使います。まず1人で歩く・視点を動かす操作ができ、接続したゲームパッドもUEから認識されている状態にしてください。テンプレートの移動処理や入力設定は、そのまま利用します。
スタート地点を2つ置く
レベル内の Player Start を2つにします。これは、プレイヤーのキャラクターを出現させる候補地点です。床の少し上に置き、互いのカプセルが重ならないように離してください。
キャラクターをもう1体レベルへ直接置く必要はありません。Third PersonのGameModeが、設定された Default Pawn Class をもとにキャラクターを生成します。独自のレベルで試す場合は、「World Settings」の「GameMode Override」がThird Person用のGameModeになっていることも確認します。
画面分割とゲームパッドの割り当てを設定する
「Project Settings」→「Maps & Modes」→「Local Multiplayer」で、次のように設定します。
| 設定 | 今回の値 | 意味 |
|---|---|---|
| Use Splitscreen | オン | 複数のローカルプレイヤーで画面を分ける |
| Two Player Splitscreen Layout | Vertical | 画面を左右に分ける |
| Skip Assigning Gamepad to Player 1 | オン | 最初のゲームパッドを1Pへ割り当てず、2Pから使う |
最後の設定が、今回の「キーボードで1P、ゲームパッドで2P」に必要です。オフのままだと、キーボードと最初のゲームパッドが同じ1Pを操作することがあります。画面を分けただけでは、入力まで希望どおりに分かれるとは限りません。

実行時の人数は「1」のままにする
エディタのプレイ設定では「Number of Players」を 1、「Net Mode」を Play Standalone にし、「Standalone Game」で起動します。
この「Number of Players」は、主にネットワークプレイを試すための設定です。今回はゲームを1つ起動し、その中にノードで2人目を追加します。ここを2にして別のゲームウィンドウを増やす必要はありません。
2人目を追加して歩いてみる
プレイヤーを追加するためのActorを1つ作ります。今回は、同じマップで2人プレイを始めるところに絞ります。
- Actorを親クラスにしたBlueprint BP_LocalCoopSetup を作り、レベルへ 1つだけ 配置します。
- SecondPlayer という変数を作ります。型は Player ControllerのObject Reference、初期値は
Noneにします。 - Event Graphで、
Event BeginPlay → Create Local Player → Set SecondPlayerと白い実行線をつなぎます。 - Create Local Playerの「Controller Id」を -1、「Spawn Player Controller」を オンにします。
- Create Local Playerの Return Value を、Set SecondPlayerの値へつなぎます。

Object Reference(参照) は、「作ったどのPlayer Controllerか」を後から指定するためのものです。Return Valueに返された2人目をSecondPlayerへ保存しておけば、後で2PのUIを作るときにも同じ相手を指定できます。None は、まだ相手が入っていない状態です。
Controller Idの -1 は「次の空きIDを選ぶ」という指定です。一方、Spawn Player Controllerは、追加時にPlayer Controllerを作るかどうかの設定です。今回はすぐに操作したいのでオンにします。
続けて、SecondPlayerから実行ピン付きの Is Valid へつなぎます。これは、参照先を今使えるか確かめるノードです。
- Set SecondPlayerの実行出力 → Is Validの実行入力
- Get SecondPlayer → Is Validの「Input Object」
- 「Is Not Valid」→ Print Stringで「2Pの作成に失敗」と表示
- 「Is Valid」は、今の段階では未接続で構いません。後でUIの作成をつなぎます。

コンパイルしてStandalone Gameで起動すると、画面が左右に分かれます。キーボードで1P、ゲームパッドで2Pを動かしてみてください。一方を動かしたときに、もう一方のキャラクターまで一緒に動かなければ、入力も分かれています。
2人で同じ箱の周りを歩いてみると、「世界は1つ、見る位置は2つ」という関係がよく分かります。ここまでで、画面分割の土台はできました。
入力の設定も、各プレイヤーが持つ
Third Personテンプレートでは、Input Mapping Context に「どのキーやボタンで、移動やジャンプをするか」が登録されています。これを使えるようにするのが Add Mapping Context です。
入力を受け持つ Enhanced Input Local Player Subsystem は、プレイヤーごとの入力設定の管理場所です。名前は長いですが、ここでは「1P用と2P用が別々にある」と押さえれば十分です。
元のテンプレートで2人とも動くなら、追加の入力ノードは不要です。入力処理を改造済みで2Pだけ動かない場合は、既存のAdd Mapping Contextが 操作する本人のPlayer Controllerから取得したSubsystem を対象にしているか確認します。キャラクター内なら Get Controller、Player Controller内なら Self が本人を指します。
毎回 Get Player Controller(Player Index = 0) を使うと、2Pを準備しているつもりでも1P側の設定を触ってしまいます。なお、Player Indexは一覧の順番、Controller Idは入力側のIDです。今回の2Pは、番号 から探し直さずSecondPlayerで指定します。
自分の画面にUIを出す仕組み
2人とも歩けたら、それぞれの画面に名前とHPバーを付けましょう。ここで必要なのは、誰のUIを作るかと、どこへ表示するかの2つです。
| ノード・入力 | 指定すること |
|---|---|
| Create Widgetの Owning Player | このUIの持ち主となるPlayer Controller |
| Add to Player Screen | 持ち主に割り当てられた画面の領域へ表示する |
いつもの Add to Viewport は、ゲームウィンドウ全体を基準にUIを配置します。たとえば1P用と2P用のUIを両方「左上」に置くと、ウィンドウ左上で重なることがあります。自動で各画面に1つずつ配られるわけではありません。
Add to Player Screenなら、同じ「左上」の設定でも、1PのUIは左側の画面、2PのUIは右側の画面の左上に配置されます。画面の分割を上下に変えたときも、それぞれの領域を基準に配置できます。

ただし、持ち主を指定しても、名前やHPが自動で入るわけではありません。 「誰の画面に出すか」と「何を表示するか」は別です。次は1Pへ「1P・75%」、2Pへ「2P・40%」を渡し、表示先と内容が対応していることを確かめます。
実践:1Pと2Pに名前とHPバーを付ける
完成すると、各画面の左上に名前と青いバーが1組ずつ表示されます。今回は、バーの見た目を確かめる固定値を使います。ダメージでHPを減らす処理は、この記事ではまだ加えません。
1. 名前とバーを置く
Widget Blueprint WBP_PlayerHUD を作り、Designerで次の階層にします。
Canvas Panel
└─ Size Box(Width Override = 240)
└─ Border(Padding = 12)
└─ Vertical Box
├─ Text Block:PlayerText
└─ Size Box(Height Override = 16)
└─ Progress Bar:HealthBar
外側のSize Boxは、Canvas Panel SlotのAnchorsを 左上、Positionを X=16・Y=16、Alignmentを X=0・Y=0、Auto Sizeを オンにします。内側のSize Boxは、Vertical Box Slotの横方向を「Fill」にしてバーの幅を確保します。
PlayerTextとHealthBarは、名前を変更して Is Variable をオンにしてください。これでGraphから「どの文字・どのバーを変更するか」を指定できます。
PlayerTextの文字を仮に「1P」、HealthBarの「Percent」を 0.75 にすると、Designerで見た目を確かめられます。背景は薄い灰色、バーは青など、空き部分と残りの量を見分けられる色にします。
Percentは0〜1で表す割合です。0なら空、1なら満タン、0.75なら4分の3が埋まり ます。75%を表示するときに、数値の75をそのまま入れないようにしましょう。

2. 渡された名前と割合を表示する
WBP_PlayerHUDに ConfigureHUD という関数を作り、次の入力を追加します。これは「このUIへ、名前とバーの割合をセットする」ための関数です。
| 入力名 | 型 | 受け取るもの |
|---|---|---|
| InLabel | Text | 「1P」または「2P」 |
| InRatio | Float | 0.75や0.4といった割合 |
関数の入力は、入口ノードの出力ピンからつなぐか、関数内で右クリックして Get InLabel・Get InRatio を検索すると取り出せます。図では配線を見やすくするためGetを使います。新しい変数を作る必要はありません。
関数の入口から、次の順に実行線をつなぎます。
- Set Text:PlayerTextのGetを「Target」、InLabelを「In Text」へつなぎます。
- Set Percent:HealthBarのGetを「Target」へつなぎます。InRatioは Clamp (Float) へ渡し、Min=0・Max=1にして、そのReturn Valueを「In Percent」へつなぎます。

Clampは、値を指定した範囲に収めるノードです。今回は0〜1の範囲にして、バーへ渡します。コンパイルして保存してください。

3. 持ち主を指定してUIを作る
BP_LocalCoopSetupへ戻り、AddHUDForPlayer という関数を作ります。1Pと2Pで同じ手順を使えるように、持ち主・名前・割合を入力で受け取ります。
| 入力名 | 型 |
|---|---|
| OwnerController | Player ControllerのObject Reference |
| PlayerLabel | Text |
| HealthRatio | Float |
最初に、実行ピン付きのIs ValidへOwnerControllerを渡します。「Is Not Valid」はPrint Stringで「HUDの持ち主が見つかりません」と表示して終了し、「Is Valid」から次へ進みます。
- Create WidgetのClassにWBP_PlayerHUDを選び、「Owning Player」へOwnerControllerをつなぎます。
- そのReturn Valueから ConfigureHUD を呼び出します。「In Label」へPlayerLabel、「In Ratio」へHealthRatioを渡します。
- 続けて Add to Player Screen を呼びます。「Target」は、同じCreate WidgetのReturn Valueです。「Z Order」は0で構いません。

ここでのCreate WidgetのReturn Valueは、今作ったUIそのものです。ConfigureHUDとAdd to Player Screenの両方に、同じUIを渡します。Classは「どの種類を作るか」、Return Valueは「実際に作ったもの」という違いです。

Add to Player ScreenのReturn ValueはBooleanで、表示の成否を返します。実行出力をBranchへ、Return ValueをそのConditionへつなぎ、False側はPrint Stringで「HUDの表示に失敗」と出してください。True側で、この関数の処理は終わりです。

4. 1Pと2PのUIを順に作る
BP_LocalCoopSetupのEvent Graphへ戻ります。2人目を追加した後のIs Validで、空けておいた 「Is Valid」側 にAddHUDForPlayerを2つ、順に接続します。
| 呼び出す順 | Owner Controller | Player Label | Health Ratio |
|---|---|---|---|
| 1回目 | Get Player Controller(Player Index=0)のReturn Value | 1P | 0.75 |
| 2回目 | Get SecondPlayer | 2P | 0.4 |

Player Index=0は、今回最初から参加している1Pを取得するために使います。2Pは、Create Local Playerで返されたSecondPlayerを使います。

起動し直し、左の画面に「1P」と4分の3のバー、右の画面に「2P」と4割のバーがあれば成功です。どちらも、自分の画面の左上に出ていることを確かめてください。
試しに2回目のHealth Ratioだけを 0.4 → 0.2 に変えて、もう一度起動してみましょう。1Pのバーは変わらず、2Pのバーだけ短くなります。同じWidget Blueprintを使っていても、作ったUIは別々なので、それぞれへ違う値を渡せます。
実際のHPと連動させるときも考え方は同じです。持ち主が操作しているキャラクターのHPを読み、そのUIへ渡します。Widget内では Get Owning Player Pawn で持ち主のPawnを取得できます。HPの持たせ方とダメージ処理は、体力とダメージ入門を参考にしてください。
うまく動かないとき
画面が分かれない・2Pのキャラクターが出ない
まず、BP_LocalCoopSetupがレベルに1つ配置されているか、BeginPlayからCreate Local Playerまで実行線がつながっているかを確認します。「2Pの作成に失敗」が出たら、Return Valueが使える状態になっていません。
SecondPlayerが有効なら、次にSecondPlayerから Get Controlled Pawn を取得してIs Validで確認します。こちらが無効なら、GameModeのDefault Pawn Classや、Player Startが壁・床・別のキャラクターと重なっていないかを調べます。
Pawnも有効なのに表示がおかしい場合は、キャラクターのカメラ設定とUse Splitscreenを確認します。「画面が黒いからPlayer Start不足」と決めつけず、Controller → Pawn → カメラ・表示設定の順に確かめると、直す場所を絞れます。
2Pだけ動かない・ゲームパッドでも1Pが動く
ゲームパッドが認識され、起動したゲームウィンドウにフォーカスがあることを確認します。そのうえで、Skip Assigning Gamepad to Player 1がオンか、2P自身のSubsystemにInput Mapping Contextが追加されているか、そのContextにゲームパッドのキーが登録されているかを見ます。
古いUEでは、このゲームパッド割り当て設定に既知の不具合もあります。まず記事の条件に合わせてUE5.5以降の新規Third Personで試すと、独自の入力処理と の切り分けがしやすくなります。
UIが重なる・両方とも同じHPになる
表示位置の問題なら、Create WidgetのOwning Playerと、Add to Player ScreenのTargetを確認します。1Pと2Pで別々にCreate Widgetを呼び、各自のPlayer Controllerを持ち主に指定できているかを見てください。
位置は正しくても両方とも75%なら、渡しているHealth Ratioを確認します。持ち主の設定からHPを推測して表示してくれるわけではありません。ConfigureHUDの入力と、Set Percentまでの接続をたどりましょう。
おまけ:画面の向きと、その先の作り方
上下分割に変えてみる
Two Player Splitscreen Layoutを Horizontal にすると上下分割になります。Verticalは左右、Horizontalは上下です。左右に分けると各画面は縦長に、上下に分けると横長になります。
今回作ったHUDは各プレイヤーの領域を基準に置くので、上下に変えた後も、それぞれの画面の左上に収まるか試せます。遠くの敵を見つけやすいか、足元が見切れないか、UIが邪魔にならないかを実際に歩いて比べ、ゲームに合う向きを選びましょう。
人数・処理負荷・オンラインは別に考える
今回は、ゲームを新しく起動するたびに、最初の1Pへ2Pを1人追加する構成です。途中参加やレベル遷移を取り入れるときは、すでにいるプレイヤーを重ねて追加しない管理が必要になります。
また、カメラが2つになると描画の仕事も増えます。ただし、処理時間が常にちょうど2倍になるわけではありません。1人のときと2人のときで、同じ場所を映して動作の重さを比べます。
この実践は、1台のPC内で同じ世界を共有するものです。別のPC同士をつなぐオン ラインプレイには、相手へゲームの状態を伝える仕組みが必要になります。まずは2人で同じ箱の周りを歩く、別々のスイッチを押すといった、小さな協力プレイから広げていくと作りやすくなります。
まとめ
Create Local Playerで参加者を追加し、画面分割を有効にすると、1つのステージをそれぞれのカメラから見られます。キーボードとゲームパッドを使う今回は、入力の割り当ても合わせて設定しました。
UIは 持ち主を決めて作り、その人の値を渡し、Add to Player Screenで表示するという順です。この3つを分けて考えると、同じHUDを使いながら、1Pと2Pそれぞれの状態を表示できます。