- Home /
Get Asset Preview (3.5)
So we are working on finishing up our editors for our game and haven't upgraded to unity 4. I know there is a function EditorUtility.GetAssetPreview(). Here is my problem:
Below is the code I am trying to reference. Essentially, I am reading in a list of game objects from various file paths. I am loading each object in, and trying to render a preview texture of it (for a custom editor). However, I am getting very weird, inconsistent results. Essentially, I have ~80 prefabs in the paths I am trying to load. Of those 80, either 7 or 13 textures are actually created. I can't find anything in their documentation limiting the amount of textures that can be created, I am only loading and performing the render ONCE. If I close the window and reopen, triggering the reload, I get a different set of prefabs.
Essentially on first load I get 7 textures. On second load I get 13. And it switches back and forth if I continue this. I have debugged the code to ensure I am getting valid game objects, but it isn't being rendered. All the prefabs are more or less exactly the same (minus some script values) so models and such shouldn't be the issue (as they are the 'same'). It's like the GetAssetPreview doesn't have the time or resources to create the textures but that doesn't make sense as it's not asynchronous.
Any help or insight you can provide, I would appreciate. Thank you for your time.
/// <summary>
/// Reads the in all objects from the paths.
/// </summary>
/// <param name='paths'>
/// The paths to read objects from.
/// </param>
void ReadInAllObjects(string[] paths)
{
// just testing...
int totalObj = 0;
int totalLoaded = 0;
int haveImages = 0;
// iterate over all paths desired to be loaded
foreach(string path in paths)
{
// read in all files from the given path
string[] allFilesInPath = Directory.GetFiles(path, "*.prefab");
totalObj += allFilesInPath.Length;
foreach(string filePath in allFilesInPath)
{
//string newpath = filePath.Replace(@"\", @"/"); // not needed, but makes file path cleaner
GameObject obj = (GameObject)AssetDatabase.LoadAssetAtPath(newpath, typeof(GameObject));
if(obj is GameObject)
{
++totalLoaded;
Texture2D texture = EditorUtility.GetAssetPreview(obj);
if(texture != null)
{
++haveImages;
gameObjects.Add(new ObjectTexturePair(texture, obj));
}
}
}
}
Debug.Log("Total obj: " + totalObj);
Debug.Log("Total loaded: " + totalLoaded);
Debug.Log("Have images: " + haveImages);
} // eo ReadInAllObjects
/// <summary>
/// Object texture pair used to link a texture and an object so
/// it's easier to manage and not lose or duplicate information elsewhere.
/// </summary>
public class ObjectTexturePair
{
public Texture2D texture;
public GameObject gameObject;
public ObjectTexturePair(Texture2D texture, GameObject gameObject)
{
this.texture = texture;
this.gameObject = gameObject;
}
} // End ObjectTexturePair
Answer by startassets · Mar 12, 2017 at 07:46 PM
@jaised I've just finished my own preview asset, maybe it will be useful for you: https://forum.unity3d.com/threads/powerful-preview.460157/
UPD: I made some test stuff for Unity 3.5 asset previewing, but it needs extra work, to make it behave just like native Unity preview, or Powerful Preview, do. Next code implements only scene object drawing, nothing else.
What you need to do: instatiate objects, hide them from inspector and implement some hiding from main camera mechanism, so scene won't be messed up ( like in Powerful Preview ). If you need some interactive preview - implement input events handling.
So the clue is to implement it from the scratch without standard GetAssetPreview, it allows you don't create many render textures, so you decrease amount of memory you need. The only thing that you need is make object visible and invisible every time you switch between your prefabs.
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor( typeof( PreviewAsset ) )]
public class PreviewAssetEditor : Editor
{
public override void OnPreviewGUI( Rect r, GUIStyle background )
{
//Here you can handle icon drawing, when width and height are 40 pixels, but
//I don't need that.
if( r.width < Screen.width - 100.0f )
{
return;
}
mPreviewCamera.aspect = mRenderTexture.width / mRenderTexture.height;
mPreviewCamera.Render();
GUI.DrawTexture(
new Rect(
r.x + r.width / 2 - mRenderTexture.width / 2,
r.y + r.height / 2 - mRenderTexture.height / 2,
mRenderTexture.width,
mRenderTexture.height
), mRenderTexture );
}
public override bool HasPreviewGUI()
{
return true;
}
public void OnEnable()
{
GameObject camObject = new GameObject("PreviewCamera");
mPreviewCamera = camObject.AddComponent( "Camera" ) as Camera;
mPreviewCamera.transform.position = new Vector3( 0, 0, -3 );
//Size should be power of 2.
mRenderTexture = new RenderTexture( 512, 512, 24, RenderTextureFormat.ARGB32 );
mRenderTexture.Create();
mPreviewCamera.targetTexture = mRenderTexture;
}
public void OnDisable()
{
GameObject.DestroyImmediate( mPreviewCamera.gameObject );
mRenderTexture.Release();
}
public override void OnInspectorGUI()
{
Repaint();
}
private Camera mPreviewCamera;
private RenderTexture mRenderTexture;
}
It doesn't work in 3.5 as it wasn't submitted with that version of Unity. However, it looks like you used a similar approach to what I did. I essentially created my own 'preview' and ditched Unity's. Even up until 5.5 I have had issues with it when trying various things (particularly preview textures). I have long since moved away from this, but glad to see there is a somewhat maintained alternative. Thanks @startassets
You make me go and download Unity 3.5, if I get smth I will tell you.
You can download v3.5 from https://unity3d.com/get-unity/download/archive