今回はUnityで空に浮かぶ雲を動かしてよりリアルな感じを出してみたいと思います。
Unityでは最初にデフォルトのスカイボックスが設定されており、以下のような感じの空になっています。
デフォルトのスカイボックスは自動で作成されたものですが、自分でスカイボックスを作成する時は基本的に6個の空のテクスチャを用意し、それらを6面に貼り付けたCubeを表示したものです。
スカイボックスの作り方についてはUnityマニュアルを参照してください。
前後左右上下のテクスチャを表示してキャラクターがどの方向を見ても空が表示されるようになりますが、空のテクスチャに雲を描いていてもそれは動きません。
そこで今回はこの空を動かして少しリアルな感じを出してみたいと思います。
今回は2パターンの作成方法をやりますが、最初のスカイボックスの回転だけでいいかもしれません(場合によっては必要になるかも?)。(´Д`)
スカイボックスを回転させて雲が動いているように見せる
1からスカイボックスを作成すると大変なので、アセットストアで無料のスカイボックス用のテクスチャとマテリアルをダウンロードします。
アセットストアでカテゴリの「テクスチャ&マテリアル」で「空」を選択し値段でソートします。
その中のColorSkiesをインポートして使用します。
スカイボックスの設定と確認
UnityメニューのWindow→Rendering→Lighting Settingsを選択し、EnvironmentのSkybox MaterialにColorSkies/Skies/Sky_5を設定します。
これで空に雲があるスカイボックスが設定されました。
ここでスタンダードアセットのThirdPersonControllerをヒエラルキー上に配置し、MainCameraをThirdPersonControllerの子要素に移動しカメラが常にキャラクターの背後にあるようにします。
これでキャラクターを移動させると空は表示されていますが、雲が動いていないのが確認出来ると思います。
そこでこのスカイボックスに設定しているマテリアルのRotationを変化させ、スカイボックスを回転させることで雲が動いているように見せていきます。
スカイボックスをスクリプトで回転させる
スカイボックスに設定したSky_5マテリアルを選択してインスペクタを見ると、
上のようにマテリアルにRotationという項目があります。
このRotationの値を変化させるとスカイボックスが回転します。
そこでスクリプトを使ってこのスカイボックスのマテリアルのシェーダーのRotationを変化させる事でスカイボックスを回転させていきます。
新しくRotateSkyBoxスクリプトを作成し、何らかのゲームオブジェクトに設定します(今回はDirectional Lightに取り付けました)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateSkyBox : MonoBehaviour { // 回転スピード [SerializeField] private float rotateSpeed = 0.5f; // スカイボックスのマテリアル private Material skyboxMaterial; // Use this for initialization void Start () { // Lighting Settingsで指定したスカイボックスのマテリアルを取得 skyboxMaterial = RenderSettings.skybox; } // Update is called once per frame void Update () { // スカイボックスマテリアルのRotationを操作して角度を変化させる skyboxMaterial.SetFloat("_Rotation", Mathf.Repeat(skyboxMaterial.GetFloat("_Rotation") + rotateSpeed * Time.deltaTime, 360f)); } } |
rotateSpeedはスカイボックスの回転速度を設定し、skyboxMaterialにはLighting Settingsで設定したスカイボックスのマテリアルをStartメソッドで設定します。
Lighting Settingsで設定したスカイボックスのマテリアルはRenderSettings.skyboxで取得出来ます。
UpdateメソッドでskyboxMaterial.SetFloatでマテリアルのパラメータの_Rotationに現在のマテリアルパラメータの_Rotationに1秒間に回転する角度を足した値を設定しています。
角度は0~360の間で制限したいので、Mathf.Repeatを使って360を超えたら0になるようにしています。
これでスカイボックスが横に回転するようになりました。
ゲーム中に変化させたRotationの値はゲーム後も反映されますので、0からやり直したい場合はインスペクタで再度設定するか、スクリプトでRotationに0を設定するといいかもしれません。
実際に確認してみると、
上のような感じでスカイボックスが回転し、雲が動いているように見えます。
自前の球を作成し、それを回転させて雲が動いているように見せる
次はゲームの舞台を覆う球のゲームオブジェクトを作成し、それに空のマテリアルを設定し回転させて雲が動いているようにしてみたいと思います。
球の空を作成する時にProBuilderを使います。
球の空を作成する
球の空を使う場合はLighting SettingsのSkybox MaterialをNullにします。
球の空を作成していきます。
ヒエラルキー上で右クリック→3D Object→Sphereを選択します。
ヒエラルキーでSphereゲームオブジェクトを選択した状態でProBuilderウインドウのProBuilderizeボタンを押してSphereをProBuilderで使えるようにします。
ProBuilderのNew Shape ToolでIcosahedronで球に近いものも作れますが、綺麗な球とならずマテリアルを設定した時に凸凹が目立つ為、SphereをProBuilderで使えるようにしました。
次にヒエラルキーでSphereを選択した状態でProBuilderのFlip Object Normalsボタンを押します。
Flip Object Normalsボタンを押すと球を構成している表面が反転します。
なぜ表面を反転させる必要があるかと言うと、作成した球をゲームの舞台を覆うように配置して球の内側にマテリアルを表示したい為です。
反転せずにマテリアルを設定すると球の外側にマテリアルが表示され、ゲームの舞台から球を見ると内側なのでマテリアルが表示されません。
また球に衝突するコライダを設定した場合も球を反転させていないとコライダを持つキャラクター等が球の中に存在する事が出来ません(衝突判定される為)。
今回は球は衝突判定をしないのでコライダを設定する必要はありません。ただ衝突判定させたい時はこの事を考慮する必要があります。
面を反転させたらAltキーを押しながらExportボタンを押すと設定ウインドウが出るのでExport FormatをAssetにしてプレハブとして出力します。
プレハブにした球をヒエラルキー上にドラッグ&ドロップして名前をSkyboxObjとし、元々のSphereは削除します。
次にアセットストアで「df360」で検索し、出てきたDF360 -Volume1をインポートします。
このDF360はパノラマの空と地面を含むマテリアルが入っているので、Assets→DutchFree360→Volume_1→02b_UnClipped_SunSkies→Materialsの中のDF360_006_Reloaded_4k_sRGB_usをSkyboxObjにドラッグ&ドロップし設定します。
次にSkyboxObjのTransformのScaleをXYZで1000にしてゲームの舞台を覆うように配置します。
これで球の内部から球の方を見ると空と地面が表示されます。
上のようになりましたが、ゲームの球の空の中にちっちゃくゲームの舞台が見えています。
これで空が出来上がりました。
スクリプトで球を回転させる
スカイボックスの時のようにこの球の空をスクリプトで回転させましょう。
スクリプトをSkyboxObjに取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateSkyBox : MonoBehaviour { // 回転スピード [SerializeField] private float rotateSpeed = 0.5f; // Update is called once per frame void Update () { transform.Rotate(Vector3.up * rotateSpeed * Time.deltaTime); } } |
ワールドのY軸で回転させています。
これでスカイボックスと同じように空を作成する事が出来ました。
ただ球は他のゲームオブジェクトと同じなので、球が小さいとキャラクターを動かした時に空に近づいてしまいます。
なので、TransformのScaleのXYZを1000としてゲームの舞台よりかなり大きくしています。
また今回使用したマテリアルは地面を含みますので、場合によっては地面が見えてしまいます。
オブジェクトを回転させないでマテリアルのタイリングを変更して回転しているように見せる方法
ゲームオブジェクト自体を回転させて空の雲が動いているように見せる方法の他にオブジェクトに設定したマテリアルのテクスチャのタイリングを変更して回転しているように見せる事も出来ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateSkyBox2 : MonoBehaviour { // 回転スピード [SerializeField] private float rotateSpeed = 1f / 60f; // スカイボックスのマテリアル private Material skyboxMaterial; // Use this for initialization void Start () { // Lighting Settingsで指定したスカイボックスのマテリアルのテクスチャを取得 skyboxMaterial = GetComponent<MeshRenderer>().material; } // Update is called once per frame void Update () { skyboxMaterial.mainTextureOffset = new Vector2(Mathf.Repeat(skyboxMaterial.mainTextureOffset.x + rotateSpeed * Time.deltaTime, 1f), 0f); } } |
Updateメソッドでスカイボックスのマテリアルに設定したメインテクスチャのオフセットのXを変更しています。
タイリングは0~1の間でループさせるようにしています。
なので回転するスピード(rotateSpeed)が1の場合は1秒で空が1周するので60で割ると1分で1周、さらに60で割れば1時間で1周することになります。
雲が別に動いているように見せる
球の空を回転させる事で空全体が動いているように見せることが出来ました。
しかし雲が一緒に動いてしまうので少しリアルさに欠けてしまいます。
そこでSkyboxObjの空とは別に雲を作成し、少しリアルな感じを出してみたいと思います。
SkyboxObjを選択した状態でCtrl+Dキーを押してゲームオブジェクトをコピーし、名前をCloudにします。
Assetsエリアで右クリック→Create→Materialを選択し、名前をMyCloudとし、Cloudゲームオブジェクトにドラッグ&ドロップして設定します。
次に雲のテクスチャを作りますが、今回はわたくしの作った適当な雲を使ってください(もちろんご自分で用意されても構いません)。
画像をドラッグして、デスクトップ等にドロップしてください。
雲の背景は透明になっている必要があります。
上の空白のような部分に画像が表示されていますが、雲を白色で描いているので意味のない空間があるだけのように見えますが・・・・・(^_^;)
雲のテクスチャは2048×2048サイズで作成しています。
雲のテクスチャ画像をUnityに取り込んだら、インポートの設定を行います。
上のような感じで設定しました。
先ほど作成したMyCloudマテリアルの設定を行います。
MyCloudのRendering ModeをTransparentにし、Albedoにインポートした空のテクスチャを設定します。
これでCloudゲームオブジェクトが出来上がりました。
雲の部分以外は透明なので先ほど作ったSkyboxObjも見えます。
Cloudゲームオブジェクトは上のようになりましたが、デフォルトのDirectional Lightの光をそのまま使うと雲の明るさにムラが出てしまうので、Cloudゲームオブジェクト専用のDirectional Lightを作成する事にします。
CloudゲームオブジェクトのインスペクタのLayer部分をクリックし、新しくCloudレイヤーを追加しCloudゲームオブジェクトにCloudレイヤーを設定します。
次にデフォルトで配置されている太陽の光として使っているDirectional Lightを選択し、Culling MaskでCloudレイヤーを外します。
Culling MaskでCloudレイヤーを外したことでCloudゲームオブジェクトはこのDirectinal Lightの光が当たりません。
ヒエラルキー上で右クリック→Light→Directional Lightを選択し、名前をSkybox Directional Lightとします。
TransformのRotationのXを270にします。
Skybox Directional LightのCulling MaskでCloudレイヤーだけをチェックし、Cloudゲームオブジェクトだけに光が当たるようにします。
上のように球の空の雲に光があたり雲がわかりやすくなりました。
CloudゲームオブジェクトにもRotateSkyBoxスクリプトを取り付け、インスペクタでrotateSpeedの値を変更し、SkyboxObjとは回転するスピードを変えます。
CloudゲームオブジェクトはSkyboxObjと同じ大きさで作っており、さらに雲の部分以外は透明なので、同じ領域を動く二つの球が違う速度で回転する事で別の雲の動きを作っています。
別に動く雲の確認
それでは機能が出来たので確認してみましょう。
上のようになりました。
Cloudゲームオブジェクトの回転スピードをSkyboxObjとは変えたことであたかも雲が別に動いて見えるようになりました。
雲のテクスチャはいいかげんに作りましたが、なんだかそれっぽく出来てますね。(^^)/
終わりに
スカイボックスはゲーム全体の周囲に描画されるので、遠景として使用でき、どれだけ追いかけても近づいてくることはありません。
ただスカイボックスの回転はワールドのY軸でしか回転出来ません(出来るかもしれませんがシェーダースクリプトを変更する必要があるかも?)。
一方、球で作成した空の場合は物理的な大きさを持っている為、相当な大きさの球を作らないとキャラクターが近づいた時に空が近づいてきます。(^_^;)
ただ球のゲームオブジェクトを回転させるので自由に回転をさせることが出来ます(特別に必要性を感じませんが・・・・)。
今回は球を使って雲を空とは別に動いているように見せていますが、パノラマ動画の機能を使えばあらかじめ空と雲のパノラマ動画を用意しておき、それを再生して空を作成する事が出来ます。
最初から動画として作成されているものを再生するだけなのでリアルな空のパノラマ動画を用意出来れば後は設定するだけです。
パノラマ動画については
を参照してください。