Author: TRSasasusu

メタボールで洞窟

こんにちは。Kishiです。Unityで洞窟を作りました。

kcs_cave

メタボールをつなげ、さらにその法線を反転させることにより、任意の洞窟を作ることができます。

具体的には、マーチングキューブ法を使っています。その実装は、まず等電位面を計算し、そして空間を小さな立方体に分割して(ここであまり細かく分割するとUnityが固まるので注意)、その閉曲面内に各々の立方体の頂点が入るかを調べて入っている頂点を線形補完してつないで、そしてひたすら面を張っていくという単純なものです。Unityには最大頂点数があるのでこれをいかに超えるかが面白いところだと思います。

(テクスチャをもう少しきれいに貼りたい)

さて、8月には自作ゲームをリリースしようと思っているので、どこかのタイミングでトレーラーを出したいなと考えています(いつだろう)。

ConEmuでMSYS2を快適にする

こんにちは。Kishiです。

Windows 10のInsider Previewでは既にBash on Ubuntu on Windowsが使えるようですね(Ubuntuの例のバグが2013年になくなったことも関係しているか?)

それはさておき、ConEmuとMSYS2の話です。

MSYS2には標準でminttyがあるじゃないか、という声も聞こえてきそうですが、ただKaoriYaさんのVIMを使いたかっただけなのです。(これはwinptyをかませてもうまく動かなかった。もっと言うと、sl.exeがwinptyをかませても標準とは違う場所を走っていったため)

そこで、タブ付き、画面分割付き、そして背景画像を半透明化して表示できる(これ重要)ConEmuを導入しました。

kcs_cemx

まずはSettingsから、Startup→Tasksでmsys2を

set MSYSTEM=MSYS & c:\path_to_bash\bash.exe –login

で追加し、これをStartupに登録します。

次に、ConEmu Hereを動作させます。SettingsからIntegrationにてCommand:に

set MSYSTEM=MSYS & c:\path_to_bash\bash.exe -c "export CONEMU_CURRENT=$PWD && /c/path_to_bash/bash.exe –login"

と入力してRegister後にSave settings、そしてMSYS2の/etc/profileの一番下に

<br />
if [ -n ${CONEMU_CURRENT} ]; then<br />
    cd ${CONEMU_CURRENT}<br />
else<br />
    cd ~<br />
fi<br />

と書いて保存します。これで、任意のフォルダから右クリックでMSYS2を開けるようになりました。

ちなみに、MSYS2からエクスプローラは

$ start .

で開けます(cmd.exeでも同様)。

最後に、画面分割です。これは当初マウスを使ってGUIを操作してやっていましたが、やってられないのでコマンドからこれを可能にするプログラムを作成しました(実際は-new_console:sをうまく使えばできます)。

https://github.com/TRSasasusu/cemx

導入は簡単です。

<br />
$ git clone git://github.com/TRSasasusu/cemx.git<br />
$ cd cemx<br />
$ make<br />
$ ./cemx s<br />

以上です。あとは、cemx.exeを/usr/local/binあたりにおけばコマンドとして使えます。もちろん、ConEmu以外では動作しないのでご注意を。

(ConEmuを開いた後にCtrl+Win+Enterで幸せになれるかもしれません)

4月に定例会を3回開きました

こんにちは。Kishiです。副代表なのでこういう記事も書きます。

新年度が始まったので、新入生への自己紹介もかねてそれぞれの部員に自分のやっている研究内容を発表してもらいました。

内容としては、UnityでD言語を使う話に始まり、福澤諭吉先生をポアソン合成する話、AIにオセロをやらせる話、セルシェーディング、作曲、マーチングキューブ法、セキュリティキャンプ、AR、・・・など非常に多岐にわたりました(これでもごく一部)。

発表の後も多くの質問が出て、活発な議論ができました。

1年生にも発表してくれた方がいましたが、今後の定例会では1年生からも多くの人が発表できるでしょう。

(某大手ゲーム会社からの見学もありました)

Unityにおける親子関係構築時のサイズ変更問題 その2

こんにちは。Kishiです。

昨年、Unityにおける親子関係構築時のサイズ変更問題 という記事を書きましたが、これでもまだ解決できない場合があることに気づきました。

まず、このときの記事の概要はUnityにおいて親子関係を構築した時に子供のサイズがおかしくなるというもので、これはヒエラルキー上で

<br />
▽親オブジェクト<br />
  ▽New Game Object<br />
     子オブジェクト<br />

のようにすればよく、つまりスクリプトにおいて

<br />
// parentObjectは親オブジェクト, childObjectは子オブジェクトを指す。<br />
GameObject emptyObject = new GameObject();<br />
emptyObject.transform.parent = parentObject.transform;<br />
childObject.transform.parent = emptyObject.transform;<br />

とすれば解決できるというものでした。

しかし、今日親のRotationを変更した状態で親子関係を構築したら再びこの悪夢がやってきたのです。

kcs_lift

今回はGoogle検索は使わずRotationを手掛かりにスクリプトを書いてみたところ解決したので、これを以下に残します。

<br />
// parentObjectは親オブジェクト, childObjectは子オブジェクトを指す。<br />
GameObject emptyObject = new GameObject();<br />
emptyObject.transform.rotation = parentObject.transform.rotation; // この行を追加。<br />
emptyObject.transform.parent = parentObject.transform;<br />
childObject.transform.parent = emptyObject.transform;<br />

↑のように1行加えるだけで解決しました。

ちなみに、この写真はスピンアクションクリエイターからです。

Unityで関数の引数にListを使うと…

こんにちは。Kishiです。

ある日、Unity Editor上で軽快に動いていたアプリをAndroid向けにビルドしてみました。そして、いざ実行してみると…、

動かない。

正確には、アプリの一部の機能が動かないのでした。そこで、デバッグのためにDevelopment Buildにしてみると…、

こいつ・・・動くぞ!

訳がわからない。

とりあえず適当にデバッグしていると、Listを引数にとる関数が怪しいとわかりました。そして色々テストした結果、驚愕の事実が判明しました。

その関数内で引数にとったListをAddしたら異常終了する環境がある。

はい。しょうがないですね。意味はないかもしれないですがrefにしてもダメでした。

仕方がないので、Listをメンバ変数にすることでうまくやり過ごしました。みなさんも気をつけましょう。

以上。

Unityで使えるSkyboxを作る その2

こんにちは、Kishiです。今回もSkyboxをつくります。(その1

前回はBlenderを使いましたが、今回はシェーダーを書きます。

<br />
Shader &quot;Custom/base_uv_skybox&quot; {<br />
	Properties {</p>
<p>	}<br />
	SubShader {<br />
		Tags { &quot;RenderType&quot; = &quot;Background&quot; &quot;Queue&quot; = &quot;Background&quot; }<br />
		Pass {<br />
			ZWrite Off<br />
			Cull Off<br />
			Fog { Mode Off }</p>
<p>			CGPROGRAM<br />
			#pragma vertex vert<br />
			#pragma fragment frag</p>
<p>			#include &quot;UnityCG.cginc&quot;</p>
<p>			struct appdata {<br />
				float4 position : POSITION;<br />
				float3 uv : TEXCOORD;<br />
			};</p>
<p>			struct v2f {<br />
				float4 position : SV_POSITION;<br />
				float3 uv : TEXCOORD;<br />
			};</p>
<p>			v2f vert(appdata v) {<br />
				v2f o;<br />
				o.position = mul(UNITY_MATRIX_MVP, v.position);<br />
				o.uv = v.uv;<br />
				return o;<br />
			}</p>
<p>			fixed4 frag(v2f i) : COLOR{<br />
				return fixed4(i.uv.xyz, 1);<br />
			}</p>
<p>			ENDCG<br />
		}<br />
	}<br />
}<br />

これで、以下のような基本的な世界ができます。

kcs_skybox2_0

これを基にして_Timeを使って色々動かしてみたり、不思議な紋様を描いてみたり、といったことができます。

例えば、以下はパーリンノイズを適用したみたものです。

kcs_skybox2_1

Unityで使えるSkyboxを作る

こんにちは、Kishiです。今回はSkyboxを作ります。

  1. Blenderを開きます。
  2. UV球を作成します。大きさは中央の立方体よりもかなり大きくしてください。
  3. UV球を選択したまま編集モードからすべての面を選択してCtrl + Shift + Nですべての法線を内側へ向けます。あと、シェーディングから面をスムーズにします。
  4. 下図にシームをつけて展開します。UV図をエクスポートしたらお好きな空を描きます。
    kcs_skybox_6
  5. 描いた空をテクスチャとしてUV球に貼り付けます。
  6. 下図のようにランプの位置とエネルギを調節して太陽のようにします。
    kcs_skybox_2
  7. 中央の立方体を選択して下図のように設定します。
    kcs_skybox_0kcs_skybox_3
  8. F12でレンダリングします。そして、下図のようにお目当ての環境マップを保存します。(撮りなおしたいときは「環境マップをクリア」を選択してからF12)
    kcs_skybox_4

これで環境マップが手に入りました。そしていざUnityに持ってきてSkyboxのCubemapとして使おうとすると、ぐちゃぐちゃになってしまいます。

http://docs.unity3d.com/ja/current/Manual/class-Cubemap.html

このリンクからわかるように、Blenderで作られる環境マップの形のままではUnityでCubemapとして使えません。そこで、

https://github.com/TRSasasusu/blender_envmap_to_unity

このためのPythonスクリプトを作成しました。ライセンスはGPL v3ですが、このプログラム自体をあなたの制作物に含まない限り、その制作物にGPL v3は適用する必要はありません。(もちろん、適用したいならしてもかまいません)

使い方は簡単。ですがその前にPILをどうにかして手に入れます。(運が良ければ

<br />
$ easy_install pillow<br />

<br />
$ pip install PIL<br />

<br />
$ pip install Pillow<br />

で入るのですが、ダメなら

http://www.pythonware.com/products/pil/

で手に入れられます)

それから

<br />
$ python blender_envmap_to_unity.py hoge.png<br />

こうして完成した画像ファイルをUnityに持っていき、Texture TypeをCubemapにし、Fixup Edge Seamsにチェックを入れ、FormatをTruecolorにしてApply。そしてSkybox/Cubemapとしたマテリアルにこれを適用することで、ようやく自作Skyboxを作ることができます。
kcs_skybox_5

Blenderで環境マップを作るときに、UV球だけでなく山などもモデリングして立方体の周りにおいておけば、↑のような風景を作ることも可能です。

Unityで近づくと見えるシェーダー

こんにちは。Kishiです。今回はUnityでマリオギャラクシーのどこかのステージにあったような、近づくと見えるシェーダーを作ってみました。影もちゃんとついています。

非常に簡単です。Surface Shaderでも色々できるんですね。

まずはshader

</p>
<p>Shader &quot;Custom/hole_shader_complete&quot; {<br />
	Properties{<br />
		_MainColor(&quot;Color&quot;, Color) = (1,1,1)<br />
		_MainTex(&quot;Texture&quot;, 2D) = &quot;white&quot; {}<br />
		_BumpMap(&quot;Bumpmap&quot;, 2D) = &quot;bump&quot; {}<br />
		_PlayerPos(&quot;Player Position&quot;, Vector) = (0.0, 0.0, 0.0, 1.0)<br />
	}<br />
	SubShader{<br />
		Tags{ &quot;RenderType&quot; = &quot;Opaque&quot; }<br />
		CGPROGRAM<br />
		#pragma surface surf Lambert</p>
<p>		struct Input {<br />
			float2 uv_MainTex;<br />
			float2 uv_BumpMap;<br />
			float4 color : COLOR;<br />
			float3 worldPos;<br />
		};<br />
		float4 _MainColor;<br />
		sampler2D _MainTex;<br />
		sampler2D _BumpMap;<br />
		float4 _PlayerPos;</p>
<p>		void surf(Input IN, inout SurfaceOutput o) {<br />
			float4 c = tex2D(_MainTex, IN.uv_MainTex) * _MainColor;<br />
			float dist = distance(IN.worldPos, _PlayerPos);</p>
<p>			if (dist &lt; 5.0) {<br />
				o.Albedo = c.rgb;<br />
				o.Alpha = c.a;<br />
				o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));<br />
			}<br />
			else {<br />
				clip(-1);<br />
			}</p>
<p>		}<br />
		ENDCG<br />
	}<br />
	Fallback &quot;Diffuse&quot;<br />
}<br />

次は消したいものにつけるC#コード

<br />
using UnityEngine;<br />
using System.Collections;</p>
<p>public class HoleOther : MonoBehaviour {<br />
	[SerializeField]<br />
	GameObject player_;</p>
<p>	// Use this for initialization<br />
	void Start () {<br />
		GetComponent&lt;Renderer&gt;().material.SetVector(&quot;_PlayerPos&quot;, player_.transform.position);<br />
	}</p>
<p>	// Update is called once per frame<br />
	void Update () {<br />
		GetComponent&lt;Renderer&gt;().material.SetVector(&quot;_PlayerPos&quot;, player_.transform.position);</p>
<p>	}<br />
}<br />

以上です。