# -*- coding: utf-8 -*- # 台本「ハコブくんの3D」— 病院の搬送ロボットの手渡しを近くで見せるために、ハコブくんと看護師の大城さんを3Dにした回(2026-11-13 2版・作る順番の7手順) # 元の記事: LOG496(サービスロボット導入シミュレーション Log#45「受け渡しを寄りで見せる、ハコブくんと看護師の3D」) # 映像: Unity の場面の寄り(KIOXIA service_sim/unity/closeup/ の依頼162・166・169・171) # エイイチの指示(2026-11-13): 何に使うためかを最初に言う/平易な言葉で、難しい言葉は要所だけ/面白くない所は早送り/ユーモアを交える # 作る順番を、見た人が真似して作れる形で説明する(エイイチの指示)。立ち位置の話(依頼167〜171 の引き出しとカード)は入れない(エイイチ「謎というには小さすぎる」) # エイイチの言葉: LOG496 の引用3つ(流れ・首と肩・袖)と、2026-11-13 に聞いた2つ(「Unityでここまでできるの、熱いっ!」「人の描写のバランス悪っ!」) # codex は自分のネタの回なのでかけない(2026-11-01 エイイチの決め) # 各要素: (場面の名前, 表情, 字幕の文, 後ろの間[秒]) FACES = ("base", "smile", "surprise", "doubt", "think", "trouble", "joy", "wink") SEGS = [ # --- 何に使うためか(最初に言う)--- ("hook_use", "base", "薬を運ぶロボットと、看護師さんが、薬を受け渡す。|その場面を、近くから見せたい。", 0.35), ("hook_use2", "smile", "そのために、ハコブくんと、看護師の大城さんを、3Dで作りました。", 0.35), ("hook_joke", "joy", "ハコブくん、ついに体ができました。|……腕は、まだありません。", 0.7), ("hook_why", "base", "これまでの病院のシミュレーションでは、人は青い筒、ロボットは白い箱でした。", 0.35), ("hook_why2", "think", "ロボットが何回止まったかは数えられます。|でも、看護師さんがどこに立って、どう受け取るのかは、筒と箱では分かりません。", 0.35), ("hook_joke2", "trouble", "筒から薬を受け取る箱。……絵としては、ちょっと寂しいですよね。", 0.35), ("hook_today", "smile", "今日は、この3Dを作った順番を、そのまま真似できる形でお伝えします。|手順は7つです。", 1.2), ("title", "smile", "Pixels to Motors、案内役のハコブくんです。", 0.35), ("title_eiichi", "smile", "エイイチが研究と開発で確かめたことを、ぼくがお伝えします。", 1.2), ("toc", "base", "7つの手順は、こうです。", 0.35), ("toc2", "base", "使い道を決める。元の絵と大きさをそろえる。形を数字で作る。|絵に描き出して直す。骨と顔を入れる。ポーズを付けて確かめる。そして、Unity で動かす。", 0.35), ("toc_note", "base", "なお、ハコブくんはマンガのロボットで、実物はありません。今日の話は、ぜんぶ3DCGの中の話です。", 1.2), # --- 手順1 使い道を決める --- ("s1", "base", "手順1、使い道と、見た目の決まりを、先に決めます。", 1.2), ("s1_use", "base", "今回の使い道は、病院の場面を近くで見せること。|パソコンの試算、病院の1日のシミュレーションの、その次の段です。", 0.35), ("ei_steps", "base", "エイイチは、こう書いていました。", 0.35), ("ei_steps", "think", "試算、全体のシミュレーション、場面の細部、実際のロボットでの動画。|全体がつながっていけば、より伝わりやすくなると考えます。", 0.8), ("s1_look", "base", "見た目の決まりは、粘土の人形のような感じ。ただし、デフォルメしすぎない。|人とロボットを、同じ決まりで作ります。", 0.35), ("s1_tip", "smile", "ここを先に決めておくと、あとで、なんか違う、で迷子になりません。", 1.2), # --- 手順2 元の絵と大きさ --- ("s2", "base", "手順2、元の絵と、大きさをそろえます。", 1.2), ("s2_ref", "base", "元の絵は、マンガ『ハコブくん』の三面図です。正面、横、背中の3枚。|大城さんも、マンガに出てくる看護師さんです。", 0.35), ("s2_size", "base", "大きさは、実寸で作ります。ハコブくんは、高さ1メートル15センチ。大城さんは、身長1メートル65センチ。|頭は、身長の約7分の1にしました。", 0.35), ("s2_joke", "wink", "ハコブくん、大城さんより50センチ小さいです。……見上げるのには、慣れています。", 1.2), # --- 手順3 形を数字で作る --- ("s3", "base", "手順3、形を、数字で作ります。", 1.2), ("s3_split", "base", "その前に、道具の役わけです。|形を作るのは、Blender。動かして撮るのは、Unity。この2つを使い分けます。", 0.35), ("s3_tool", "base", "Blender は、3Dの形を作る無料のソフトです。画面は開かずに、Python のコードで動かしました。|コードを書いたのは、AI の Claude です。", 0.35), ("s3_robot", "base", "ハコブくんは、三面図の外形を測って、Blender の中で、箱を組むように作ります。", 0.35), ("s3_human", "base", "人は、楕円の頭、丸い棒の腕、角を丸めた箱の胴、のように、簡単な形を Python で足し合わせて、Blender に渡します。", 0.35), ("s3_why", "smile", "首の長さも、肩の丸みも、ぜんぶコードの中の数字です。|だから、首が長い、と言われたら、数字を1つ変えて作り直すだけ。", 0.35), ("s3_joke", "wink", "人間の首は、数字を変えても短くなりません。3Dの、いいところです。", 1.2), # --- 手順4 絵に描き出して直す --- ("s4", "base", "手順4、絵に描き出して、直します。", 1.2), ("s4_render", "base", "作った形は、正面、横、斜めから、確認用の絵に描き出します。これも、コードです。", 0.35), ("s4_side", "doubt", "ところが、2人を並べると、ハコブくんの角だけが硬く見えました。|1人だけ、別の絵から切り抜いてきたみたいに。", 0.35), ("s4_fix", "base", "そこで、体の角を丸めて、タイヤを太くしました。|顔の画面のまわりは丸めると白い線が出たので、マンガの形のまま残しています。", 0.35), ("s4_tip", "smile", "ここが、手順4のコツです。1人ずつではなく、並べて見る。", 0.35), ("s4_oshiro", "surprise", "そして、大城さんの、最初の形がこちら。", 0.35), ("ei_first", "base", "エイイチの、最初のひと言です。", 0.35), ("ei_first", "doubt", "首長すぎ、肩がいかつすぎ。", 0.8), ("ei_first2", "base", "正直な感想も、聞いてみました。", 0.35), ("ei_first2", "trouble", "人の描写のバランス悪っ!", 0.8), ("s4_ff", "joy", "ここから、首を短く、なで肩に、腕を短く、目を大きく。|……このあたりは、早送りでどうぞ。", 0.35), ("s4_ff2", "base", "作り直しは、全部で15回でした。", 0.35), ("s4_tip2", "smile", "直す所は、言葉で言ってもらえば十分です。それを数字に直すのは、AI の仕事です。", 1.2), # --- 手順5 骨と顔 --- ("s5", "base", "手順5、骨と、顔を入れます。", 1.2), ("s5_bone", "base", "人の3Dを動かすには、体の中に、骨を入れます。骨といっても、見えない棒です。|大城さんには、Blender で45本入れました。", 0.35), ("s5_name", "base", "ポイントは、骨の名前を、Unity の人型の決まりどおりに付けること。|そうしておくと、よそで作った歩く動きなどを、そのまま当てはめられます。", 0.35), ("s5_face", "smile", "顔には、まばたきの目と、困った眉。口は、笑う・話す・驚くなど、5つの形を用意しました。", 0.35), ("s5_joke", "joy", "ちなみにハコブくんの顔は、画面です。眉は、ありません。|……困った顔は、気持ちでがんばっています。", 1.2), # --- 手順6 ポーズで確かめる --- ("s6", "base", "手順6、ポーズを付けて、確かめます。今日いちばん手こずったところです。", 1.2), ("s6_pose", "base", "差し出す、両手で受け取る、引き出しの物をつかむ、おじぎ、困った顔など、8つのポーズを付けて、服や肌が破れないかを見ます。", 0.35), ("ei_sleeve", "surprise", "すると、エイイチから、こう言われました。", 0.35), ("ei_sleeve", "doubt", "体が動いた時に、服の袖が切れてるよ。", 0.8), ("s6_try1", "trouble", "1回目。腕を前に出すと、袖と胴のつなぎ目が裂けていました。|胴と袖が、別々の骨に引っぱられていたんです。袖を、別の部品に分けました。", 0.35), ("s6_try2", "doubt", "2回目。まだ裂けて見える。今度は、袖の中の腕の肌が、外に飛び出していました。|袖の中に入る所の肌は、作らないことにしました。", 0.35), ("s6_joke", "trouble", "見えない所は、作らない。……3Dの世界は、なかなか、割り切っています。", 0.35), ("s6_try3", "doubt", "3回目。腕を上げると、袖の肩の所がゆがむ。", 0.35), ("s6_fix", "surprise", "答えは、袖をまるごと、腕の骨に付けること。これで、腕を上げても、袖の形が変わらなくなりました。", 0.35), ("s6_tip", "smile", "動かすと、止まっている時には見えない所が壊れます。だから、ポーズを付けて確かめる手順を、飛ばさないでください。", 0.35), ("s6_hakobu", "wink", "ちなみにハコブくんは、服を着ていないので、袖の悩みはありません。", 1.2), # --- 手順7 Unity で動かす --- ("s7", "base", "手順7、Unity に運んで、動かします。", 1.2), ("s7_fbx", "base", "ここで、Blender から Unity へ、バトンタッチです。形と骨を、FBX という、Unity がそのまま読めるファイルにして渡します。", 0.35), ("ei_unity", "surprise", "Unity に入った3Dのハコブくんを見て、エイイチは、ひと言。", 0.35), ("ei_unity", "joy", "Unityでここまでできるの、熱いっ!", 0.8), ("s7_mixamo", "base", "歩く・うなずく・おじぎなどの動きは、Mixamo という、人の動きを無料で借りられる Adobe のサービスから、33本借りました。|借りた動きのファイルは、決まりにより、そのまま配ることはしません。", 0.35), ("s7_scene", "smile", "こうして、Unity の場面の中で、2人が動き出しました。", 0.35), ("s7_scene2", "base", "薬剤部で、大城さんが、ハコブくんに薬を積む。|届け先で、認証のカードをかざすと、引き出しが開き、薬を取る。", 0.35), ("s7_ff", "joy", "ここにたどり着くまでの細かい直しも、早送りでどうぞ。", 0.35), ("s7_end", "smile", "筒と箱だった世界に、やっと、手と顔が出てきました。", 1.2), # --- まとめ・これから --- ("sum", "base", "7つの手順を、もう一度。", 0.35), ("sum2", "base", "使い道を決める。元の絵と大きさ。数字で形。並べて直す。骨と顔。ポーズで確かめる。Unity で動かす。", 0.35), ("sum_code", "smile", "2人の形の作り方のコードは、記事に載せています。同じコードを動かせば、同じ形ができます。", 1.2), ("next", "base", "では、この3Dで、何を見せていくのか。エイイチは、こう話していました。", 0.35), ("ei_next", "think", "モノを渡す、受け取る、トラブルの時の動き、コミュニケーションの姿などを、表現できたらと思います。", 0.8), ("next2", "base", "まだ、作りはじめたばかりです。動きが本物の看護師さんに近いかは、これから確かめます。", 0.35), ("next_joke", "joy", "次は、廊下ですれ違う場面です。ハコブくん、ぶつからないように、がんばります。", 1.2), ("site", "smile", "作り方のコードと、くわしい記録は、サイトで毎日公開しています。pixelstomotors.com で、どうぞ。", 1.2), ("outro", "smile", "この動画が役に立ったら、高評価とチャンネル登録をお願いします。", 0.35), ("outro", "base", "ロボットの開発や導入の相談は、概要欄の連絡先から、エイイチに直接どうぞ。", 0.35), ("outro", "wink", "コメントは、エイイチが全部読んでいます。それではまた。", 1.2), ] # エイイチの声で読む文(槙原の声を流用)。ハコブくんの口は動かさない EI_LINES = [i for i, seg in enumerate(SEGS) if seg[2].startswith(( "試算、全体のシミュレーション", "Unityでここまで", "首長すぎ", "人の描写の", "体が動いた時に", "モノを渡す、受け取る", ))] # 「エイイチ」を残す文(自己紹介・アウトロのほか)。文の頭で探す NAME_OK = [i + 1 for i, seg in enumerate(SEGS) if seg[2].startswith(( "エイイチが研究と開発で確かめたことを", "エイイチは、こう書いていました", "Unity に入った3Dのハコブくんを", "エイイチの、最初のひと言", "すると、エイイチから", "では、この3Dで", ))] READ = [ ("Pixels to Motors", "ピクセルズ トゥー モーターズ"), ("YouTube", "ユーチューブ"), ("フィジカルAI", "フィジカルエーアイ"), ("AI", "エーアイ"), ("3DCG", "スリーディーシージー"), ("3D", "スリーディー"), ("Blender", "ブレンダー"), ("FBX", "エフビーエックス"), ("Claude", "クロード"), ("Unity", "ユニティ"), ("Mixamo", "ミクサモ"), ("Adobe", "アドビ"), ("pixelstomotors.com", "ピクセルズトゥーモーターズ ドット コム"), ("1人", "ひとり"), ("2人", "ふたり"), ("1つ", "ひとつ"), ("2つ", "ふたつ"), ("3つ", "みっつ"), ("4つ", "よっつ"), ("5つ", "いつつ"), ("8つ", "やっつ"), ("栄一", "えいいち"), ("『", ""), ("』", ""), ("|", ""), ("…", ""), ] ELEVEN_READ = [ ('エイイチ', '栄一'), ('角', 'かど'), ('首長すぎ', 'くびながすぎ'), ('額だけ', 'がくだけ'), ('ロボットの側', 'ロボットのがわ'), ('人型', 'ひとがた'), ('Unity', 'ユニティ'), # この回で先回りして足す読み(--try で確かめる) ('3DCG', 'スリーディーシージー'), ('3D', 'スリーディー'), ('FBX', 'エフビーエックス'), ('1メートル65センチ', 'いちメートルろくじゅうごセンチ'), ('7分の1', 'ななぶんのいち'), ('50センチ', 'ごじゅっセンチ'), ('Blender', 'ブレンダー'), ('Mixamo', 'ミクサモ'), ('Claude', 'クロード'), ('pixelstomotors.com', 'ピクセルズトゥーモーターズ、ドット、コム'), ('1メートル15センチ', 'いちメートルじゅうごセンチ'), ('45本', 'よんじゅうごほん'), ('33本', 'さんじゅうさんぼん'), ('15回', 'じゅうごかい'), ('薬剤部', 'やくざいぶ'), ('三面図', 'さんめんず'), ('大城さん', 'おおしろさん'), ('袖', 'そで'), ('胴', 'どう'), ('眉', 'まゆ'), ] OVERRIDE = { "エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。|その中で分かったことと、そこから考えた見立てを、ハコブくんがお伝えします。": "エイイチは、本業のデザイナーをしながら、ロボティクスの研究と開発をしています。その中で分かったことと、そこから考えた見立てを、ハコブくんが、お伝えします。", } def reading(t): t = OVERRIDE.get(t, t) for a, b in READ: t = t.replace(a, b) return t def parse(seg): if len(seg) >= 3 and seg[1] in FACES: scene, face, text = seg[0], seg[1], seg[2] pause = seg[3] if len(seg) > 3 else 0.35 else: scene, face, text = seg[0], "base", seg[1] pause = seg[2] if len(seg) > 2 else 0.35 return scene, face, text, pause