【Unity】Modelインポート時のシェーダーを自動で設定する

前回の続きです。

なんで2年以上も前の記事の続きを書いているかというと、エディタ拡張で「これどうすればいいんだろう。何かサンプル無いかなー」って検索したら、自分の記事が出てきて存在を思い出したからです(笑)

さて、今回困っていたことは、タイトルの通り「Modelインポート時のシェーダーを自動で設定する」です。
結論から書くと、OnAssignMaterialModel(モデルのマテリアルを割り当てる時に呼ばれる関数)内で変更すると良いみたいです。

下の例では以下の様な判定でシェーダーを変更しています。
  • インポートするモデルのパスにcharacterがあり、テクスチャの名前にeffectがある=>モバイル用加算シェーダー
  • インポートするモデルのパスにcharacterがあり、テクスチャの名前にeffectがない=>モバイル用ディフューズシェーダー
  • インポートするモデルのパスにcharacterがない=>ライトを使わないシェーダー
他には以下のことも行っています。
  • モデルと同じ階層にマテリアルを保存(何もしない場合はMaterialフォルダが作られ、その下に保存されます。)
  • パスにcharacterがない場合はアニメーションをインポートしない
補足事項としては、OnAssignMaterialModel内で全く変更したくない場合はnullをreturnするとokです。

CustomModelImporter.cs

using UnityEngine;
using UnityEditor;
using System.IO;

public sealed class CustomModelImporter : AssetPostprocessor
{
//Postprocessorの制御順(今回は使っていないのでいらない気がしています)
public override int GetPostprocessOrder()
{
return 0;
}

//インポート前の処理
void OnPreprocessModel()
{
//パスにcharacterが入っていなければ何もしない
if(!assetPath.Contains("character")) return;
var modelImporter = assetImporter as ModelImporter;
//アニメーションをインポートしない
modelImporter.importAnimation = false;
//アニメーションタイプを無しにする
modelImporter.animationType = ModelImporterAnimationType.None;
}

//material
//モデルから生成したマテリアル(データとしては保存されていません)
//renderer
//このパラメータの使い方分かってません…!
//戻り値
//設定するmaterialです。nullならUnityがデフォルトのマテリアル検索/生成メソッドを使用してマテリアルを割り当てます。
Material OnAssignMaterialModel(Material material,Renderer renderer)
{
//テクスチャの名前
string textureName = material.mainTexture.name;
//作成して保存するマテリアルのパス
string materialPath = string.Format("{0}/{1}.mat",Path.GetDirectoryName(assetPath),textureName);

Debug.Log("assetPath:"+assetPath);
Debug.Log("textureName:"+material.mainTexture.name);
Debug.Log("materialPath:"+materialPath);

//パスとテクスチャの名前によって、マテリアルを切り替える
//パスにcharacterという文字が含まれていたら
if(assetPath.Contains("character"))
{
//テクスチャにeffectという文字が含まれていたら
if(textureName.Contains("effect"))
{
//モバイル用加算シェーダーに変更する
material.shader = Shader.Find("Mobile/Particles/Additive");
}
else
{
//モバイル用ディフューズシェーダーに変更する
material.shader = Shader.Find("Mobile/Diffuse");
}
}
else
{
//ライトを使わないシェーダーに変更する
material.shader = Shader.Find("Unlit/Texture");
}
//シェーダーを変更したマテリアルをmaterialPathに保存する
AssetDatabase.CreateAsset(material, materialPath);Debug.Log(string.Format("CustomModelImporterの処理により、以下の場所に[{1}]シェーダーのマテリアルを作成しました。\n{0}",materialPath,material.shader.name));
return material;
}
}


もし何か、間違っている箇所とかあったら教えていただけると助かります!
(あとニコニコブロマガに綺麗にソースコード貼る方法あれば知りたいです)

========================================
2016/3/5追記
テクスチャが剥がれると報告を受けて、下記サイトの用に行うと良いと言う回避策を頂きました。

Unityで拡張子を変換するエディタ拡張
http://qiita.com/naotaro0123/items/6abe82ae0f827f675177

以下、全てのインポートされたマテリアルのシェーダーをUnlit/Textureに変更するスクリプトになります。

CustomAssetPostprocessor.cs
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections;

public class CustomAssetPostprocessor : AssetPostprocessor {
/// <summary>
/// あらゆる種類の任意の数のアセットがインポートが完了したときに呼ばれる処理
/// </summary>
/// <param name="importedAssets"> インポートされたアセットのファイルパス。 </param>
/// <param name="deletedAssets"> 削除されたアセットのファイルパス。 </param>
/// <param name="movedAssets"> 移動されたアセットのファイルパス。 </param>
/// <param name="movedFromPath"> 移動されたアセットの移動前のファイルパス。 </param>
static void OnPostprocessAllAssets
(string importedAssets, string deletedAssets,
string movedAssets, string movedFromPath)
{
// アセットがインポートされた場合
foreach(string asset in importedAssets){
// 拡張子のみ取得
string type = Path.GetExtension(asset);

if(type == ".mat"){
// マテリアルを取得
var material = AssetDatabase.LoadAssetAtPath<Material>(asset);
// シェーダーをUnlit/Textureに変更
material.shader = Shader.Find("Unlit/Texture");
}
}
}
}