てつぶろぐ

けつぶろぐ。

知見のゴミ箱。

【読書感想文】DDD(ドメイン駆動開発)について①

はじめに

最近.NETエンタープライズアプリケーションアーキテクチャ第二版を分からん分からん言いながら読んでるので、 メモついでにブログ記事にしました。

DDD(ドメイン駆動開発)

「抽象的な設計原則を現実のソフトウェアに適用する」 というのが開発者のエリック・エヴァンスさんが提唱したDDDの概要です

はい、サッパリですね

今回は、DDDで扱われいる用語を自分なりにまとめて行きます

DDDによる分析

DDDによる分析の要素はユビキタス言語境界付けられたコンテキストの2つ。 この2つは互いに関連しあっている。

  • ユビキタス言語

    • ユビキタス(いつでもどこでも誰でも)という意味が指すとおり、プロジェクトの関係者全員が使用する言語
    • ビジネス側と開発側の概念を統一し、拡張したもの
    • プロジェクト内のあらゆる場面でのコミュニケーションにおいて使用される事が理想
    • アーキテクト(設計者)はドメイン対する知識を深めながら、名詞と動詞を語彙に追加していくことになる
    • ユビキタス言語は、聞き取り調査や話し合いの中から生まれる
    • ドメインモデルで利用される命名規則とコーディング規則にはユビキタス言語の命名規則が反映されているべきである
      • ユビキタス言語が更新された場合、命名とコーディング規則も合わせて更新を行う
  • 境界付けられたコンテキスト

    • ドメインの領域の内、独自のユビキタス言語を持つため別個に扱ったほうが良い領域のこと
    • 境界付けられたコンテキストごとに、適切なアーキテクチャを決定する必要がある。
    • アーキテクトの主な役割は、ドメインから、ドメインごとのコンテキストを洗い出しサブドメインことにある
    • ユビキタス言語を変化させるのであれば、新しい境界付けられたコンテキストが発生したということ
      • 1つのビジネスドメインの中で同じ用語が別の意味で扱われていたり、異なる用語が同じ意味で使われていた場合に、そのビジネスドメインは複数のサブドメイン分ける必要があると言える
    • コンテキストの数と境界付けられたコンテキスト同士の関係が、企業の物理的な組織を反映していることもよく有り、部署ごとにコンテキストが定義されるのが一般的
      • 大抵は境界付けられたコンテキスト毎に開発チームが割り当てられる
    • コンテキスト間で重複した言語を共有カーネルとして共有事も可能だが、コンテキストAで行われた変更でコンテキストBのコードが動かなくなるなど、弊害は多い

コンテキストマッピング

  • コンテキストの種類

    • 上流コンテキスト
      • 下流に影響を与えるコンテキスト
      • 下流を一方的に変更することがある
    • 下流コンテキスト
      • 受動的であり、上流コンテキストによって変更される
  • コンテキストマッピングの関係パターン

    • ACL(腐敗防止層)
      • 最も安全な関係パターン
      • 一方の上流コンテキストが変更された際にコンテキストを同期させるために必要な変更が全てACLに分離される
      • 外部サービス、レガシーコードをカプセル化していル場合に有効
    • Conformist (順応者)
      • 下流コンテキストは上流コンテキストに受動的に従う
      • 下流コンテキストは上流コンテキストの必要のないデータまで受け取る
    • Customer / Supplier (顧客/受給者)
      • Conformistに近いが、不要なデータが送信されないようにチーム間で協力が発生する点が異なる
    • Paetnership
      • 二つのコンテキストは別々に開発されコードの共有は行われないが、相互依存しておりリリースや変更の際には双方を無視できない
    • 共有カーネル
      • 二つのコンテキストがモデルの一部を共有する
      • 共有カーネルを変更するにはチーム間の同期が必須

コンテキスト毎にアーキテクチャを定義する

  • 階層化アーキテクチャ
    • DDD分析から見つかるアーキテクチャの内で最も一般的
    • 元は、プレゼンテーション層/ビジネス層/データ層の三層構造であった
      • 最近(2014年頃)では、プレゼンテーション層/アプリケーション層/ドメイン層/インフラストラクチャ層で構成される
    • プレゼンテーション層
      • UIを提供する画面の集まり
      • 各画面には、データが読み込まれその画面のアクションは明確に定義されたデータを転送する
        • アプリケーション層から、プレゼンテーション層に追加されるデータをビューモデルと呼ぶ
          • 逆に、プレゼンテーション層からアプリケーション層に渡されるデータを入力モデルと呼ぶ
    • アプリケーション層
      • プレゼンテーションの指示に従い、アクションを手配する層
    • ドメイン
    • インフラストラクチャ層
      • セキュリティ、ログ、キャッシュなどが分類される

次回は、プレゼンテーション層の具体的な扱いについて書いていきます

リンク

次回を作成次第、追加していきます

クソゴリラ調教日誌:ファーシェーダ

f:id:honzyou1753:20180306215909p:plain

はじめに

お久しぶりです。ハンドルネーム増やしすぎて自分を見失っているチンパン28号です。
何百番煎じかわかりませんが、最近バーチャルユーチューバーとやらを始めました。


クソゴリラ、自己紹介する.002

その中でニシローランドゴリラの毛並みを再現するためにファーシェーダを書いてたので、知見として残しておきます。

ファーシェーダはその名の通り体毛を表現するためのシェーダです。
生物の毛並みを表現する手段としては、モデリングの段階で体毛を束で生やしていく方法もありますが、クソゴリラの全身に生えている毛をモデリングするのは非情に手間がかかる上に、
束ごとに作るとどうしてもアニメ調になってしまいがちです。

アニメキャラを作る場合には効果的ですが、今回は東山動物園のイケメンゴリラシャバーニくんを目指しているのでファーシェーダ、書いていきましょう!

説明の内容は、ShaderLabの頂点・フラグメントシェーダの基本をおさえている人向けです。

使用エンジン:Unity
使用言語:ShaderLab

参考にしたサイト様

ファーシェーダの理屈を知る上でこの記事が個人的には一番参考になりました。
Maverick Project

ShaderLabの記法で参考になったのはこちらの方の記事です。
純粋にファーシェーダだけ実装したいならこっちの記事のほうが分かりやすいかも……
.cgincの存在はこの記事で知ったので、ガッツリパク…参考にしてます
qiita.com

簡単に説明すると、元となるモデルの毛を生やしたい面にテクスチャの透明度を変えた面を何層も重ねるティラミス方式で毛を表現するのがファーシェーダの理屈です

材料

  • むき身のクソゴリラ一匹

f:id:honzyou1753:20180306230740p:plain:h256

  • クソゴリラボディのメインテクスチャ
    • 載せているのはファーシェーダを適用する身体のみですが、顔も用意しています

f:id:honzyou1753:20180306230911p:plain:h256

  • 毛のばらつきを表現するためのノイズテクスチャ
    • GINP2のフィルタで簡単に作れます
    • ノイズを細かくすることでふわっとした毛になり、荒くすることでゴワゴワの毛になります

f:id:honzyou1753:20180306231538p:plain:h256

  • 毛の生える量をUV座標で指定するための明度テクスチャ
    • 白いほど毛が長く、真っ黒は無毛です
    • UV座標はメインテクスチャに準拠します

f:id:honzyou1753:20180306232452p:plain:h256

  • トゥーンシェーダ(太陽光反映)用の色味指定用画像

f:id:honzyou1753:20180306232359p:plain

実装

ここわかんねぇぞ解説しろ!って部分があったらコメント下さい

Fur.shader

Shader "Custom/fur" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}	//  メインテクスチャ
		_FurTex  ("Base (RGB)", 2D) = "white" {}		// ファー用ノイズテクスチャ
		_FurMapTex  ("Base (RGB)", 2D) = "white" {}	//  ファーの生える位置・量を決める白黒テクスチャ
		_Ramp ("Toon Ramp (RGB)", 2D) = "gray" {} 	// トゥーンシェーダ用テクスチャ
		_Gravity ("Gravity", Vector) = (0.0, 1, 0.0, 0.0)	// 重力、ココいじれば毛を逆立てたり垂らしたり出来ます
		_FurLength ("Length",float) = 1			// 毛の長さ(計算的には掛け算をしているので名前あってないなこれ)
	}
	
	Category {
		Tags {"Queue" = "Transparent"}
		Blend SrcAlpha OneMinusSrcAlpha
		// パスは1+30で固定
		SubShader {
		// 一番最初は地肌を描画する
		Pass {
			CGPROGRAM
				
			#define FUR_OFFSET 0.0
			#include "UnityCG.cginc"
			#include "AutoLight.cginc"
                	#include "FurHelper.cginc"

			#pragma vertex vert
			// 最初だけ地肌用のフラグメントシェーダ使ってます
			#pragma fragment skinfrag
                
			ENDCG
            	}
		// 以降はひたすら体毛の層を重ねる
		Pass {
			CGPROGRAM

			#define FUR_OFFSET 0.01

			#include "UnityCG.cginc"
			#include "AutoLight.cginc"
                	#include "FurHelper.cginc"

			#pragma vertex vert
			#pragma fragment furfrag
                                        
                	ENDCG
			}
		}

		// 以降はFUR_OFFSETの値だけ少しずつ増やして、ひたすら残り29Passを書いてます
		// FUR_OFFSETの値は透明度から引くので0~1の間でよしなに設定しましょう

		Fallback " VertexLit", 1
	}
}
ポイント解説
Category {
	Tags {"Queue" = "Transparent"}
	Blend SrcAlpha OneMinusSrcAlpha

Category {}の先頭で設定したTagsやアルファブレンドなどの設定は、以降のCategory {}で囲んだ全てのPassで適用されます。便利。

	#define FUR_OFFSET 0.0
	~
        #include "FurHelper.cginc"

FUR_OFFSETはFurHelperで使うので、先に書いとかないとエラー吐きます。

FurHelper.cginc

.cgincファイルは、.shderファイルに#includeすることで一つのシェーダー関数を使い回すことが出来ます。
今回のような複数Passを何度も書くような場面で凄い便利でした。

#ifndef EDO_FUR_SHADER_HELPER
#define EDO_FUR_SHADER_HELPER

// 頂点シェーダへの入力構造体
struct vertInput {
	float4 vertex    : POSITION;
	float4 normal    : NORMAL;
	float2 texcoord  : TEXCOORD0;
};

// フラグメントシェーダへの入力構造体
struct vert2frag {
	float4 position : POSITION;
	float3 normal   : TEXCOORD0;
	float2 uv       : TEXCOORD1;
	float2 furUv      : TEXCOORD2;
	float3 lightDir : TEXCOORD3;
	half glay		: TEXCOORD5;
	float4 vertex	: TEXCOORD6;
};

uniform sampler2D _MainTex;
uniform sampler2D _FurTex;
uniform sampler2D _FurMapTex;
uniform sampler2D _Ramp;
uniform float4 _Gravity;
uniform float _FurLength;

// 頂点シェーダ
vert2frag vert(vertInput v) {
	vert2frag o;
	o.glay = tex2Dlod (_FurMapTex, float4(v.texcoord.xy,0,0)).r;
	
	// 変位係数で毛の位置を散らす
	float displacementFactor = pow(FUR_OFFSET, 3.0);
	float4 normal;
	normal = normalize(v.normal + _Gravity * displacementFactor);
	
	float4 vertexOffset = normal * FUR_OFFSET * o.glay * _FurLength;
	float4 worldPos = float4(v.vertex.xyz + vertexOffset.xyz, 1.0);
	o.position = UnityObjectToClipPos(worldPos);
	o.uv  = v.texcoord;
	o.furUv = v.texcoord * 10.0;

	o.vertex = v.vertex;
	o.normal = normalize(v.normal).xyz;
	o.lightDir = normalize(ObjSpaceLightDir(v.vertex));

	return o;
}

// フラグメントシェーダ
float4 furfrag(vert2frag i) : COLOR {
	float4 map = tex2D(_FurTex, i.furUv);
	if (map.r < FUR_OFFSET || i.glay <= 0.0) {
		discard;
	}

	fixed atten = LIGHT_ATTENUATION(i);
	// 以下はトゥーンシェーダ
	// 光源の向きと頂点法線の内角から0~1の値を取って、トゥーン輝度割当用の画像のx,y軸に当ててるだけです
	half d = dot (i.normal, i.lightDir)*0.5 + 0.5;
	half3 ramp = tex2D (_Ramp, float2(d,d)).rgb;
	float4 color = tex2D(_MainTex, i.uv);
	color.a = 1.1 - FUR_OFFSET;
	return color * float4(ramp,1) * (atten * 2);
}
// 地肌用フラグメントシェーダ
// _FurTexの値で描画判定をしている以外は同じです
float4 skinfrag(vert2frag i) : COLOR {
	fixed atten = LIGHT_ATTENUATION(i);
	half d = dot (i.normal, i.lightDir)*0.5 + 0.5;
	half3 ramp = tex2D (_Ramp, float2(d,d)).rgb;
	float4 color = tex2D(_MainTex, i.uv);
	color.rgb = color * ramp * (atten * 2);
	return color;
}

#endif
ポイント解説
o.glay = tex2Dlod (_FurMapTex, float4(v.texcoord.xy,0,0)).r;

毛の生える長さの比率を_FurMapTexの各UV座標の明度から0(ハゲ)~1(ふさふさ)で取っています
頂点シェーダでUV座標を取る場合はtex2Dlod を使用します。
今回は_FurMapTexをグレースケールで作ったので適当にr(赤)の値を取っていますが、ちゃんと明度を取りたいにしたいって人は
glay = r * 0.3 + g * 0.6 + b * 0.1;
で彩度付き画像からグレースケールを取れるらしいですよ。正直画像側から設定したほうが楽だし計算コストもかからないから推奨しないけど。

	float4 n = normalize(aNormal) * FUR_OFFSET * o.glay * _FurLength;
	float4 wpos = float4(v.vertex.xyz + n.xyz, 1.0);
	o.position = (UNITY_MATRIX_MVP, float4(wpos, 1.0));

ここでは毛の伸びる方向と長さから頂点の最終的なワールド座標を決めています
UNITY_MATRIX_MVPでモデルビュー行列×射影行列を既に定義してくれてます。Unity便利。

o.furUv = v.texcoord * 10.0;

ここではファーのノイズテクスチャを適用するUVを元のUVの拡大して代入しています。
なぜ拡大しているかというと、そのままUVを適用すると毛の一本一本がぶっとくなるからです。
一応かける値の増減でコード側から毛の粗さをいじれます

float4 map = tex2D(_FurTex, i.uv2);
if (map.a <= 0.0 || map.r < FUR_OFFSET || i.glay <= 0.0) {
	discard;
}

ノイズ画像の明度(r)がFUR_OFFSETより小さいか、頂点シェーダ側で設定した_FurMapTexの明度が0であれば描画をしないようにしてます。
正直、FUR_OFFSETじゃなくて別途定数を用意したほうが良いと書いてて思ったので、みんなはそうしてね。

これにはクソゴリラもニッコリ

f:id:honzyou1753:20180307014936p:plain

最後に

ファーシェーダは複数パスに変更が及ぶ結構重い処理なので、Unityがまれに落ちます。
セーブはこまめにしましょう(戒め)。

一つのPassの中でfor文でかっこよく回せないかなと思って、色々調べてたけど結局できなかったなぁ…
もしくは Pass間で値を受け渡す方法知りたい。



あと

はてなコード書きづらすぎだろ!!!!!!!!!!!!!!!
というわけで次回はQiitaでお会いしましょう。はいウホウホ(ノルマ達成)

============= 2018/05/13 追記 =============
記事内に誤りがありました。
> ファーシェーダは複数パスに変更が及ぶ結構重い処理なので、Unityがまれに落ちます。
> セーブはこまめにしましょう(戒め)。
と言っていましたが、実際に落ちる原因はフラグメントシェーダの戻り値にfixed4(8bit)を指定していた時があり、
256以上の色データが返された際にオーバフローを起こしていただけでした。
載せてあるサンプルコードでは直っていたので、影響はないです。
とは言ってもfloat4でも無駄があるので、halfが適切かと思います。

キモくて怖いやつ【3Dモデル配布】

牛鬼(仮)

f:id:honzyou1753:20171109015409p:plain f:id:honzyou1753:20171109015348p:plain

昔作ったけど、結局何にも使わなかったし今後何をする予定もないので、3Dモデルのアップローダのテストも兼ねて放流。

改めて見ると、ホラーゲームで動かすにも使いづらいサイズ感だな…

zipの中身を知りたくて─────

  • CowOrga.blenderファイル
    • 本体。Armatureと頂点ウェイト入り
  • CowOrga_A.png
    • ボディ部分のテクスチャ
  • CowOrga_B.png
    • 角部分のテクスチャ
  • AO_*.png
    • アンビエントオクルージョンベイクしただけの画像。
      手元のペイントソフトから別レイヤで乗算とかオーバーレイで色塗ってやると楽なんだなコレが
  • CowOrga_*.fbx
    • ハイポリ(一万ちょっと)とローポリ(3000ぐらい)のFBX。(ボーンは)ないです

配布場所

ux.getuploader.com

パスワードは chinpan_3d

利用規約

使う人多分いないだろうけど。

無言利用🙆

改変🙆

+二次配布🙆

【ゲーム感想】CupHead プレイ

f:id:honzyou1753:20171025013247j:plain

挨拶

どうも、哲人28号です。

最近、自炊で炒飯を作るのにハマってます。

でも私が作るとどう作ってもピラフになるんですよね・・・
名古屋の喫茶店で働いてた呪いかな・・・

CupHead is 何

store.steampowered.com CupHeadは、今年の9/19にSteam・XboxOneから配信されている
シューティングアクションゲームです。
お値段は1980円。
プラットフォームはUnity。

何と言っても、このゲームの特徴はキャラクター・背景・画面の表示・エフェクトに至るまで全て1930年代のカートゥーン風に仕上げていることです。
私としてはトムとジェリーのイメージが一番近いですかね。

▼ステージ画面。動くもの以外はしっかり書き込まれているのが細かい。 f:id:honzyou1753:20171025013332j:plain ▼ボス戦。初見殺し祭り。 f:id:honzyou1753:20171025013419j:plain ▼空中ボス戦。操作キャラも空中シューティング仕様になります。 f:id:honzyou1753:20171025013411j:plain ▼少ないけど横スクロールのステージもある。 f:id:honzyou1753:20171025014015j:plain

難しい

まぁこのゲーム、実際プレイして貰えれば分かるんですけど

メチャクチャ難しい。

CupHeadをプレイした海外のゲームライターが下手すぎると、ちょっと話題になるぐらいです。

(一応汚名返上記事) jp.automaton.am

▼200回ぐらい見たシーン。 f:id:honzyou1753:20171025025046j:plain

死んでも面白い

実際のところ

  • 敵(ボス)の攻撃は初見殺し5割
  • 複雑な操作(十字移動+ジャンプ+射撃+射撃切り替え+回避移動)
  • 序盤から複数操作を組合わせた動きを要求

など、ゲーム自体初心者の人や、アクション(シューティング)ゲームを普段やらない人にとっては優しくないゲーム性ではあります。

ファミコンスーファミの1990年代のゲームを彷彿とさせる難しさです。

しかし、私は実際のプレイでそんなにストレスを感じる事はありませんでした。

理由としては、以下の点が上げられます。

  • 安地だと思った所にカートゥーンムーヴで攻撃が伸びてくるので、逆に笑える
  • ボス面、スクロール面のプレイ時間がどちらも目安1~2分なので、リトライのスパンが短い
  • 切り替え可能な射撃・チャーム(補助アイテム)・スーパーアーツ(必殺技)があり、選択の幅が広く試行錯誤できる
  • 初見殺しの攻撃もあるが、詰むような状況に陥りづらい
    • 逆に初見で避けれた時に脳汁がドバドバ出る

▼HPが3というのも絶妙な設定。コイツの第一形態の動きは某有名AV男優の動きに似ている…似てない? f:id:honzyou1753:20171025021423j:plain

難しさ≠煩わしさ

あくまでCupHeadの「1990年代の難しさ」は、操作・敵の猛攻のみであり、それ以外の部分はとても現代チックであると私は思います。

セーブは全てオートセーブですし、残機がなくなったら最初から。というのもありません。

操作自体も複雑で難しいんですが、ジャンプで届きそうなところにはちゃんと届くし、ラグなんてのももちろん無いので操作自体は快適です。

「難しさ」と「煩わしさ」が混在する1990年代のゲームから「難しさ」のみを上手に抽出していると感じました。

▼コイツのエロ画像がもうあるという事実。それもまた現代チック。 f:id:honzyou1753:20171025023229j:plain

思い出スクショ

▼ラスボスのクソザコDevilくん。操作に慣れてくるのと、一つ前のKingDiceニキがめちゃキツイのであんまり強く感じないです。 f:id:honzyou1753:20171025025201j:plain ▼キチンとトムとジェリーのパロディボスもいます。 f:id:honzyou1753:20171025024919j:plain ▼ボスの残り体力は戦闘中はわかりませんが、死ぬと目安が見れます。 f:id:honzyou1753:20171025030123j:plain ▼日本語対応はまだしていないので、全部英語ですがそこは気合で。(日本語対応そのうちするらしいです) f:id:honzyou1753:20171025025417j:plain ▼最も死んだであろう重力反転ステージ。 f:id:honzyou1753:20171025025939j:plain

まとめ

面白いから、プレイして、どうぞ。

あと、開発者のヤベー奴エピソード載ってるからこれも一緒に読んで。 madewithunity.jp

HTCvive使ってサーバルちゃんになりたかった話②

             f:id:honzyou1753:20171003235122p:plain

挨拶

どうも、哲人28号です。

最近、エイリアン・コヴェナントを見た勢いで、エイリアンシリーズをイッキ見してました。

リプリー役のシガニー・ウィーバー氏が女前過ぎて惚れるわ。

振り返り

 前回の記事です。

honzyou1753.hatenablog.com

 前回はサーバルちゃんとさばんなちほーのモデルをUnityに取り込み、IKをつける

ところまでやりました。

今回はいよいよHTCviveを使ってサーバルちゃんの体内に入り込んでいきます。

 

準備

 UnityでHTCviveを使う際に最も簡単な方法は、

Steamが提供しているSteamVRを使うことです。

 

SteamVRはUnity側でも「SteamVR Plugin」というAssetが公開されており、

これを使えばUnity上でVRの開発が(比較的)簡単にできます。

 

ここらへんは私よりもっと詳しく解説しているお方がたくさんいるので、
興味があったらしらべてみてくだしあ。

実装

 実装と言っても、あらかたの作業は前回で終えているので、

今回は結果報告みたいな感じですね。

 

前回のおさらいですが、HTCviveで取れる位置情報は

  • ヘッドセットの 位置・向き
  • 左右コントローラーの位置・向き

ですので、

 

サーバルちゃんの手を追従させていたターゲットをHTCvive左右コントローラー、

頭の向きを追従させていたターゲットをヘッドセットの向きに合わせあげれば良いわけです。

 

実際に撮って見た動画がこちら


HTCvive使ってサーバルちゃんになりたかった結果①

 

 

 

何かキメェ・・・

 

でも、まぁそれなりには見れますね。

動きがぎこちないのは、予想以上にサーバルちゃんより私の肩幅が広かったのが原因だと思います。 人間の最も発達した筋肉は背筋ですからね。

 

 

外から見た結果はまだ良い方で、

次は私(HTCvive装着者)目線の動画を見てみましょう。

 


HTCvive使ってサーバルちゃんになりたかった結果②

 

 

 

ファッ?! 

 

髪の毛が見えるのは予想してたんですが、顔の裏まで見えるのは予想外でした。

結構MMD元のモデルってゲームで使う前提で作られてないから、

陰面(モデルの裏側)の非描画処理をしてないんですね。

 

そうじゃなくてもカメラのレイヤー設定でHTCviveのカメラ側からは顔の部分だけ表示させない、と言った処理を入れる必要はありそうです。

 

まとめ

サーバルちゃん度・・・30%(見た目のみ)

 

肩幅や腕の長さの差を比率でとったり、

UnityのIKだと大分できることが制限されるので

自分でIK実装したりとか改善の余地は多々ありますが、

今回は一旦切ってまた気分が乗ったらやりましょう。

 

けもフレ騒動もありますしね。

 

見たまま編集だと出来ないこと多くてストレス溜まるので、次回から記事書くときは

Markdownで書こうかな・・・

HTCvive使ってサーバルちゃんになりたかった話①

挨拶

どうも、哲人28号です。

時の流れは早いもので、社会人になり5ヶ月とちょっとが経ちました。

生後で言ったらもうハイハイしていてもおかしくない、そんな時期です。

 

まぁ、今でもおっぱい吸いたいですけどね。

事の起こり

久しぶりにHTCviveを使って何かできないかなと思ってニコ動でVR技術系の動画を
あさっていた所、この動画を発見しました。

見るのがめんどくさいよー!と言う人に向けて説明すると、

Unityでサーバルちゃんの手足にボーンを追従させるターゲットオブジェクトを
配置して、IK(インバースキネマティクス)でサーバルちゃんを外から動かすよ!

ってな内容になってます。

 

この動画を見て思ったんですよ・・・

 

これ、内側から動かしたればサーバルちゃんになれるんじゃね?

 

と、言うことでサーバルちゃんになるぞ俺はなるぞお前。

 

準備

まず、今回はタイトルにある通りHTCviveとUnityを使って行くのですが、

サーバルちゃんになるためにはサーバルちゃん本体が必要です。

 

今回使わせていただいたモデルはこちら。

3d.nicovideo.jp

ついでにさばんなちほーも。

seiga.nicovideo.jp

 

ちなみにどちらのモデルも配布サイトに従ってモデルをダウンロードするのですが、
MMDでの使用を想定してあるため、そのままではUnityに取り込むことが出来ません。

なのでちょっと一手間加えます。

サーバルちゃんは.pmx形式なのでMMD4Mecanim (※1)を使いUnityに取り込み、

さばんなちほーは.mqo(メタセコイア())形式のため、一度Blenderに取り込み、
Unityで扱える.fbxに変換します(この際にもblender側で.mqoをインポートするためのプラグインを使っていますが、今回は省略)

 

で、Unityに読み込んだらシーン上に配置します。

f:id:honzyou1753:20170916214637p:plain

 

やっぱりUnity楽でええなぁ。

ちなみにゲームビューではこんな感じ。

遠景まで見えると、ちゃんとさばんなちほー感でてます。

f:id:honzyou1753:20170916214928p:plain

 

記事の冒頭で紹介した動画見る限り、
そんなにやること多くなさそうなのでサクッと作っていきましょう。

 

あ、あと一応ですが配布されているMMDモデルによっては、改変の禁止・MMD以外への使用を禁止する規約等が定められている場合があるので、readmeとか配布サイトの規約はキチンと読みましょう。

 

※1: Nora(@Stereoarts)氏が公開しているMMDモデル形式をUnityに取り込むためのCustomAsset。

※2: 3Dモデリングソフトの一つ。無料でも使えるが、凄い機能が制限されるので筆者はBlenderの方が好き。

実装

HTCviveをトラッキングしてUnity側上で取れる情報は

  • ヘッドセットの 位置・向き
  • 左右コントローラーの位置・向き

です。VRトラッカーとか買えばもっと取れたりするんですが、今回は使わないし持ってないのでので割愛です。

www.vive.com

 

ヘッドセットでサーバルちゃんの頭、コントローラで左右の手の位置・方向を追従させることでサーバルちゃんになります。

その際IK(インバースキネマティクス)を使います。

IKを利用することで、手先の位置・方向を動かすだけで肩から手首までの角度を自動で計算し、曲げてくれるようになります。

IKについての詳細も話そうとすると別に記事一つ作れる量になりそうなので、割愛しますが興味が湧いたら調べてみると良いと思います。

 

ただ、IKを設定するスクリプトを自前で書こうとすると大変なので、

今回はUnityが提供するhumanoidのIK機能を使ってみたいと思います。

 humanoidのIK機能の設定

シーン上に設置したサーバルちゃんの元となるモデルデータを選択し

[Inspector]から[rig]を選択します。

[rig]項目内にある[AnimationType]から[humanoid]を選択します。

f:id:honzyou1753:20170916222111p:plain

[humanoid]に設定することで、人型のモデルにUnity側からUnity共通で使えるボーンの設定を行ってくれるようです。

 

これでIKが使えるようになったので、サーバルちゃんモデルにAnimatorControllerを追加しIKの設定をします。

と言っても、チェックボックスにチェック打つだけなんですが。

 

UnityのIKの設定は公式のマニュアルの方にも載っているので、参考までに。

docs.unity3d.com

 

きちんとIKが効いているかわからないので、公式マニュアルに従ってちょっとスクリプト入れてみましょう

 

仮のオブジェクトCube作成し、子オブジェクトに手を追従させるEntityを作成します。顔はカメラ目線でもしてもらいましょうか。

モーションはUnityのサンプルにあったhumanoidWalkをさせます。

f:id:honzyou1753:20170916224604p:plain

どうやらちゃんと効いているようですね。

シーンビューからCubeを動かしても、ちゃんと手が追従するのが確認できます。

f:id:honzyou1753:20170916224844p:plain

 

これでIKの設定ができたので、次回からいよいよHTCviveでサーバルちゃんと合体します。