Search Unity

Sprites and MaterialPropertyBlocks in editor

Discussion in '2D' started by AlexTemina, Dec 5, 2016.

  1. AlexTemina

    AlexTemina

    Joined:
    Feb 19, 2014
    Posts:
    44
    Hi, I'm having some problems with Material Property Blocks...

    My objects are always sprite renderers, but they have 3 sprites. The shader controls which Texture to show.

    I have a custom editor for sprite renderer that lets you set the 3 sprites. We use different materials for each object, but we decided to use only 1 material and use Material Property Block to change the textures of each object, per renderer. During edit mode it looks it works, I can see the sprites on the scene, but when playing, the material property block gets reset somewhat, as if the sprite renderer was overwriting it, so only the main sprite stays and the other 2 textures are gone.

    The question is:
    once you set a material property block, does it stay like when you set a texture in a material? or do I have to set it everytime I play?

    Is there a way to get what I want to do? Using one material for all objects but set the 3 textures different per object?

    Thanks for the help.

    This the custom editor code:
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. [CanEditMultipleObjects]
    5. [CustomEditor( typeof( SpriteRenderer ) )]
    6. public class TestSpriteRendererEditor : Editor
    7. {
    8.     #region Accessors
    9.     protected bool IsComposer
    10.     {
    11.         get
    12.         {
    13.             Material mat = materialProp.objectReferenceValue as Material;
    14.             return mat && mat.HasProperty( "_WarmTex" ) && mat.HasProperty( "_ColdTex" );
    15.         }
    16.     }
    17.  
    18.     private SpriteRenderer _rend
    19.     {
    20.         get
    21.         {
    22.             return target as SpriteRenderer;
    23.         }
    24.     }
    25.     #endregion Accessors
    26.  
    27.     #region PrivateFields
    28.  
    29.     //Props
    30.     private SerializedProperty materialProp;
    31.    
    32.     private SerializedProperty coldSpriteProp;
    33.     private SerializedProperty colorProp;
    34.     private SerializedProperty sortingLayerProp;
    35.     private SerializedProperty sortingOrderProp;
    36.  
    37.     //sprites are fields taken from textures
    38.     private Sprite _neutral_sprite;
    39.  
    40.     private Sprite _warm_sprite;
    41.     private Sprite _cold_sprite;
    42.  
    43.     //SortingLayer as an enum, is a field
    44.     private UnitySortingLayer _sorting_layer;
    45.  
    46.     private MaterialPropertyBlock _property_block;
    47.  
    48.     #endregion PrivateFields
    49.  
    50.     #region Unity
    51.  
    52.     private void OnEnable( )
    53.     {
    54.         if( _property_block == null )
    55.         {
    56.             _property_block = new MaterialPropertyBlock( );
    57.             _rend.GetPropertyBlock( _property_block );
    58.         }
    59.  
    60.         _SetPropsFromSpriteRenderer( );
    61.         _ApplyModifiedPropertiesToRender( );
    62.     }
    63.  
    64.     public override void OnInspectorGUI( )
    65.     {
    66.         serializedObject.Update( );
    67.  
    68.         //Material. Textures will be applied if material changes
    69.         EditorGUI.BeginChangeCheck( );
    70.  
    71.         EditorGUILayout.PropertyField( materialProp, new GUIContent( "Material" ) );
    72.  
    73.         if( EditorGUI.EndChangeCheck( ) )
    74.         {
    75.             _ApplyMaterialTextures( );
    76.             serializedObject.ApplyModifiedProperties( );
    77.         }
    78.  
    79.         //Rest of the properties
    80.         EditorGUI.BeginChangeCheck( );
    81.  
    82.         EditorGUILayout.Space( );
    83.  
    84.         //Sprites
    85.         string neutral_sprite_name = IsComposer ? "Neutral Sprite" : "Sprite";
    86.         _neutral_sprite = EditorGUILayout.ObjectField( neutral_sprite_name, _neutral_sprite, typeof( Sprite ), true ) as Sprite;
    87.  
    88.         if( IsComposer )
    89.         {
    90.             _warm_sprite = EditorGUILayout.ObjectField( "Warm Sprite", _warm_sprite, typeof( Sprite ), true ) as Sprite;
    91.             _cold_sprite = EditorGUILayout.ObjectField( "Cold Sprite", _cold_sprite, typeof( Sprite ), true ) as Sprite;
    92.         }
    93.  
    94.         if( EditorGUI.EndChangeCheck( ) )
    95.         {
    96.             _ApplyModifiedPropertiesToRender( );
    97.         }
    98.     }
    99.  
    100.     #endregion Unity
    101.  
    102.     #region PrivateMethods
    103.  
    104.     private void _SetPropsFromSpriteRenderer( )
    105.     {
    106.         _ApplyMaterialTextures( );
    107.  
    108.         colorProp = serializedObject.FindProperty( "m_Color" );
    109.  
    110.         //Sorting layer
    111.         sortingLayerProp = serializedObject.FindProperty( "m_SortingLayerID" );
    112.         _sorting_layer = new UnitySortingLayer( );
    113.         _sorting_layer.Set( UnitySortingLayerUtils.GetSortingLayerIndex( sortingLayerProp.intValue ), sortingLayerProp.intValue );
    114.  
    115.         //Sorting Order
    116.         sortingOrderProp = serializedObject.FindProperty( "m_SortingOrder" );
    117.     }
    118.  
    119.     private void _ApplyMaterialTextures( )
    120.     {
    121.         //Material
    122.         materialProp = serializedObject.FindProperty( "m_Materials" ).GetArrayElementAtIndex( 0 );
    123.  
    124.         //Sprites
    125.  
    126.         Texture2D main_tex = _property_block.GetTexture( "_MainTex" ) as Texture2D;
    127.         if( main_tex )
    128.         {
    129.             _neutral_sprite = EditorUtils.GetObjectFromPath<Sprite>( main_tex );
    130.         }
    131.  
    132.         Texture2D warm_tex = _property_block.GetTexture( "_WarmTex" ) as Texture2D;
    133.         if( warm_tex )
    134.         {
    135.             _warm_sprite = EditorUtils.GetObjectFromPath<Sprite>( warm_tex );
    136.         }
    137.  
    138.         Texture2D cold_tex = _property_block.GetTexture( "_ColdTex" ) as Texture2D;
    139.         if( cold_tex )
    140.         {
    141.             _cold_sprite = EditorUtils.GetObjectFromPath<Sprite>( cold_tex );
    142.         }
    143.         else
    144.         {
    145.             Debug.Log( "Cold tex is null" );
    146.         }
    147.     }
    148.  
    149.     private void _ApplyModifiedPropertiesToRender( )
    150.     {
    151.         if( IsComposer )
    152.         {
    153.             _rend.GetPropertyBlock( _property_block );
    154.  
    155.             _SetNeutralTextureInRender( );
    156.             _SetWarmTextureInRender( );
    157.             _setColdTextureInRender( );
    158.  
    159.             _rend.SetPropertyBlock( _property_block );
    160.         }
    161.  
    162.         sortingLayerProp.intValue = _sorting_layer.layerUid;
    163.  
    164.         serializedObject.ApplyModifiedProperties( );
    165.     }
    166.  
    167.     private void _SetTextureInRender( string tex_name_, Sprite sprite_ )
    168.     {
    169.         if( sprite_ && sprite_.texture )
    170.         {
    171.             _property_block.SetTexture( tex_name_, sprite_.texture );
    172.         }
    173.     }
    174.  
    175.     private void _SetNeutralTextureInRender( )
    176.     {
    177.         _SetTextureInRender( "_MainTex", _neutral_sprite );
    178.     }
    179.  
    180.     private void _SetWarmTextureInRender( )
    181.     {
    182.         _SetTextureInRender( "_WarmTex", _warm_sprite );
    183.     }
    184.  
    185.     private void _setColdTextureInRender( )
    186.     {
    187.         _SetTextureInRender( "_ColdTex", _cold_sprite );
    188.     }
    189.  
    190.     #endregion PrivateMethods
    191. }