10日目：空背景(スカイドーム)で学ぶUV展開とUVOffset

この記事はアドベントカレンダー「[【VCI】テーマパーク を作ろう](https://adventar.org/calendars/5855) 」の10日目の記事です。

# 今回の内容
今回は昼と夜が切替可能な空の背景(スカイドーム)を作りながら以下のことを学んでいきます
　・BlenderでのUV展開
　・UVOffsetの使い方
スカイドームとは球または半球に画像を貼り付けた様なものとなります
今回は半球で作成します。

# Blenderでのスカイドーム作成
※UV展開にはあまり詳しくないため紹介する方法よりもっといい方法があるかと思います。
もし「もっといいやり方知ってるよ！」って人いたらコメント頂けるとありがたいです。

## UV展開
今回作成に当たりいろいろ情報を調べましたが、スカイドームの作成にはいくつか方法があるみたいです。
今回は以下のサイトを参考にUV球を使い、円形の画像を使って作成します。
　・https://rikoubou.hatenablog.com/entry/2018/05/21/174949
画像は昼用のものは趣味で撮った360度画像があったのでそちらを使っていきます。夜用の方は球面画像でもないフリー素材を使ってみます。

基本的に上記サイトにそって勧めました。ただ、デフォルトはメッシュが外向きになっているのでメッシュの向きを反転させる必要があります。
全選択してメッシュ>ノーマル>反転で逆向きにしましょう。
完成した図が以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/ab642a88-08c3-4adc-fb38-77bd8cd903a9.png)

確認の際にマテリアルのプロパティの裏面の非表示にチェックを付けておくと裏面が映らなくなり確認しやすくなります。
(上記画像の右下の方にある項目)

UVの味方ですが、左のウィンドウがUV用のビュー、右側がモデリング用のビューです。
左側のウィンドウの頂点が右側の頂点と対応しています。試しにUVビューで頂点を動かしてみるとモデリングのビューで画像の表示が変わるのがわかるかと思います。
あとはUV画面を見ながらUV頂点の位置・サイズを調整したら完成です

## UVOffset用の設定
(ここから独自流となります。)
スカイドーム自体は上記手順で完了なのですが、今回は昼用と夜用の背景を切り替えられるようにしたいためここからUVOffset用の加工をしていきます。
UVOffsetとは複数の画像を1枚にまとめ、メッシュ位置と画像をずらすことでモデルに表示される絵柄を切り替える手法です。

まず昼用と夜用を横並びにくっつけた画像を用意します。
次にその画像をUVビューの画像メニューから開きます。
すると以下のような画像の状態になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/450fa6d9-3b86-ae54-4e90-95b3fa31e69c.png)

このままでは昼と夜が半々のスカイドームとなってしまうため、UVビューで以下のように頂点を修正します。
(x方向のsizeを0.5し、さらにxのマイナス方向へ0.5ずらすと以下のようになります。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/71565b48-5313-f365-dd86-124a2e95d08a.png)

これて1枚の画像に昼と夜の状態を持ちながら昼の状態のみを表示することができました。
現在は昼の部分しか表示されていませんが、Vキャスで関数を使うことで夜の状態と昼の状態を切り替えます。
(blender上で夜の方の画像も確認できる方法があった気がしますが思い出せないので今回は省略します)

完了したらfbxに出力します

# Unityでの設定作業
Unityで特に設定する作業はありませんが、マテリアルの項目にoffsetというものがあるので、こちらを変更すると夜の見え方も確認できます。
offsetは先ほどのUV画像をどれくらいずらして表示するかという意味で、一番左上がx=0,y=0,一番右下がx=1,y=1となっています。
今回はxに0.5を指定すると画像が半分だけ横にずれて夜の状態を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/57afe679-c72b-5e9e-dc1b-718470b047ff.png)


## コード作成
ここからはVキャス及びエディタでの作業となります。

今回は画像をずらして表示するのにUVoffestの機能を使います。
　・[vci.assets(ExportAssets)](https://virtualcast.jp/wiki/doku.php?id=vci:script:reference:exportassets)
　　(SetMaterialTextureOffsetFromNameという関数を使います)

今回は30分ごとに昼と夜が切り替わるように作成しました。
(00~29分が昼，30~59分が夜)

``` lua
-- 昼かどうかのを管理するフラグ。昼だとTrue。夜だとfalse
local isDaytime = true

-- スカイドームのUVOffset更新用の関数
function refreshSkyDome()
  -- 分を取得して文字列から数値に変更(数値に変更しないと大小の比較ができない)
  local minute = tonumber(os.date("%M"))

　--昼かつ30分より後の時
  if isDaytime and minute >= 30 then
    -- 画像をx方向に半分(0.5)ずらして表示
    vci.assets.SetMaterialTextureOffsetFromName("SkyDome",Vector2.__new(0.5, 0.0))
    -- フラグを夜にする
    isDaytime = false
  elseif not isDaytime and minute < 30 then
    -- 画像をずらさないで表示
    vci.assets.SetMaterialTextureOffsetFromName("SkyDome",Vector2.__new(0.0, 0.0))
    -- フラグを昼にする
    isDaytime = true
  end
end

function updateAll()
  -- ここに今まで作成した別の処理あり(省略) --

　-- 関数の呼び出し
  refreshSkyDome()
end
```

あとは動作確認して完了です！無事夜になりました！
![20201212-003847.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64877/1bbaea6c-772b-3de6-e5c6-43ddbfd53626.png)


# 終わりに 
いかがでしたでしょうか？
今回作成したスカイドームはあとあと夜との切り替えができるようにしようと思っているため、もしかしたらまるごと別の方法で作成したものに置き換えるかもしれません。
次回は観覧車を回していきたいと思います。