【Unity】Modelインポート時のシェーダーを自動で設定する
前回の続きです。
なんで2年以上も前の記事の続きを書いているかというと、エディタ拡張で「これどうすればいいんだろう。何かサンプル無いかなー」って検索したら、自分の記事が出てきて存在を思い出したからです(笑)
さて、今回困っていたことは、タイトルの通り「Modelインポート時のシェーダーを自動で設定する」です。
結論から書くと、OnAssignMaterialModel(モデルのマテリアルを割り当てる時に呼ばれる関数)内で変更すると良いみたいです。
下の例では以下の様な判定でシェーダーを変更しています。
CustomModelImporter.cs
もし何か、間違っている箇所とかあったら教えていただけると助かります!
(あとニコニコブロマガに綺麗にソースコード貼る方法あれば知りたいです)
========================================
2016/3/5追記
テクスチャが剥がれると報告を受けて、下記サイトの用に行うと良いと言う回避策を頂きました。
Unityで拡張子を変換するエディタ拡張
http://qiita.com/naotaro0123/items/6abe82ae0f827f675177
以下、全てのインポートされたマテリアルのシェーダーをUnlit/Textureに変更するスクリプトになります。
CustomAssetPostprocessor.cs
なんで2年以上も前の記事の続きを書いているかというと、エディタ拡張で「これどうすればいいんだろう。何かサンプル無いかなー」って検索したら、自分の記事が出てきて存在を思い出したからです(笑)
さて、今回困っていたことは、タイトルの通り「Modelインポート時のシェーダーを自動で設定する」です。
結論から書くと、OnAssignMaterialModel(モデルのマテリアルを割り当てる時に呼ばれる関数)内で変更すると良いみたいです。
下の例では以下の様な判定でシェーダーを変更しています。
- インポートするモデルのパスにcharacterがあり、テクスチャの名前にeffectがある=>モバイル用加算シェーダー
- インポートするモデルのパスにcharacterがあり、テクスチャの名前にeffectがない=>モバイル用ディフューズシェーダー
- インポートするモデルのパスにcharacterがない=>ライトを使わないシェーダー
- モデルと同じ階層にマテリアルを保存(何もしない場合はMaterialフォルダが作られ、その下に保存されます。)
- パスにcharacterがない場合はアニメーションをインポートしない
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;
}
}
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");
}
}
}
}
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");
}
}
}
}