That’s right. Going through Color[]
to compile color palette data in an inefficient process ideally should be done as pre-processing step (in editor as asset/scene preparation) and saved for easy and fast access while application is running
Click RMB over component in Inspector window and choose "Update Color Data"
to update.
![inspector view][1]
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class PageData : MonoBehaviour
{
[SerializeField] ColorTrio _sharedColors;
[SerializeField] SpriteRenderer[] _spriteRenderers;
[SerializeField] ColorTrio[] _colors;
void Start ()
{
for( int i=0 ; i<_spriteRenderers.Length ; i++ )
{
var spriteRenderer = _spriteRenderers*;*
var color = _colors*;*
Debug.Log( $“{spriteRenderer.name}'s colors: {color}” , spriteRenderer.gameObject );
}
}
[ContextMenu(“Update Color Data”)]
void UpdateColorData ()
{
_spriteRenderers = GetComponentsInChildren( includeInactive:true );
_colors = new ColorTrio[ _spriteRenderers.Length ];
Dictionary<Color,int> shared_palette_unsorted = new Dictionary<Color,int>();
for( int i=0 ; i<_spriteRenderers.Length ; i++ )
{
var spriteRenderer = _spriteRenderers*;*
// compile sorted array of colors (from most to least common one):
Color[] palette;
{
Dictionary<Color,int> palette_unsorted = new Dictionary<Color,int>();//to represent Color and number of pixels of that Color
Sprite sprite = spriteRenderer.sprite;
Rect spriteRect = sprite.rect;
Color[] spritePixels = sprite.texture.GetPixels( (int)spriteRect.x , (int)spriteRect.y , (int)spriteRect.width , (int)spriteRect.height );
foreach( var color in spritePixels )
{
if( color.a!=1 ) continue;// lets skip all transparent and semi-transparent pixels
if( palette_unsorted.ContainsKey(color) )
palette_unsorted++;// another pixel of this color
else
palette_unsorted.Add( color , 1 );// first
}
palette = palette_unsorted
.OrderByDescending( (kv)=>kv.Value )
.Select( (kv)=> kv.Key )
.ToArray();
foreach( var kv in palette_unsorted )
{
Color color = kv.Key;
int count = kv.Value;
if( shared_palette_unsorted.ContainsKey(color) )
shared_palette_unsorted += count;
else
shared_palette_unsorted.Add( color , count );
}
}
// pick colors:
{
ColorTrio trio = new ColorTrio();
trio.primary = palette[0];
trio.secondary = palette.FirstOrDefault( (col)=> col!=trio.primary );// will result in Color(0,0,0,0) if none found
trio.tertiary = palette.FirstOrDefault( (col)=> col!=trio.primary && col!=trio.secondary );// will result in Color(0,0,0,0) if none found
colors = trio;
}_
#if DEBUG
// print debug info
{
var sb = new System.Text.StringBuilder();
foreach( var color in palette ) sb.AppendLine( " color: {color}" );*_</em></em>
<em><em><em><em>Debug.Log( "‘{spriteRenderer.name}’ colors: {_colors.primary}, {_colors.secondary}, {_colors.tertiary}
all colors:
{sb}" , spriteRenderer.gameObject );*
}
#endif
}_
// pick shared colors:
{
Color[] shared_sorted = shared_palette_unsorted
.OrderByDescending( (kv)=>kv.Value )
.Select( (kv)=> kv.Key )
.ToArray();
ColorTrio trio = new ColorTrio();
trio.primary = shared_sorted[0];
trio.secondary = shared_sorted.FirstOrDefault( (col)=> col!=trio.primary );// will result in Color(0,0,0,0) if none found
trio.tertiary = shared_sorted.FirstOrDefault( (col)=> col!=trio.primary && col!=trio.secondary );// will result in Color(0,0,0,0) if none found
_sharedColors = trio;
#if DEBUG
Debug.Log( $“‘{this.name}’ SHARED COLORS: {_sharedColors.primary}, {_sharedColors.secondary}, {_sharedColors.tertiary}” , gameObject );
#endif
}
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty( this );
#endif
}
public ColorTrio GetColorsFor ( SpriteRenderer spriteRenderer )
{
for( int i=0 ; i<_spriteRenderers.Length ; i++ )
{
if( spriteRenderers*==spriteRenderer )
return _colors;*
}
// else not found:
Debug.LogWarning( "'{spriteRenderer.name}' not found among '{this.name}' SpriteRenderers" , spriteRenderer );*_</em></em></em></em></em></em></em>
<em><em><em><em><em><em><em>_*return default(ColorTrio);*_</em></em></em></em></em></em></em>
<em><em><em><em><em><em><em>_*}*_</em></em></em></em></em></em></em>
<em><em><em><em><em><em><em>_*public ColorTrio GetColorsFor ( GameObject go )*_</em></em></em></em></em></em></em>
<em><em><em><em><em><em><em>_*{*_</em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em>*for( int i=0 ; i<_spriteRenderers.Length ; i++ )*</em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em>_*{*_</em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em>if( _spriteRenderers*.gameObject==go )*</em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em><em>return _colors*;*</em></em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em>_*}*_</em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em>_*// else not found:*_</em></em></em></em></em></em></em></em></em>
<em><em><em><em><em><em><em><em><em>_*Debug.LogWarning( “‘{go.name}’ not found among ‘{this.name}’ SpriteRenderers” , go );
return default(ColorTrio);
}_
[System.Serializable]
public struct ColorTrio
{
public Color primary, secondary, tertiary;
public override string ToString () => $“( primary:{primary} , secondary:{secondary} , tertiary:{tertiary} )”;
}
}
_*[1]: https://i.imgur.com/z5EgSeU.jpg*_