Slide 1

Slide 1 text

4画面出力とレシート印刷で作る 体験型デジタルサイネージ @ksk1030 Gotanda.unity #8 / 2018.09.26

Slide 2

Slide 2 text

話します  ・どんな物を作ったか  ・機能の話ざっくり 話しません  ・ハードウェア側の細かい設定の話

Slide 3

Slide 3 text

どんな物を作ったか?

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

作ったもの

Slide 6

Slide 6 text

作ったもの 北海道大学博物館内のサイネージ  ・クイズゲームで色々学ぼう的な Windows10 上で動作  ・マルチディスプレイ(4画面)  ・レシート印刷(施設内で使えるクーポン発行)  ・Flicker API(インスタは審査落ちた...)  ・csvファイルでのデータ更新

Slide 7

Slide 7 text

マルチディスプレイ ② ②’ ① ③ プロジェクタ x 3 + 手元のタッチパネル 真ん中とタッチパネルは同じ画面を表示 しているので、実質3つのカメラを用意

Slide 8

Slide 8 text

マルチディスプレイ using UnityEngine; public class MultiDisplayManager : SingletonMonoBehaviour { void Start() { int maxDisplayCount = 3; #if SINGLE_DISPLAY maxDisplayCount = 1; #endif for (int i = 0; i < maxDisplayCount && i < Display.displays.Length; i++) { Display.displays[i].Activate(); } } }

Slide 9

Slide 9 text

マルチディスプレイ using UnityEngine; public class MultiDisplayManager : SingletonMonoBehaviour { void Start() { int maxDisplayCount = 3; #if SINGLE_DISPLAY maxDisplayCount = 1; #endif for (int i = 0; i < maxDisplayCount && i < Display.displays.Length; i++) { Display.displays[i].Activate(); } } } Display.displays に接続中のディスプレイが 格納されている Length で取得した台数分 Activate() する (手元で確認するときに1画面出力できる  よう環境変数 SINGLE_DISPLAY を用意) 公式:https://docs.unity3d.com/ja/current/Manual/MultiDisplay.html

Slide 10

Slide 10 text

実装はこれで良いのだが、やってみると... ディスプレイごとの設定でハマる  ・リフレッシュレート  ・アスペクト比  ・Unity上の Index と OS上の番号が一致しない - PCに物理的に接続した順で判定されている? - https://gist.github.com/keijiro/a898b77fa06ee7c83cffc263419b32e3 - 詳細情報求ム... マルチディスプレイ

Slide 11

Slide 11 text

専用のプリンタを設置 クイズで一定以上のスコアを達成すると 博物館内のカフェで使えるクーポン発行 レシート印刷 EPSON TM-m10 https://www.epson.jp/products/receiptprinter/tmm10/

Slide 12

Slide 12 text

※レシートとは言っても通常の印刷と同じ レシート印刷 signage  ┣━ Assets  :  ┣━ Plugins     :  ┣━ System.Drawing.dll        :  ①System.Drawing.dll を Plugins ディレクトリに設置   場所:C:\Windows\Microsoft.NET\Framework\ {バージョン} \System.Drawing.dll  ②Other Settings の Api Compatibility Level を “.NET2.0” に

Slide 13

Slide 13 text

レシート印刷 void PrintExec() { PrintDocument printDocument = new PrintDocument(); // オブジェクトの作成 printDocument.PrintPage += new PrintPageEventHandler(PrintPage); // イベントハンドラの追加 printDocument.Print(); // 印刷開始 } void PrintPage(object sender, PrintPageEventArgs eventPrintPage) { drawFont = new System.Drawing.Font("Arial", 10); // Arial フォントのサイズ10 drawBrush = new SolidBrush(System.Drawing.Color.Black); // 色は黒 drawFormat.Alignment = StringAlignment.Center; // センタリング string text = "印刷したい文字列"; eventPrintPage.Graphics.DrawString(text, drawFont, drawBrush, drawRect, drawFormat); Image image = Image.FromFile("画像のパス"); eventPrintPage.Graphics.DrawImage(image, new Rectangle(offsetX, offsetY, width, height)); image.Dispose(); //後始末 eventPrintPage.HasMorePages = false; //次のページがないことを通知する }

Slide 14

Slide 14 text

レシート印刷 void PrintExec() { PrintDocument printDocument = new PrintDocument(); // オブジェクトの作成 printDocument.PrintPage += new PrintPageEventHandler(PrintPage); // イベントハンドラの追加 printDocument.Print(); // 印刷開始 } void PrintPage(object sender, PrintPageEventArgs eventPrintPage) { drawFont = new System.Drawing.Font("Arial", 10); // Arial フォントのサイズ10 drawBrush = new SolidBrush(System.Drawing.Color.Black); // 色は黒 drawFormat.Alignment = StringAlignment.Center; // センタリング string text = "印刷したい文字列"; eventPrintPage.Graphics.DrawString(text, drawFont, drawBrush, drawRect, drawFormat); Image image = Image.FromFile("画像のパス"); eventPrintPage.Graphics.DrawImage(image, new Rectangle(offsetX, offsetY, width, height)); image.Dispose(); //後始末 eventPrintPage.HasMorePages = false; //次のページがないことを通知する } メインの処理 PrintDocument のオブジェクトを作成して PrintPage イベントハンドラを追加してやる (この辺は .NET の領域)

Slide 15

Slide 15 text

レシート印刷 void PrintExec() { PrintDocument printDocument = new PrintDocument(); // オブジェクトの作成 printDocument.PrintPage += new PrintPageEventHandler(PrintPage); // イベントハンドラの追加 printDocument.Print(); // 印刷開始 } void PrintPage(object sender, PrintPageEventArgs eventPrintPage) { drawFont = new System.Drawing.Font("Arial", 10); // Arial フォントのサイズ10 drawBrush = new SolidBrush(System.Drawing.Color.Black); // 色は黒 drawFormat.Alignment = StringAlignment.Center; // センタリング string text = "印刷したい文字列"; eventPrintPage.Graphics.DrawString(text, drawFont, drawBrush, drawRect, drawFormat); Image image = Image.FromFile("画像のパス"); eventPrintPage.Graphics.DrawImage(image, new Rectangle(offsetX, offsetY, width, height)); image.Dispose(); //後始末 eventPrintPage.HasMorePages = false; //次のページがないことを通知する } DrawString に文字列を渡すと印刷できる フォントや色、レイアウトもオプションで 渡せば細かく指定することが可能

Slide 16

Slide 16 text

レシート印刷 void PrintExec() { PrintDocument printDocument = new PrintDocument(); // オブジェクトの作成 printDocument.PrintPage += new PrintPageEventHandler(PrintPage); // イベントハンドラの追加 printDocument.Print(); // 印刷開始 } void PrintPage(object sender, PrintPageEventArgs eventPrintPage) { drawFont = new System.Drawing.Font("Arial", 10); // Arial フォントのサイズ10 drawBrush = new SolidBrush(System.Drawing.Color.Black); // 色は黒 drawFormat.Alignment = StringAlignment.Center; // センタリング string text = "印刷したい文字列"; eventPrintPage.Graphics.DrawString(text, drawFont, drawBrush, drawRect, drawFormat); Image image = Image.FromFile("画像のパス"); eventPrintPage.Graphics.DrawImage(image, new Rectangle(offsetX, offsetY, width, height)); image.Dispose(); //後始末 eventPrintPage.HasMorePages = false; //次のページがないことを通知する } DrawImage に画像と表示領域を Rectangle で渡してやると画像も印刷できる

Slide 17

Slide 17 text

レシートもこれで印刷できるが、これもやってみると... やはりハマる  ・System.Drawing.dll なんて知らんかった  ・Api Compatibility Level の設定も知らんぞ  ・画像とテキストで細かく offset を指定する必要あり  ・別途プリンタのドライバの設定が必要  ・情報が出てこない(→最近は結構情報がある) - https://qiita.com/koukiwf/items/e91067e95c2a64af54d6 - http://madgenius.hateblo.jp/entry/2018/01/30/172740 レシート印刷

Slide 18

Slide 18 text

その他にも 色々ハマる  ・そもそも端末/OS側を色々いじる必要    →3画面出力できるようグラボ取り付け    →自動起動/終了のためにタスクスケジューラとか BIOS の設定  ・インスタAPI使いたい    →ご当地写真を表示するんだ!審査が必要か!    →英文の説明入り動画まで作ったのにリジェクト    →Flicker API で妥協してやった に救われる  ・Windows10 だとエッジスワイプで通知が出る    →物理的にスワイプできないようフレームをつける

Slide 19

Slide 19 text

こんだけ色々出てくる  → Unityが何でもできるからこそ! ゲームや今回のサイネージ以外でも  ・UIの自由度  ・インタラクティブな機能 を活かせるフィールドなら応用できる! 最近だと xR(VR / AR)なんかが好例 それでも...

Slide 20

Slide 20 text

Unity盛り上げていきましょう! (そしてマルチディスプレイの順番の詳細を教えてください...)

Slide 21

Slide 21 text

中谷 圭佑 (@ksk1030)  任天堂株式会社(2011/04〜2013/12)  ・人事  株式会社ORSO(2014/01〜)  ・エンジニア(Node.js / Ruby がメイン)  ・経営企画 ◆Speaker Deck  ・https://speakerdeck.com/ksk1030m 自己紹介

Slide 22

Slide 22 text

We are hiring! ARコンテンツとかも作ってます!

Slide 23

Slide 23 text

Thank you for listening !!