只需在“项目”窗口中创建一个名为“编辑器”的文件夹,然后在其中添加此脚本即可。然后,打开“窗口-单色纹理检测器”并点击“刷新”。
你可能会问,为什么我需要这个?某些纹理可以是 1024x1024 或更大,并且仅包含单一颜色(Asset Store 上的许多艺术资源将此类纹理用于其材质的金属/发射/镜面/等通道)。为什么你想要一个 1k 纹理?您可以简单地将其最大尺寸设置为 32,在显着优化纹理尺寸的同时,它也会产生相同的效果。该插件可用于快速找到此类纹理。
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
public class SingleColorTextureDetector : EditorWindow, IHasCustomMenu
{
[Serializable]
private class SaveData
{
public List paths = new List();
}
private const string LOW_RES_DUMMY_TEXTURE_PATH = "Assets/low_dummyy_texturee.png";
private const string HIGH_RES_DUMMY_TEXTURE_PATH = "Assets/high_dummyy_texturee.png";
private const string SAVE_FILE_PATH = "Library/SingleColorAssetDetector.json";
private const float BUTTON_DRAG_THRESHOLD_SQR = 600f;
private readonly MethodInfo instanceIDFromGUID = typeof( AssetDatabase ).GetMethod( "GetInstanceIDFromGUID", BindingFlags.NonPublic | BindingFlags.Static );
private List results = new List(); // This is not readonly so that it can be serialized
private double lastClickTime;
private string lastClickedPath;
private readonly GUIContent buttonGUIContent = new GUIContent();
private Vector2 buttonPressPosition;
private Vector2 scrollPos;
[MenuItem( "Window/Single Color Texture Detector" )]
private static void Init()
{
SingleColorTextureDetector window = GetWindow();
window.titleContent = new GUIContent( "Solid Textures" );
window.minSize = new Vector2( 200f, 150f );
window.Show();
}
private void Awake()
{
LoadSession( null );
}
// Show additional options in the window's context menu
public void AddItemsToMenu( GenericMenu menu )
{
if( results.Count > 0 )
menu.AddItem( new GUIContent( "Save To Clipboard" ), false, () => GUIUtility.systemCopyBuffer = JsonUtility.ToJson( new SaveData() { paths = results }, true ) );
else
menu.AddDisabledItem( new GUIContent( "Save To Clipboard" ) );
if( string.IsNullOrEmpty( GUIUtility.systemCopyBuffer ) )
menu.AddDisabledItem( new GUIContent( "Load From Clipboard" ) );
else
{
menu.AddItem( new GUIContent( "Load From Clipboard" ), false, () =>
{
string json = GUIUtility.systemCopyBuffer;
LoadSession( json );
SaveSession( json ); // If load succeeds, overwrite the saved session
} );
}
}
private void OnGUI()
{
Event ev = Event.current;
scrollPos = GUILayout.BeginScrollView( scrollPos );
// Calculate single color Textures
if( GUILayout.Button( "Refresh" ) )
{
try
{
double startTime = EditorApplication.timeSinceStartup;
CalculateSingleColorTextures();
SaveSession( null );
Debug.Log( "Refreshed in " + ( EditorApplication.timeSinceStartup - startTime ) + " seconds." );
}
catch( Exception e )
{
Debug.LogException( e );
}
finally
{
EditorUtility.ClearProgressBar();
if( File.Exists( LOW_RES_DUMMY_TEXTURE_PATH ) )
AssetDatabase.DeleteAsset( LOW_RES_DUMMY_TEXTURE_PATH );
if( File.Exists( HIGH_RES_DUMMY_TEXTURE_PATH ) )
AssetDatabase.DeleteAsset( HIGH_RES_DUMMY_TEXTURE_PATH );
}
GUIUtility.ExitGUI();
}
// Draw found results
if( results.Count > 0 )
{
EditorGUILayout.HelpBox( "- Double click a path to select the Texture asset\n- Right/middle click a path to hide it from the list", MessageType.Info );
for( int i = 0; i < results.Count; i++ )
{
Rect rect = EditorGUILayout.GetControlRect( false, EditorGUIUtility.singleLineHeight + 2f );
rect.xMin += 3f;
rect.xMax -= 3f;
Rect iconRect = new Rect( rect.x, rect.y, rect.height, rect.height );
rect.xMin += iconRect.width + 2f;
Texture icon = AssetDatabase.GetCachedIcon( results[i] );
if( icon )
EditorGUI.DrawTextureTransparent( iconRect, icon );
// Buttons must support 1) click and 2) drag & drop. The most reliable way is to simulate GUI.Button from scratch
buttonGUIContent.text = results[i];
int buttonControlID = GUIUtility.GetControlID( FocusType.Passive );
switch( ev.GetTypeForControl( buttonControlID ) )
{
case EventType.MouseDown:
if( rect.Contains( ev.mousePosition ) )
{
GUIUtility.hotControl = buttonControlID;
buttonPressPosition = ev.mousePosition;
}
break;
case EventType.MouseDrag:
if( GUIUtility.hotControl == buttonControlID && ev.button == 0 && ( ev.mousePosition - buttonPressPosition ).sqrMagnitude >= BUTTON_DRAG_THRESHOLD_SQR )
{
GUIUtility.hotControl = 0;
Object asset = AssetDatabase.LoadMainAssetAtPath( results[i] );
if( asset )
{
// Credit: https://forum.unity.com/threads/editor-draganddrop-bug-system-needs-to-be-initialized-by-unity.219342/#post-1464056
DragAndDrop.PrepareStartDrag();
DragAndDrop.objectReferences = new Object[] { asset };
DragAndDrop.StartDrag( "DuplicateAssetDetector" );
}
ev.Use();
}
break;
case EventType.MouseUp:
if( GUIUtility.hotControl == buttonControlID )
{
GUIUtility.hotControl = 0;
if( rect.Contains( ev.mousePosition ) )
{
if( ev.button == 0 && File.Exists( results[i] ) )
{
// Ping clicked Texture
double clickTime = EditorApplication.timeSinceStartup;
if( clickTime - lastClickTime < 0.5f && lastClickedPath == results[i] )
{
if( !ev.control && !ev.command && !ev.shift )
Selection.objects = new Object[] { AssetDatabase.LoadMainAssetAtPath( results[i] ) };
else
{
// While holding CTRL, either add clicked asset to current selection or remove it from current selection
Object asset = AssetDatabase.LoadMainAssetAtPath( results[i] );
List