近年、土木分野ではICTの発展と普及が進み、BIM/CIMと連携したAR(拡張現実)の導入が広がっています。設計や施工段階での合意形成から検査業務、教育まで、活用範囲は急速に拡大中です。本記事では、土木現場におけるAR導入のメリットや位置づけ、導入方法を紹介します。
AR導入のメリット
ARを導入することで、従来の図面では難しかった理解や共有が容易になり、現場業務の効率化や安全性向上に役立ちます。ここでは、AR導入のメリットを具体的にご紹介します。
合意形成を迅速化
ARは、現地の環境に3Dモデルを重ね合わせて表示することで、完成形やリスクを直感的に伝えられます。発注者や受注者、地域住民の方も同じ映像を共有できるため、設計不整合や干渉、生活環境への影響を早期に発見でき、協議のスピード向上につながるのが大きなメリットです。
検査・出来形確認の効率化
位置精度の高いARを使えば、現場でモデルと実物を照合しながら確認ができます。移動や採寸、再確認といった手戻りを削減できる点は大きなメリットです。
これは、国土交通省がBIM/CIM活用項目として掲げている「監督・検査の効率化」「変更協議の省力化」「対外説明」にも直結します。
教育・広報での活用
展示施設や体験エリアでのAR投影は、完成物の理解を深めるのに有効です。施工ミスや安全教育の再現にも利用でき、説明のわかりやすさを高めるほか、研修における危険を察知の向上にも役立ちます。
教育現場や広報活動に活用すれば、理解促進や普及啓発にもつながるでしょう。
BIM/CIMにおけるARの位置づけ
ARは、さまざまな課題を解決する革新的な技術です。ここでは、BIM/CIMにおけるARの位置づけを整理し、具体的な役割を解説します。
BIM/CIMの全体像
BIM/CIMは、調査・設計・施工・維持管理の各段階で3Dモデルを中心に情報を共有する取り組みです。国土交通省は段階的に適用を拡大し、令和5年度から小規模を除くすべての公共工事で原則適用としました。
これにより、さらなるBIM/CIMの効率的な活用とともに、アナログな制度からデジタル技術を前提とした制度へと変革が進んでいます。
ARの役割
この流れの中で、ARは統合モデル(IFCやLandXMLなど)を現地に展開するための可視化インターフェースとなります。施工工程や品質確認、関係者への説明を現場で支援する有効な手段であり、意思決定の精度向上にもつながるでしょう。
さらに、設計・施工ワークフローの中で現物とモデルを重ねて判断する活用が定着しつつあります。
ARによる現場での最終活用段階
ARは、BIM/CIMで整備された情報を現場で直接活用する最終段階といえるでしょう。机上での検討にとどまらず、現場に展開してこそ価値が発揮されます。施工中の意思決定を早め、合意形成や検査の信頼性を高める役割を果たしています。
つまりARは、BIM/CIMの「最後の1mm」、設計と施工をつなぐ橋渡しとなる重要な位置付けです。
プロジェクトの開始方法とプラグイン周り(Android/マーカー式AR)
ARを導入する際には、実際の環境に即した構築が大切です。ここでは、ゲームエンジン「Unity」を用いてAndroid端末でマーカー式ARを構築し、実際に動作させるまでの手順を紹介します。
仕様は次のものを使用します。
- 出現モデル:1つ
- 出現トリガー:事前に準備するマーカー
- モデル位置:マーカーに依存する
ここから順番に説明していきます。
1.Unityを用いた環境構築
AR開発を始めるには、Unityで基礎的な作業環境を整える必要があります。以下の手順に沿って設定します。
①新規プロジェクトの作成

Unity Hubを起動し、「New Project」を選択します。テンプレートは「3D」(URPでも可)を指定し、名称は「CIM_AR_Marker」など英数字のみを用いて設定します。プロジェクト作成後、「File>Build Settings」を開き、プラットフォームを「Android」に切り替えて「Switch Platform」を実行します。これにより、以降の開発環境がAndroid向けに最適化されます。
②必要パッケージの導入(Package Manager)

「Window>Package Manager」を開き、「AR Foundation」と「ARCore XR Plugin」をインストールします。これら2つのパッケージで、画像マーカーの認識やモデル描画に必要な機能が整います。基本構成として必要なのは、この2点の導入です。
③XR Plug-in Managementの設定
「Edit>Project Settings>XR Plug-in Management」を開き、Androidタブで「ARCore」にチェックを入れます。続いて、「ARCore Settings」で「Require(AR必須)」を有効にしておくと、非対応端末での誤動作を防げます。この設定によって、AR動作環境の信頼性が確保されます。
④Android Player設定(要点)
「Edit>Project Settings>Player>Android」を開き、各項目を以下のように調整します。
- Minimum API Level:Android 7.0以上を推奨
- Scripting Backend:IL2CPP
- Target Architectures:ARM64(Play配布時に必須)
- Graphics APIs:OpenGLES3(Vulkanでも可)
画面の向きは任意ですが、Portrait(縦固定)が扱いやすく推奨されています。これらの設定により、ビルド後の実行安定性が向上します。
⑤シーン初期化

ヒエラルキーに「AR Session」と「XR Origin」が配置されていることを確認します。XR Origin配下のカメラがAR表示用カメラとなり、空間認識の中心点を担います。XR OriginのInspector最下部から「Add Component>AR Tracked Image Manager」を追加し、マーカー検出機能を付与します。

次に、Projectビュー内で右クリックし「Create>XR>Reference Image Library」を作成します。ここに印刷予定のマーカー画像と実寸幅(m)を登録します。画像は高コントラストで模様が豊富なものが望ましく、重複を避けることで認識精度が向上します。これにより、「Android+マーカー検出でモデルを出す」環境が構築されます。
2.モデルデータの準備
BIM/CIMで作成した3DモデルをUnityで扱う場合、形式はIFCやLandXMLからFBXまたはglTF(.glb推奨)に変換します。
Unityは1ユニット=1mで処理されるため、モデルの実寸スケールでエクスポートする方法がベストです。変換時にスケール倍率が入る可能性があるため、DCC側(Revit/InfraWorks/3Dツールなど)>エクスポート設定>Unity上のImport Settingsでスケールを調整し、実寸に合わせます。
モデル原点はマーカー原点(0,0,0)と一致させておくと配置が正確です。
3.取り込み・配置・呼び起こし
モデルの取り込み、配置・呼び起こし(マーカーを原点に出現)を説明します。
①モデルの取り込み
「ProjectAssets」内にCreate>Folderで「Models」フォルダーを作成し、変換したモデルをインポートします。使用するモデルのFBXやglbをドラッグ&ドロ ップを行いましょう。モデルを選択し、 Inspector > Model で Scale Factor を確認しつつ、尺度などを調整します。
②マーカーの登録
次にAsstsにて「Reference Image Library」を開き、印刷物と同じマーカー画像を登録し、Specify Sizeにて実寸幅を指定します。XR OriginのInspectorに追加した「AR Tracked Image Manager」のSerialized LibraryにReference Image Libraryをドラッグ&ドロップを行います。Tracked Image Prefabは空欄のままです。
③マーカーの検出
マーカー認識時にモデルを出現させるため、Assts内で空のC#スクリプトを作成し「MarkerSpawner」として保存します。

スクリプト内容をC#にコピペし、Hierarchy上のXR OriginにC# 「MarkerSpawner」をドラッグ&ドロップで追加します。XR OriginのInspectorの下に「MarkerSpawner」が表示されているかを確認しましょう。
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(ARTrackedImageManager))]
public class MarkerSpawner : MonoBehaviour
{
private ARTrackedImageManager imageManager;
[Header("Prefab & Placement")]
public GameObject modelPrefab; // 出したいモデル
public Vector3 localOffset = Vector3.zero; // マーカー座標系でのオフセット(m)
public Vector3 localEuler = Vector3.zero; // マーカー座標系での回転(°)
public bool flattenXZ = true; // 最終的にピッチ/ロールを0にする
[Header("Spawn Control")]
public int stableWaitFrames = 30; // 検出後の安定待ち
public int horizontalWaitFrames = 10; // 水平化までの待ち
public float reRecognizeDelay = 3f; // 再認識クールダウン(秒)
public bool onePerMarker = true; // 同一マーカーは一度だけspawn
[Header("Safety")]
public bool disableCamerasInSpawned = true; // Prefab内のCameraを自動無効化
private bool canRecognize = true;
private readonly HashSet<string> spawnedKeys = new();
private GameObject currentModel;
void Awake()
{
imageManager = GetComponent<ARTrackedImageManager>();
if (!imageManager) Debug.LogError("[MarkerSpawner] ARTrackedImageManager not found.");
}
void OnEnable()
{
if (!imageManager) imageManager = GetComponent<ARTrackedImageManager>();
imageManager.trackedImagesChanged += OnChanged;
Debug.Log("[MarkerSpawner] Enabled.");
}
void OnDisable()
{
if (imageManager) imageManager.trackedImagesChanged -= OnChanged;
}
void OnChanged(ARTrackedImagesChangedEventArgs e)
{
// 初回検出を拾えない端末もあるため、added/updated の両方で試行
foreach (var img in e.added) TryQueueSpawn(img);
foreach (var img in e.updated) TryQueueSpawn(img);
// removed は無視(固定表示のため消さない)
}
void TryQueueSpawn(ARTrackedImage img)
{
if (!canRecognize) return;
if (img.trackingState == TrackingState.None) return;
string key = img.referenceImage.guid.ToString(); // 版差回避のためGUIDを利用
if (onePerMarker && spawnedKeys.Contains(key)) return;
StartCoroutine(SpawnRoutine(img, key));
}
IEnumerator SpawnRoutine(ARTrackedImage img, string key)
{
canRecognize = false;
// 追跡安定のため少し待つ
for (int i = 0; i < Mathf.Max(0, stableWaitFrames); i++) yield return null;
// マーカー姿勢 + ローカルオフセット/回転をワールドに変換
Pose markerPose = new Pose(img.transform.position, img.transform.rotation);
Vector3 worldPos = markerPose.position + markerPose.rotation * localOffset;
Quaternion worldRot = markerPose.rotation * Quaternion.Euler(localEuler);
// ワールドに直置き(子にせず最初から固定)
currentModel = Instantiate(modelPrefab, worldPos, worldRot);
// Prefab内のCamera/AudioListenerは無効化(AR映像を消さない保険)
if (disableCamerasInSpawned && currentModel)
{
foreach (var c in currentModel.GetComponentsInChildren<Camera>(true)) c.enabled = false;
foreach (var a in currentModel.GetComponentsInChildren<AudioListener>(true)) a.enabled = false;
}
// 必要ならピッチ/ロールを0化して水平に
if (flattenXZ)
{
for (int i = 0; i < Mathf.Max(0, horizontalWaitFrames); i++) yield return null;
if (currentModel)
{
var eul = currentModel.transform.eulerAngles;
currentModel.transform.rotation = Quaternion.Euler(0f, eul.y, 0f);
}
}
spawnedKeys.Add(key);
Debug.Log($"[MarkerSpawner] Spawned GUID={key} at {currentModel.transform.position}");
// 再認識までクールダウン
yield return new WaitForSeconds(Mathf.Max(0.01f, reRecognizeDelay));
canRecognize = true;
Debug.Log("[MarkerSpawner] Ready for next recognition.");
}
}
Image ManagerとPrefabを割り当てます。Local offset値でモデルが出現するマーカーからのオフセット距離が設定でき、Local eulerは角度です。
Flatten XZは強制水平化の切替であり、Stable[Horizontal] Wait Framesはマーカーを認識して安定するまでの待ち時間です。フレームは30となります。

マーカーはマット紙に印刷します。また、似たような柄を使用すると誤検出になる可能性が高いため、ユニークなパターンを選びましょう。コントラストの強めの画像を使用すると安定した認識が得られます。
3.ビルドと端末への導入
「File>Build Settings」を開き、「Build」を実行します。保存先と.apkファイルの名称を設定します。.apkファイルを使用するAndroid端末にインポートし、アプリをインストールしましょう。

アプリを起動し、カメラでマーカーを読み取ると、設定した3Dモデルが現場上に重なって表示されます。描画精度やスケール感を確認し、必要に応じて調整を行います。
Android端末を開発者モードに設定しておくと、「Build and Run」が可能となります。PCと端末を接続した状態で、「Build and Run」を実行すると.apkファイルを出力し、インポートと実行を自動で行います。手動転送の手間が省け、動作確認が効率化されます。
まとめ
本記事では、AR導入のメリット・BIM/CIMにおける活用の位置づけ、プロジェクト開始方法などを紹介しました。
令和5年度からのBIM/CIMの原則適用とともに、今後も多くの企業が導入し、拡大していくものと見られます。効率的な活用とともに、現場の時間的コストの大幅な削減が期待できるでしょう。
