Hello Everyone,
im trying to generate a Material with a packed Atlast Texture.
for this i’m collecting the Data (Textures, Meshes…) and processing them within a GameObjectConversionSystem. but calling any Editor Api that creates an Asset throws an Error.
namespace CWBR.Editor.Conversion
{
[UpdateInGroup(typeof(GameObjectBeforeConversionGroup))]
public class SceneRenderingAssetsCollectorSystem : GameObjectConversionSystem
{
public int MaxOriginalTextureResolution = 512;
RenderingAssetsHolder renderingAssetsHolder;
private List<Material> materialsWithoutTexture;
protected override void OnStartRunning()
{
base.OnStartRunning();
//Generate the RenderingAssetsHolder if not existing
var (renderingAssetsHolders,_) = ScriptableObjectUtils.GetAllInstances<RenderingAssetsHolder>(new string[] {FoldersPaths.RenderingAssetsHoldersPath});
/* // Not Working so im creating the Scriptable Object Manually from the Editor
bool rahExists = false;
var activeSceneName = SceneManager.GetActiveScene().name;
Debug.Log($"activeSceneName : {activeSceneName}");
for (var i = 0; i < renderingAssetsHolders.Length; i++)
{
if (renderingAssetsHolders[i].SceneName == activeSceneName)
{
rahExists = true;
renderingAssetsHolder = renderingAssetsHolders[i];
}
}
if (rahExists == false)
{
//FIXME: The Editor is not Able to Create the ScriptableObject Asset
renderingAssetsHolder = ScriptableObject.CreateInstance<RenderingAssetsHolder>();
renderingAssetsHolder = ScriptableObjectUtils.CreateScriptableObject<RenderingAssetsHolder>(FoldersPaths.RenderingAssetsHoldersPath+"\\"+ renderingAssetsHolders.Length + "_Asset_Holder.asset");
Debug.Log("New RenderingAssetsHolder Created for this Scene");
}
else
{
Debug.Log("RenderingAssetsHolder already Existing for this Scene");
}*/
if(renderingAssetsHolders.Length > 0)
{
renderingAssetsHolder = renderingAssetsHolders[0];
Debug.Log($"Rendering Assets Holder Found : {renderingAssetsHolder.SceneName}");
}
materialsWithoutTexture = new List<Material>();
}
/// <summary>
/// Pack All Collected Texture to a single Atlas
/// </summary>
public void PackTextures(ref RenderingAssetsHolder rah)
{
var path = FoldersPaths.RenderingAssetsHoldersPath + $"\\{rah.SceneName}_Atlas.png";
if (rah.AtlasUvs.Length == rah.OriginalTextures.Count)
{
if (rah.TextureAtlas == null)
{
Debug.Log("Texture Atlas Null!");
rah.TextureAtlas = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
EditorUtility.SetDirty(rah);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
Debug.Log("Texture Packing Skipped");
return;
}
var atlas = new Texture2D(rah.AtlasResolution, rah.AtlasResolution);
var tempTexturesArray = new Texture2D[rah.OriginalTextures.Count];
for (var i = 0; i < rah.OriginalTextures.Count; i++)
tempTexturesArray[i] = duplicateTexture(rah.OriginalTextures[i]);
rah.AtlasUvs = atlas.PackTextures(tempTexturesArray, 2, rah.AtlasResolution);
//AssetDatabase.CreateAsset(atlas, path); // Not working as workaround i use the line above
File.WriteAllBytes(path, atlas.EncodeToPNG());
// AssetDatabase.ImportAsset(path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
rah.TextureAtlas = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
rah.GeneratedMaterial.SetTexture("_MainTex", rah.TextureAtlas);
EditorUtility.SetDirty(rah);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
Texture2D duplicateTexture(Texture2D source)
{
RenderTexture renderTex = RenderTexture.GetTemporary(
source.width,
source.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear);
Graphics.Blit(source, renderTex);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = renderTex;
Texture2D readableText = new Texture2D(source.width, source.height);
readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
readableText.Apply();
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(renderTex);
return readableText;
}
//[Button("Create Material")]
public void CreateMaterial(ref RenderingAssetsHolder rah)
{
rah.GeneratedMaterial = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
var materialPath = FoldersPaths.RenderingAssetsHoldersPath + $"\\{rah.SceneName}_Material.mat";
AssetDatabase.CreateAsset(rah.GeneratedMaterial, materialPath);
// Print the path of the created asset
Debug.Log(AssetDatabase.GetAssetPath(rah.GeneratedMaterial));
}
protected override void OnUpdate()
{
materialsWithoutTexture.Clear();
Entities.ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) =>
{
var sharedMaterial = meshRenderer.sharedMaterial;
if (sharedMaterial == null)
{
Debug.Log($"this GameObject '{meshRenderer.name}' do not Contain a sharedMaterial");
return;
}
if (sharedMaterial.shader.name != "Universal Render Pipeline/Simple Lit")
return;
var mainTexture = meshRenderer.sharedMaterial.GetTexture("_MainTex") as Texture2D;
if (null == mainTexture)
{
if (materialsWithoutTexture.Contains(sharedMaterial))
return;
Debug.Log($"The material Linked to this GameObject '{meshRenderer.name}' do not Contain a '_MainTex'");
materialsWithoutTexture.Add(sharedMaterial);
// Debug.Log("Path Added!");
return;
}
/*
if (mainTexture == null)
{
Debug.Log($"The material Linked to this GameObject '{meshRenderer.name}' do not Contain a mainTexture");
return;
}
*/
if (!renderingAssetsHolder.OriginalTextures.Contains(mainTexture))
{
if (mainTexture.width > MaxOriginalTextureResolution)
{
Debug.Log($"the material {sharedMaterial.name} with Texture '{mainTexture.name}' has a resolution is higher of {mainTexture.width} which is higher than the threshhold {MaxOriginalTextureResolution} ");
}
renderingAssetsHolder.OriginalTextures.Add(mainTexture);
}
var sharedMesh = meshFilter.sharedMesh;
if (sharedMesh == null)
{
Debug.Log($"this GameObject '{meshRenderer.name}' do not Contain a sharedMesh");
return;
}
if (!renderingAssetsHolder.SharedMeshes.Contains(sharedMesh))
{
renderingAssetsHolder.SharedMeshes.Add(sharedMesh);
}
});
// CreateMaterial(ref renderingAssetsHolder);
PackTextures(ref renderingAssetsHolder);
EditorUtility.SetDirty(renderingAssetsHolder);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
materialsWithoutTexture.Clear();
Debug.Log("SceneRenderingAssetsCollectorSystem end!");
}
}
}
Error:
UnityException: Creating asset at path Assets\Scripts\ScriptableObjects\Instances\Map5_Material.mat failed.