■Unity開発メモ用のWiki◎現在扱っていること・Unity全般・MMDからUnityへの変換してインポート・MMDの仕様把握・BlenderでMMDモデルのカスタム

目次


マップMOD用のUnityテンプレート

Free HやStudioで使用できるマップMODの作成例です。
マップMODは非常に複雑で、初心者に優しいものではありません。
まず、PurpleRoomファイルを開いてください。他のタイプのMODとは異なり、マップはアセットバンドル内のアセットではなく、アセットバンドル内のシーン(シーンアセットバンドル)です。
→AssetBundleにScene自体を含める? 参考:【Unity】SceneをAssetBundleに格納して実行時にロードする方法について:https://tsubakit1.hateblo.jp/entry/2016/08/23/2336...

一度開くと、壁、床、オブジェクト、照明、Hポイントなどを含むマップのプレビューがシーンビューに表示されるはずです。
このマップはUnityの基本的なシェイプから作られていますが、通常はBlenderやお好みの3Dエディタでマップを作成し、.
obj, .fbx, .blend などのファイルをプロジェクトフォルダに保存しておきます。
Unityはそのモデルをインポートし、シーン階層にドラッグ&ドロップすることでシーンに追加することができます。
Blenderで再度モデルを保存すると、Unityはそれを再インポートし、変更内容で自動的にシーンを更新します。
したがって、マップを作成するワークフローは、3Dモデリングプログラムでモデルを構築し、
Unityにインポートし、MonoBehaviorsやライティングなどを追加することになります。

ルートノード(Map)を選択すると、2つのMonoBehaviorsがアタッチされているのが見えます。
SunLightInfo。1日のさまざまな時間帯の太陽光に関するデータです。3つの要素(昼、夕方、夜)があり、それぞれに光の色と角度、霧の色、LUTテクスチャなどが含まれている必要があります。
VisualizeGizmos。エディタでHポイントを視覚化するためのカスタムスクリプトです。マップの最終版をビルドしてリリースする前に削除する必要があります。
これを独自のマップに設定するには、HPointContainer を HP ポイントを含むトランスフォームに設定します。


次に「太陽光」を選択します。これは、ゲーム側が制御するシーンに追加される指向性光です。
インスペクタに「Sun」というタグがあるので、正しくタグ付けされないと正しく機能しないことに注意してください。
ここで設定したものは、SunLightInfoの設定によって上書きされますが、Unityのライティングをプレビューするのに便利です。
Sunlightの下には、SunShaftSourceトランスフォームがあります。
これ自体は何もしませんが(単なる空のトランスフォーム)、SunLightInfo はこのトランスフォームを、
サンシャフトが発生する位置として使用するように設定されています。


h_free は空のトランスフォームで、フリー H モードが開始される位置と回転をゲームに指示します。


background は、シーン全体を囲む大きなメッシュで、色は黒です。フォグが正しく機能するために必要です。

shadowcaster は、シーンを囲むメッシュで、影を落とす役割をします。
シーンの壁は影を落とすモードがオフに設定されており、
このメッシュは影を落とすモードが影のみ、つまり見えないが影を落とすモードに設定されていることに注意してください。

roomは、シーン全体を構成するメッシュの束です。すべてのメッシュはレイヤー「マップ」を使用していることに注意してください。

Hポイント

Map階層の外側にHPoint_Disabledが表示されているはずです。
これはHPointデータのプレハブを含むGameObjectを無効にしたものです。
Hポイントとは、ゲーム内で位置の遷移に使われるポイントです。
HPointsで使用されるIDの一覧は、このReadmeの最後を参照してください。

HPoint 通常のHポジションのHポイントに関するデータが格納されています。
HPoint_Add。レズビアン、オナニーに関するデータが含まれています。
HPoint_3P:3Pのデータが含まれています。



各種Hモードの開始位置は、このように計算されます。
Free H:シーン内の h_free トランスフォーム
レズとオナニー シーンの中心に最も近い、正しいカテゴリーのHポイント
3P: 3P_00 Hポイント
これらが存在しない場合、マップの中心(0,0,0)が開始点となります。

Hポイントは、マップMODを構築してリリースする前に、シーンから削除する必要があります。
開発中に視覚化する目的で、このシーンにのみ残されています。
HPointプレハブは、シーンとは別のアセットバンドルにコンパイルされています。

マップマスキング

マップマスキングは、カメラがマップの後ろに行ったときに、マップの一部を隠します。
つまり、邪魔にならないように、壁の一部全体が消えます。
マスキングは、map_col_(MapID)という形式の .txt ファイルであるリストファイルによって制御されます。
これは、h/list/フォルダー内のアセットバンドルにコンパイルされている必要があります。
リストファイルはタブ区切りのリストで、最初のエントリはコライダと、それによって隠されるすべてのトランスフォームです。
この例では、2つのカプセルがマスクされるように設定されています。

マップマスキングは、コライダーがカメラターゲットとカメラの間に来ると、ゲーム内でトリガーされます。
トリガーされると、指定されたトランスフォームが非表示になります。

ライティング

太陽光の挙動は、Map にアタッチされた SunLightInfo MonoBehavior で設定されます。
影は通常、マップオブジェクトではなくシャドウキャスターメッシュによって制御されます。
なぜなら、多くのマップオブジェクトは単一の面しか持たず、一方向から影を落とさない傾向があるからです。
屋内マップの大部分は影になるので、これを補正するために、マテリアルはある程度の発光を持つように設定する必要があります。

時間帯によって照明の方向や色が変わるだけでなく、ゲームオブジェクトも時間帯によって変化させることができます。
RoomのWallsフォルダ内に、Window_d、Window_e、Window_nがあります。
これらのうち2つは無効になっており、1つはUnityでプレビューするために有効なままになっています。
SunLightInfo MBにはVisibleList要素があり、その中にこの3つのオブジェクトがあり、1日の3つの時間帯にそれぞれ1つずつあります。

指向性ライトの角度を変更することは、ライティングのプレビューに便利ですが、ゲーム内で一度設定した角度は保持されないことに注意してください。
SunLightInfo MonoBehaviorで設定された角度が、指向性光の制御に使用されます。

リストファイルとアセットバンドル

マップとそのデータは、6つの別々のアセットバンドルにまとめられています。
  • map/list/mapinfo/purpleroom.unity3d
    • PurpleRoom MapInfo アセットはここにあります。
    • マップをFree Hの選択リストに追加するために必要な、マップに関する情報が含まれています。
  • map/scene/purpleroom.unity3d
    • PurpleRoomのシーンは、このアセットバンドルにコンパイルされています。
    • このシーンは、リストファイルに反映される限り、自分のマップ用に好きな名前に変更することができることに注意してください。
  • map/thumbnail/purpleroom.unity3d
    • 3つのサムネイルはここにあります。
    • サムネイルは、昼、夕方、夜のサムネイルのために、_00, _01, _02という接尾辞で名前を付ける必要があります。
  • h/list/purpleroom.unity3d
    • マップマスキングリストがここにあります。
    • map_col_(MapID)という名前の.txtファイルであるべきです。
  • h/common/purpleroom.unity3d
    • Hポイントのプレハブはここにコンパイルされます。
  • vr/common/purpleroom.unity3d
    • VR用のH Pointはここにコンパイルされています。
    • Hポントのコピーを2つ別々に管理するのは時間がかかるので、これを半自動化するスクリプトが存在します。
    • 3つのHPointプレハブをVRPointフォルダにコピーし、右クリックから「Configure VR HPoints」を選択します。
    • (.metaファイルはコピーしないでください)HPointsのテストと設定がすべて完了した後、リリース前に一度だけこの作業を行ってください。

purpleroom.unity3dを自分の好きなアセットバンドル名に置き換えて、自分のMODを作成します。

また、マップはList/Studioフォルダに.csvを追加することで、簡単にStudioに追加することができます。
マップをStudioで機能させるために追加で変更する必要はなく、Free Hで動作するものはStudioでも問題なく動作します。

HポイントIDの競合に関する注意点

SideloaderはFree HメニューにあるマップのIDを解決しません。
他のModderと調整し、あなたのマップModのID範囲を主張してください。
IDの衝突が問題になるほどのマップMODが作られることはないでしょうし、
たとえ問題になったとしても、Free Hのものはカードやシーンに保存されないので、
ユーザーに影響を与えずにIDを変更することができます。
StudioのマップIDはsideloaderで解決されるので、IDの衝突は起きないはずです。

◎HポイントID

マップMODのまとめ方改

目的:マップの取捨選択をし、軽量化と選択画面での利便性を上げる

KoikatsuSunshineModdingToolsのScriptableGameobjectを取得する


CallTestData

必要なデータを取り出す

・対象のマップMODを解凍する
・パス「MOD名¥abdata\map\list」→「mapinfo」「mapthumbnailinfo」それぞれのファイル「****.unity3d」を
ツール「AssetStudioGUI」などを使ってリパックする
 →リパックで必要なデータはMonoBeheviourの「***_thnumbnail_list」と「***_Map_list」
「***_thnumbnail_list」


「***_Map_list」

マップのサムネイルに必要なデータを編集する

  • 目標:Unityのスクリプタブルオブジェクト(ScriptableObject)をYAML形式でやや強引に編集する
    • マップの情報はUnityのスクリプタブルオブジェクト(ScriptableObject)で定義されている
    • 上記のデータを直接開いてYAML形式で書き換える

◎リパックしたUnityデータ「***_thumbnail_list.json」を正規表現でYAML形式に変換していく
サムネイルは以下の4項目が一塊として必要(名前、ID、アセットバンドルへのパス、アセットの名前)
・Name": "*****",
・ID": ****,
・"Bundle": "map/thumbnail/*****.unity3d",
・ "Asset": "**_***_****_**"

◎正規表現で不要な行を消していく
・以下のコマンドで指定したキーワードを含む行を削除する
^.*キーワード.*$(\r\n|\r|\n)?
・正規表現の「^(キャレット)」で行頭にコピペで空白を挿入する
・単純な置換で「 - Name」に置き換える

◎要らないマップの情報を削除する
・マップのサムネイルは「 Name、 ID、Bundle、Asset」の4つのパラメータ×「朝・昼・夕方・夜」の4種類で一つのかたまりとなっている
・最後にエディタ等で行数をチェックし、4の倍数になっているか確認する

Unityでのスクリプタブルオブジェクトの作成(環境構築編)

・KKS版と同じUnityバージョン(2019.4.9f1)で新しくプロジェクトを作成する
・KoikatsuSunshineModdingToolsのKKS版のUnityプロジェクトから、
 マップのスクリプタブルオブジェクトの作成に必要な、以下のスクリプトをコピーして持ってくる
  • MapInfo
  • MapThumbnailInfo
・マップのスクリプタブルオブジェクトをアセットバンドルとしてビルドする為に必要な「 Asset Bundle Browser」をインストールする

Unityでのスクリプタブルオブジェクトの作成

・「プロジェクトウィンドウ」を右クリック→「作成」→「MapThumbnailInfo」



・□{} ←こんなやつがUnityのアセットに作成されるので、名前をUnityからアンパックした時のファイル名に変更する



・パラメータのサイズを必要なマップ数分入力する



エクスプローラからスクリプタブルオブジェクトをテキストエディタ等で開き「pram:」以下の行を先程正規表現で置換したテキストと入れ替える



・Unityのインスペクタでスクリプタブルオブジェクトが正しく設定されているか確認する。
(上記のスクショは「”」を削除し忘れてエラーになっていた)

アセットバンドルのビルドとゲーム内での確認

「Asset Bundle Browser」タブを開き、作ったものをドロップしビルドする
ビルドしたのはUnityプロジェクトの\AssetBundles\StandaloneWindowsにある


・何も拡張子がついていないファイルをZIPMODに戻す

・ファイル名はオリジナルと同じになるように注意する!
 →「.unity3d」をつける?


・ゲーム内で反映されているか確認する

同様にマップ本体のデータも書き換えていく









マップMOD用のスクリプタブルオブジェクト(ScriptableObject)を作成する

ScriptableObjectとは

参考:【Unity】今更ScriptableObject入門:https://qiita.com/4_mio_11/items/a7d8967b853cef438...
ScriptableObjectとは、ゲームやアプリの中で変化せず、あちこちで共用するデータを格納する時に便利なクラス
→例えば、敵のパラメータなど
個別のゲームオブジェクト等にアタッチはせず、都度アセットをロードして使用する
別の手法の例
  • ハードコーディング(クラス内に直接書く)
  • CSVやJsonで定義して読み込む

例えば敵の最大体力が共通のものならば、各Prefabのコンポーネントにパラメータを持ってしまうと、
敵の数分そのパラメータの容量が必要になるがScriptableObjectのテーブルから参照すれば、データは一つですむ
ScriptableObjectのテーブルを使えば、パラメータのみが別アセットに分離しているのでコンフリクトしにくい

ゲームが終了した後にデータは全て初期値に戻るため、セーブデータ的な使い方はできない
逆にエディタ上で値を変更すると、そのままアセットに直保存される。
「エディタ上で実行中にパラメータ等の値を変更してゲームバランスを調整する」という工程がこの仕様によって非常に楽に進めることができる

アセットファイルへの書き込みは AssetDatabaseクラスから行われ、
スクリプト側からパラメータ等の値を変更した際には明示的に AssetDatabase の SaveAsset() を呼び出す必要がある
ただ、このSaveAsset()は実機での起動中は呼び出すことができない

ScriptableObjectの使用方法の流れ
  1. ScriptableObject派生クラスの作成
  2. ScriptableObject派生のクラスをアセット化
  3. パラメータを設定
  4. ScriptableObject派生のクラスを使用
ScriptableObjectのサンプル
参考:作成したScriptableObjectを呼び出す:https://tsubakit1.hateblo.jp/entry/20140322/139547...
1.ScriptableObjectの作成
using UnityEngine;

[CreateAssetMenu(fileName = "TestData", menuName = "ScriptableObjects/CreateAsset")]
public class TestData : ScriptableObject
{
    [SerializeField]
    public int count;
    [SerializeField]
    public string msg;
}

2.ScriptableObjectのパラメーターを設定する




3.ScriptableObjectの派生クラスの作成
using UnityEngine;

public class CallTestData : MonoBehaviour
{
    public TestData m_testData;

    void Update()
    {
        Debug.Log(m_testData.count);
        Debug.Log(m_testData.msg);
    }
}
後はドラッグ&ドロップでScriptableObjectを登録すれば呼び出すことが出来る




Resourcesから呼び出す場合
下のコードではStartのタイミングでResourcesフォルダに配置したtestdata.assetファイルをを呼び出している。

Resourcesフォルダ以外から呼ぶ場合
m_testData = AssetDatabase.LoadAssetAtPath<TestData>("Assets/TEST_001/testdata.asset");

using UnityEngine;

public class CallTestData : MonoBehaviour
{
    private TestData m_testData;

    void Start ()
    {
        m_testData = Resources.Load<TestData> ("testdata");
    }

    void Update ()
    {
        Debug.Log (m_testData.count);
        Debug.Log (m_testData.msg);
    }
}

作成の流れ

Unityプロジェクトを作成する(KKSと同じUnityVer2019.4.9が無難?)
「パッケージマネージャー」ウィンドウ→「UnityRegistry」タブ→「Asset Bundle Browser」をインストールする

KoikatsuSunshineModdingToolsにある以下のスクリプトを自分のプロジェクトにドロップ
  • 「MapThumbnailInfo」→マップのサムネイルに関するScriptableObject
  • 「mapinfo」→マップ情報
  • 「」

上記で自分のアセットにインポートしたスクリプトに対応した、ScriptableObjectを作成する
→プロジェクトウィンドウ→アセットタブ→何も無いところで右クリック→「Map Thumbnai lInfo」など
→新しく作ったScriptableObjectには接頭にMODのイニシャルみたいなのをつける?

Resourcesフォルダを作成し、そこに上記のScriptableObjectを入れる
→unityでの動作テスト用
ScriptableObjectのパラメーター入力
【マップのサムネイルの場合】
1つのマップに付き、朝〜夜までの4つの時間経過差分の設定が必要
パラメーターは「MOD名\abdata\map\list\***.unity3d」等にあるアセットをAssetStudioGUIなどで確認する



Resourcesからアセットバンドルをロードするテスト
リソースフォルダのあるアセットバンドルを読み込む例
設定が正しければ、Unityのコンソールに出力される
public class CallTestData : MonoBehaviour
{
    //マップサムネイル用のScriptableObjectの型    
    private MapThumbnailInfo m_testData;
    void Start()
    {
        m_testData = Resources.Load<MapThumbnailInfo>("MHM_thumbnail_list");

        //マップの名前
        UnityEngine.Debug.Log("name::" + m_testData.param[0].Name);
        //マップのID
        UnityEngine.Debug.Log("ID::" + m_testData.param[0].ID);
        //マップのバンドル
        UnityEngine.Debug.Log("Bundle::" + m_testData.param[0].Bundle);
        //マップのアセット
        UnityEngine.Debug.Log("Asset::" + m_testData.param[0].Asset);
      
    }
}
アセットバンドルをビルドする
参考:【Unity】AssetBundleの簡単なつくり方【コード不要】:https://your-3d.com/unity-assetbundle-simple/
◎ScriptableObjectをアセットバンドルとしてビルドする


◎ビルドしたアセットをゲーム側の「StreamingAssets」フォルダからロードする
「C:\illusion\KoikatsuSunshine\KoikatsuSunshine_Data」にある「StreamingAssets」フォルダへ先程ビルドしたアセットバンドルを入れる
→ビルドしたのはUnityプロジェクトの\AssetBundles\StandaloneWindowsにある?

◎サイドローダー形式に対応して読み込む

    private MapThumbnailInfo m_testData2;
    void Start()
    {
            // サイドローダー経由の「abdata」からAssetBundleをロードする
            var assetBundle2 = AssetBundle.LoadFromFile("C:/illusion/KoikatsuSunshine/abdata/map/list/mapthumbnailinfo/MHM000.unity3d");
            UnityEngine.Debug.Log("assetBundle2::" + assetBundle2);

            // AssetBundle内のアセットにはビルド時のアセットのパス、またはファイル名、ファイル名+拡張子でアクセスできる
            m_testData2 = assetBundle2.LoadAsset<MapThumbnailInfo>("MHM_thumbnail_list");
            UnityEngine.Debug.Log("m_testData2::" + m_testData2);

        //マップの名前
        UnityEngine.Debug.Log("name::" + m_testData2.param[0].Name);
        //マップのID
        UnityEngine.Debug.Log("ID::" + m_testData2.param[0].ID);
        //マップのバンドル
        UnityEngine.Debug.Log("Bundle::" + m_testData2.param[0].Bundle);
        //マップのアセット
        UnityEngine.Debug.Log("Asset::" + m_testData2.param[0].Asset);
    }

マップデータをまとめる(旧)

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

【メニュー編集】

スカイリム関連

スカイリム関連


Menu

【メニュー編集】

スクリプト関連

フリーエリア

管理人/副管理人のみ編集できます