3Dモデルの色を点滅するスクリプトです。
ダメージを食らったときとかの演出に使ってます。
Start()の中で、Renderer系のコンポーネント(SpriteRendererとかMeshRendererとか)を持つオブジェクトをGetcomponentsInChildren()で取得して、さらにRendererコンポーネントの持っているmaterialをすべて取得。
materialをKeyにして、該当materialの初期カラーをDictionaryに入れてます。
注意点として、materialがカラーのプロパティを持っていないと使えません。持っていないときはマテリアルを新しく作り、カラーのプロパティを持ったシェーダを設定する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//一度にすると時間かかりそうなのでコルーチンを使う //カラーの初期値も必要なのでDictionary型を使う //自分以下のオブジェクトから、カラー付きマテリアルをカラーと一緒にDictionaryにいれる // Dictionary<Material,Color> _materialAndInitialColors; protected virtual IEnumerator/*スタート時に全て取得するならここはvoidでも良い*/ DetectAllRenderer(GameObject target) { _materialAndInitialColors = new Dictionary<Material, Color>(); Renderer[] renderers = target.GetComponentsInChildren<Renderer>(); foreach (Renderer render in renderers)//レンダラーすべてを調べる { foreach (Material material in render.materials)//マテリアルすべてを調査 { if (material.HasProperty("_Color")) { _materialAndInitialColors.Add(material, material.color); break; } } yield return new WaitForEndOfFrame();/*IEnumeratorをvoidにしたらこの行は不要*/ } } |
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; //色を点滅 //カラーを持っているマテリアルと初期値のカラーを辞書型で渡す //初期値のカラーをマテリアルごとに設定しておかないといけないので辞書型を使った public class ImageFlicker { public static IEnumerator Flicker(Dictionary<Material,Color> matAndInitialColors, Color flickerColor, float flickerSpeed, float flickerDuration) { if(matAndInitialColors.Count == 0) { #if UNITY_EDITOR Debug.Log("マテリアルがセットできていない:コルーチンを使っているが数フレームで取得できるはず"); #endif yield break; } float flickerStop = Time.time + flickerDuration; while(Time.time < flickerStop) { foreach(Material mat in matAndInitialColors.Keys) { mat.color = flickerColor; } yield return new WaitForSeconds(flickerSpeed); foreach(KeyValuePair<Material,Color> kvp in matAndInitialColors) { kvp.Key.color = kvp.Value; } yield return new WaitForSeconds(flickerSpeed); } } //オブジェクトをプールする場合,ゲームオブジェクトが破壊されたときに呼び出したほうが良いかも public static void ColorInitialize(Dictionary<Material, Color> matAndInitialColors) { if (matAndInitialColors == null || matAndInitialColors.Count == 0) { #if UNITY_EDITOR Debug.Log("マテリアルがセットできていない:コルーチンを使っているが数フレームで取得できるはず"); #endif return; } foreach (KeyValuePair<Material, Color> kvp in matAndInitialColors) { kvp.Key.color = kvp.Value; } } } |
一つにまとめたスクリプトが↓です。
このcsファイルを使えばそのままコンポーネントとして使えるはずです。試してませんが。
スプライトにも多分使える? 試してませんが。
FlickerModel.cs
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class FlickerModel : MonoBehaviour { [SerializeField,Header("ダメージを受けたときの点滅色")] protected Color flickerColor = Color.red; [SerializeField] protected float flickerDuration = 0.5f, flickerSpeed = 0.1f; protected Dictionary<Material,Color> _materialAndInitialColors; protected virtual void Start() { StartCoroutine(DetectAllRenderer(gameObject); } //使うときはこれを呼び出します public void FlickerModel(){ StartCoroutine( ImageFlicker.Flicker(_materialAndInitialColors, flickerColor, flickerSpeed, flickerDuration)); } //一度にすると時間かかりそうなのでコルーチンを使う //カラーの初期値も必要なのでDictionary型を使う //オブジェクトの持つカラー付きマテリアルをカラーと一緒にいれる protected virtual IEnumerator DetectAllRenderer(GameObject target) { _materialAndInitialColors = new Dictionary<Material, Color>(); Renderer[] renderers = target.GetComponentsInChildren<Renderer>(); foreach (Renderer render in renderers)//レンダラーすべてを調べる { foreach (Material material in render.materials)//マテリアルすべてを調査 { if (material.HasProperty("_Color")) { _materialAndInitialColors.Add(material, material.color); break; } } yield return new WaitForEndOfFrame(); } } } //色を点滅 //初期値のカラーをマテリアルごとに設定しておかないといけないので辞書型を使った public class ImageFlicker { public static IEnumerator Flicker(Dictionary<Material,Color> matAndInitialColors/*マテリアルと初期設定してあるカラー*/, Color flickerColor/*点滅する色*/, float flickerSpeed/*点滅の速さ*/, float flickerDuration/*点滅する時間,秒*/) { if(matAndInitialColors.Count == 0) { #if UNITY_EDITOR Debug.Log("マテリアルがセットできていない:コルーチンを使っているが数フレームで取得できるはず"); #endif yield break; } float flickerStop = Time.time + flickerDuration; while(Time.time < flickerStop) { foreach(Material mat in matAndInitialColors.Keys) { mat.color = flickerColor; } yield return new WaitForSeconds(flickerSpeed); foreach(KeyValuePair<Material,Color> kvp in matAndInitialColors) { kvp.Key.color = kvp.Value; } yield return new WaitForSeconds(flickerSpeed); } } //追記 //オブジェクトをプールする場合、OnDisableとかで呼び出さないと赤色のまま出現することがあります public static void ColorInitialize(Dictionary<Material, Color> matAndInitialColors) { if (matAndInitialColors == null || matAndInitialColors.Count == 0) { #if UNITY_EDITOR Debug.Log("マテリアルがセットできていない:コルーチンを使っているが数フレームで取得できるはず"); #endif return; } foreach (KeyValuePair<Material, Color> kvp in matAndInitialColors) { kvp.Key.color = kvp.Value; } } } |
ImageFlickerは別ファイルにしても大丈夫です。
色んなやり方があると思います。