mirror of
https://github.com/maxartz15/MA_TextureAtlasser.git
synced 2025-07-07 16:56:08 +02:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
696ef848e0 | |||
521cb34541 | |||
d8c59e86ca | |||
e894fcf797 | |||
0dfa466d78 | |||
78f3daa145 |
@ -1,21 +1 @@
|
||||
# MA_TextureAtlasser
|
||||
Texture atlas creator for Unity
|
||||
|
||||
[]()
|
||||
|
||||
You can combine textures and/or remap the UV’s for the 3D models.
|
||||
By having full control over the size and position of the textures that are being placed in the atlas you will never stand for surprises when exporting. This will cost some more time than auto-generating your texture atlases but you know whats going on and which models/textures are getting priority. The tool can also be used to make 2D sprite sheets.
|
||||
|
||||
- Combine textures/sprites.
|
||||
- Automatically adjusts the UV's of the assigned meshes to match the new texture atlas.
|
||||
- Exports meshes as OBJ.
|
||||
- Exports texture atlas as PNG.
|
||||
- Exports texture atlas as a (sliced) sprite sheet.
|
||||
|
||||
[Example video](https://youtu.be/PBRKlopkZP0)
|
||||
|
||||
Download the UnityPackage here: https://github.com/maxartz15/MA_TextureAtlasser/releases
|
||||
|
||||
[]()
|
||||
|
||||
For more information: https://maxartz15.com/ma-textureatlasser/
|
||||
README: https://github.com/maxartz15/MA_TextureAtlasser/blob/master/README.md
|
||||
|
@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using MA_Texture;
|
||||
using System.Collections.Generic;
|
||||
@ -67,3 +68,4 @@ namespace MA_TextureAtlasserPro
|
||||
SpriteSliced
|
||||
}
|
||||
}
|
||||
#endif
|
@ -8,8 +8,6 @@ using MA_Texture;
|
||||
|
||||
namespace MA_TextureAtlasserPro
|
||||
{
|
||||
|
||||
|
||||
public static class MA_TextureAtlasserProUtils
|
||||
{
|
||||
public const string TEXTURE_ATLASSER_PATH = "Assets/MA_ToolBox/MA_TextureAtlasserPro/";
|
||||
@ -26,7 +24,7 @@ namespace MA_TextureAtlasserPro
|
||||
{
|
||||
MA_TextureAtlasserProSettings _settings = ScriptableObject.CreateInstance<MA_TextureAtlasserProSettings>();
|
||||
|
||||
if(_settings != null)
|
||||
if (_settings != null)
|
||||
{
|
||||
CreateFolder(SETTINGS_ASSET_PATH);
|
||||
AssetDatabase.CreateAsset(_settings, SETTINGS_ASSET_PATH + "MA_TextureAtlasserProSettings.asset");
|
||||
@ -92,7 +90,7 @@ namespace MA_TextureAtlasserPro
|
||||
{
|
||||
MA_TextureAtlasserProAtlas _atlas = ScriptableObject.CreateInstance<MA_TextureAtlasserProAtlas>();
|
||||
|
||||
if(_atlas != null)
|
||||
if (_atlas != null)
|
||||
{
|
||||
_atlas.CreateAtlas(name, size);
|
||||
MA_CheckTextureAtlas(_atlas);
|
||||
@ -115,22 +113,22 @@ namespace MA_TextureAtlasserPro
|
||||
MA_TextureAtlasserProAtlas _atlas = null;
|
||||
string absPath = EditorUtility.OpenFilePanel("Select Texture Atlas", LOAD_ASSET_PATH, "");
|
||||
|
||||
if(absPath.StartsWith(Application.dataPath))
|
||||
if (absPath.StartsWith(Application.dataPath))
|
||||
{
|
||||
string relPath = absPath.Substring(Application.dataPath.Length - "Assets".Length);
|
||||
_atlas = AssetDatabase.LoadAssetAtPath(relPath, typeof(MA_TextureAtlasserProAtlas)) as MA_TextureAtlasserProAtlas;
|
||||
|
||||
MA_CheckTextureAtlas(_atlas);
|
||||
|
||||
if(_atlas)
|
||||
if (_atlas)
|
||||
{
|
||||
EditorPrefs.SetString("AtlasPath", null);
|
||||
}
|
||||
}
|
||||
|
||||
if(_atlas != null)
|
||||
if (_atlas != null)
|
||||
{
|
||||
if(_atlas.selectedTextureQuad != null)
|
||||
if (_atlas.selectedTextureQuad != null)
|
||||
{
|
||||
_atlas.selectedTextureQuad.isSelected = false;
|
||||
}
|
||||
@ -142,7 +140,7 @@ namespace MA_TextureAtlasserPro
|
||||
|
||||
public static void MA_CheckTextureAtlas(MA_TextureAtlasserProAtlas atlas)
|
||||
{
|
||||
if(atlas.textureGroupRegistration == null)
|
||||
if (atlas.textureGroupRegistration == null)
|
||||
{
|
||||
atlas.textureGroupRegistration = new List<MA_TextureGroupRegistration>();
|
||||
|
||||
@ -154,7 +152,7 @@ namespace MA_TextureAtlasserPro
|
||||
atlas.textureGroupRegistration.Add(groupRegistration);
|
||||
}
|
||||
|
||||
if(atlas.textureQuads == null)
|
||||
if (atlas.textureQuads == null)
|
||||
{
|
||||
atlas.textureQuads = new List<MA_TextureAtlasserProQuad>();
|
||||
}
|
||||
@ -163,14 +161,14 @@ namespace MA_TextureAtlasserPro
|
||||
bool _sameCount = true;
|
||||
foreach (MA_TextureAtlasserProQuad q in atlas.textureQuads)
|
||||
{
|
||||
if(q.textureGroups.Count != atlas.textureGroupRegistration.Count)
|
||||
if (q.textureGroups.Count != atlas.textureGroupRegistration.Count)
|
||||
{
|
||||
_sameCount = false;
|
||||
Debug.LogWarning("TextureAtlasser: " + q.name + " doesn't have the right amount of texture groups!");
|
||||
}
|
||||
}
|
||||
|
||||
if(_sameCount)
|
||||
if (_sameCount)
|
||||
{
|
||||
foreach (MA_TextureAtlasserProQuad q in atlas.textureQuads)
|
||||
{
|
||||
@ -178,7 +176,7 @@ namespace MA_TextureAtlasserPro
|
||||
{
|
||||
for (int j = 0; j < atlas.textureGroupRegistration.Count; j++)
|
||||
{
|
||||
if(atlas.textureQuads[i].textureGroups[j].name != atlas.textureGroupRegistration[j].name)
|
||||
if (atlas.textureQuads[i].textureGroups[j].name != atlas.textureGroupRegistration[j].name)
|
||||
{
|
||||
Debug.LogWarning("TextureAtlasser: " + q.name + " doesn't have the right texture group name!");
|
||||
}
|
||||
@ -188,7 +186,7 @@ namespace MA_TextureAtlasserPro
|
||||
}
|
||||
}
|
||||
|
||||
if(atlas.exportSettings == null)
|
||||
if (atlas.exportSettings == null)
|
||||
{
|
||||
atlas.exportSettings = LoadExportSettings();
|
||||
}
|
||||
@ -196,10 +194,10 @@ namespace MA_TextureAtlasserPro
|
||||
|
||||
public static MA_TextureAtlasserProQuad CreateTextureQuad(MA_TextureAtlasserProAtlas atlas, string name, Rect rect, bool focus = true)
|
||||
{
|
||||
if(atlas != null)
|
||||
if (atlas != null)
|
||||
{
|
||||
//Create new list if we haven't one already
|
||||
if(atlas.textureQuads == null)
|
||||
if (atlas.textureQuads == null)
|
||||
{
|
||||
atlas.textureQuads = new List<MA_TextureAtlasserProQuad>();
|
||||
}
|
||||
@ -208,7 +206,7 @@ namespace MA_TextureAtlasserPro
|
||||
MA_TextureAtlasserProQuad _quad = ScriptableObject.CreateInstance<MA_TextureAtlasserProQuad>();
|
||||
|
||||
//Add quad to asset
|
||||
if(_quad != null)
|
||||
if (_quad != null)
|
||||
{
|
||||
//Set quad settings
|
||||
_quad.name = name;
|
||||
@ -222,7 +220,7 @@ namespace MA_TextureAtlasserPro
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
if(focus)
|
||||
if (focus)
|
||||
{
|
||||
atlas.selectedTextureQuad = atlas.textureQuads[atlas.textureQuads.Count - 1];
|
||||
}
|
||||
@ -244,7 +242,7 @@ namespace MA_TextureAtlasserPro
|
||||
|
||||
public static void RemoveTextureQuad(MA_TextureAtlasserProAtlas atlas, bool focus = true)
|
||||
{
|
||||
if(atlas != null && atlas.selectedTextureQuad != null)
|
||||
if (atlas != null && atlas.selectedTextureQuad != null)
|
||||
{
|
||||
int _index = atlas.textureQuads.IndexOf(atlas.selectedTextureQuad);
|
||||
|
||||
@ -263,7 +261,7 @@ namespace MA_TextureAtlasserPro
|
||||
|
||||
public static void DuplicateTextureQuad(MA_TextureAtlasserProAtlas atlas, bool focus = true, bool copyData = false, string namePrefix = "new ")
|
||||
{
|
||||
if(atlas != null && atlas.selectedTextureQuad != null)
|
||||
if (atlas != null && atlas.selectedTextureQuad != null)
|
||||
{
|
||||
MA_TextureAtlasserProQuad q = CreateTextureQuad(atlas, namePrefix + atlas.selectedTextureQuad.name, atlas.selectedTextureQuad.rect, false);
|
||||
|
||||
@ -281,7 +279,7 @@ namespace MA_TextureAtlasserPro
|
||||
}
|
||||
}
|
||||
|
||||
if(focus)
|
||||
if (focus)
|
||||
{
|
||||
atlas.selectedTextureQuad = q;
|
||||
}
|
||||
@ -293,7 +291,7 @@ namespace MA_TextureAtlasserPro
|
||||
|
||||
public static void SetTextureGroups(MA_TextureAtlasserProAtlas atlas, MA_TextureAtlasserProQuad quad)
|
||||
{
|
||||
if(quad.textureGroups == null)
|
||||
if (quad.textureGroups == null)
|
||||
{
|
||||
quad.textureGroups = new List<MA_TextureGroup>();
|
||||
}
|
||||
@ -339,7 +337,7 @@ namespace MA_TextureAtlasserPro
|
||||
|
||||
public static void CloseWindow(MA_TextureAtlasserProWindow curWindow)
|
||||
{
|
||||
if(curWindow == null)
|
||||
if (curWindow == null)
|
||||
{
|
||||
Debug.LogError("Closing window Failed: curWindow == null");
|
||||
}
|
||||
@ -391,7 +389,7 @@ namespace MA_TextureAtlasserPro
|
||||
#region Export
|
||||
public static string[] ExportAtlasModels(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string material = null, string savePath = EXPORT_ASSET_PATH)
|
||||
{
|
||||
switch(modelExportSettings.modelFormat)
|
||||
switch (modelExportSettings.modelFormat)
|
||||
{
|
||||
case ModelFormat.None:
|
||||
break;
|
||||
@ -457,13 +455,14 @@ namespace MA_TextureAtlasserPro
|
||||
newMesh = MA_MeshUtils.MA_DuplicateMesh(quad.meshes[m]);
|
||||
//Remap UV's
|
||||
newMesh = MA_MeshUtils.MA_UVReMap(newMesh, atlas.textureAtlasSize, quad.guiRect, modelExportSettings.uvChannel, modelExportSettings.uvFlipY, modelExportSettings.uvWrap);
|
||||
//Save it
|
||||
//Set name
|
||||
string meshName = string.IsNullOrEmpty(quad.name) ? "" : quad.name + "-";
|
||||
meshName += quad.meshes[m].name;
|
||||
int n = m + 1;
|
||||
meshName += "_" + n.ToString("#000");
|
||||
|
||||
string asset = MA_MeshUtils.MA_SaveMeshPrefab(newMesh, meshName, savePath, material: material);
|
||||
newMesh.name = meshName;
|
||||
//Save it
|
||||
string asset = MA_MeshUtils.MA_SaveMeshPrefab(newMesh, meshName, savePath, materialPath: material);
|
||||
assetPaths.Add(asset);
|
||||
}
|
||||
}
|
||||
@ -676,7 +675,7 @@ namespace MA_TextureAtlasserPro
|
||||
name = atlas.name
|
||||
};
|
||||
|
||||
if(textures != null)
|
||||
if (textures != null)
|
||||
{
|
||||
for (int i = 0; i < (int)Mathf.Min(materialExportSettings.shaderPropertyNames.Count, textures.Length); i++)
|
||||
{
|
||||
|
@ -17,58 +17,69 @@ namespace MA_Mesh
|
||||
{
|
||||
public static class MA_MeshUtils
|
||||
{
|
||||
public static string MA_SaveMeshAsset(Mesh mesh, string meshName, string savePath)
|
||||
public static string MA_SaveMeshAsset(Mesh mesh, string savePath)
|
||||
{
|
||||
Mesh newMesh = mesh;
|
||||
|
||||
if(meshName == "")
|
||||
if (string.IsNullOrEmpty(mesh.name))
|
||||
{
|
||||
newMesh.name = mesh.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
newMesh.name = meshName;
|
||||
mesh.name = UnityEngine.Random.Range(11111, 99999).ToString();
|
||||
}
|
||||
|
||||
string assetPath = savePath + newMesh.name + ".asset";
|
||||
string assetPath = savePath + mesh.name + ".asset";
|
||||
|
||||
AssetDatabase.CreateAsset(newMesh, assetPath);
|
||||
AssetDatabase.CreateAsset(mesh, assetPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
return assetPath;
|
||||
}
|
||||
|
||||
public static string MA_SaveMeshPrefab(Mesh mesh, string meshName, string savePath, string material)
|
||||
public static string MA_SaveMeshPrefab(Mesh mesh, string prefabName, string savePath, string materialPath)
|
||||
{
|
||||
string assetPath = "";
|
||||
string assetPath = null;
|
||||
|
||||
if (meshName == "")
|
||||
{
|
||||
meshName = mesh.name;
|
||||
}
|
||||
string meshAssetPath = MA_SaveMeshAsset(mesh, savePath);
|
||||
Mesh meshAsset = AssetDatabase.LoadAssetAtPath<Mesh>(meshAssetPath);
|
||||
|
||||
string meshPath = MA_SaveMeshAsset(mesh, meshName, savePath);
|
||||
Mesh curMesh = AssetDatabase.LoadAssetAtPath<Mesh>(meshPath);
|
||||
|
||||
if (curMesh != null)
|
||||
if (meshAsset != null)
|
||||
{
|
||||
GameObject gameObject = new GameObject
|
||||
{
|
||||
name = meshName
|
||||
name = prefabName
|
||||
};
|
||||
|
||||
gameObject.AddComponent<MeshFilter>().mesh = curMesh;
|
||||
gameObject.AddComponent<MeshFilter>().mesh = meshAsset;
|
||||
gameObject.AddComponent<MeshRenderer>();
|
||||
|
||||
Material curMaterial = AssetDatabase.LoadAssetAtPath<Material>(material);
|
||||
Material curMaterial = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
|
||||
if (curMaterial != null)
|
||||
{
|
||||
gameObject.GetComponent<MeshRenderer>().material = curMaterial;
|
||||
}
|
||||
|
||||
assetPath = savePath + meshName + ".prefab";
|
||||
if (string.IsNullOrEmpty(prefabName))
|
||||
{
|
||||
prefabName = UnityEngine.Random.Range(11111, 99999).ToString();
|
||||
}
|
||||
|
||||
assetPath = savePath + prefabName + ".prefab";
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|
||||
PrefabUtility.SaveAsPrefabAsset(gameObject, assetPath);
|
||||
|
||||
#else
|
||||
|
||||
GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
if (go != null)
|
||||
{
|
||||
PrefabUtility.ReplacePrefab(gameObject, go, ReplacePrefabOptions.ReplaceNameBased);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrefabUtility.CreatePrefab(assetPath, gameObject, ReplacePrefabOptions.ReplaceNameBased);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
UnityEngine.GameObject.DestroyImmediate(gameObject);
|
||||
}
|
||||
|
||||
@ -189,7 +200,7 @@ namespace MA_Mesh
|
||||
|
||||
sb.Append("g ").Append(mesh.name).Append("\n");
|
||||
|
||||
foreach(Vector3 v in mesh.vertices)
|
||||
foreach (Vector3 v in mesh.vertices)
|
||||
{
|
||||
//This is sort of ugly - inverting x-component since we're in
|
||||
//a different coordinate system than "everyone" is "used to".
|
||||
@ -198,19 +209,19 @@ namespace MA_Mesh
|
||||
|
||||
sb.Append("\n");
|
||||
|
||||
foreach(Vector3 v in mesh.normals)
|
||||
foreach (Vector3 v in mesh.normals)
|
||||
{
|
||||
sb.Append(string.Format("vn {0} {1} {2}\n", -v.x, v.y, v.z));
|
||||
}
|
||||
|
||||
sb.Append("\n");
|
||||
|
||||
foreach(Vector3 v in mesh.uv)
|
||||
foreach (Vector3 v in mesh.uv)
|
||||
{
|
||||
sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
|
||||
}
|
||||
|
||||
for (int m = 0 ; m < mesh.subMeshCount; m++)
|
||||
for (int m = 0; m < mesh.subMeshCount; m++)
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append("usemtl ").Append(material.name + m).Append("\n");
|
||||
@ -226,7 +237,7 @@ namespace MA_Mesh
|
||||
for (int i = 0; i < triangles.Length; i += 3)
|
||||
{
|
||||
//Because we inverted the x-component, we also needed to alter the triangle winding.
|
||||
sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i]+ 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i +2 ] + 1 + uvOffset));
|
||||
sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace MA_Texture
|
||||
RenderTexture.active = tmp;
|
||||
|
||||
// Create a new readable Texture2D to copy the pixels to it
|
||||
Texture2D myTexture2D = new Texture2D(texture.width, texture.width);
|
||||
Texture2D myTexture2D = new Texture2D(texture.width, texture.height);
|
||||
|
||||
// Copy the pixels from the RenderTexture to the new Texture
|
||||
myTexture2D.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
|
||||
@ -161,17 +161,20 @@ namespace MA_Texture
|
||||
{
|
||||
Color[] newColors = new Color[newWidth * newHeight];
|
||||
|
||||
float ratioX = ((float)curWidth) / newWidth;
|
||||
float ratioY = ((float)curHeight) / newHeight;
|
||||
float ratioX = 1.0f / ((float)newWidth / (curWidth - 1));
|
||||
float ratioY = 1.0f / ((float)newHeight / (curHeight - 1));
|
||||
|
||||
for (int y = 0; y < newHeight; y++)
|
||||
{
|
||||
var thisY = Mathf.RoundToInt((ratioY * y) * curWidth);
|
||||
int yFloor = Mathf.FloorToInt(y * ratioY);
|
||||
var y1 = (yFloor + 1) * curWidth;
|
||||
var yw = y * newWidth;
|
||||
|
||||
for (int x = 0; x < newWidth; x++)
|
||||
{
|
||||
newColors[yw + x] = curColors[Mathf.RoundToInt(thisY + ratioX * x)];
|
||||
int xFloor = Mathf.FloorToInt(x * ratioX);
|
||||
|
||||
newColors[yw + x] = curColors[Mathf.RoundToInt(y1 + xFloor)];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"com.unity.package-manager-ui": "2.1.2",
|
||||
"com.unity.2d.sprite": "1.0.0",
|
||||
"com.unity.ext.nunit": "1.0.0",
|
||||
"com.unity.test-framework": "1.1.9",
|
||||
"com.unity.ugui": "1.0.0",
|
||||
"com.unity.modules.ai": "1.0.0",
|
||||
"com.unity.modules.androidjni": "1.0.0",
|
||||
"com.unity.modules.animation": "1.0.0",
|
||||
"com.unity.modules.assetbundle": "1.0.0",
|
||||
"com.unity.modules.audio": "1.0.0",
|
||||
|
@ -3,7 +3,7 @@
|
||||
--- !u!159 &1
|
||||
EditorSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 7
|
||||
serializedVersion: 9
|
||||
m_ExternalVersionControlSupport: Hidden Meta Files
|
||||
m_SerializationMode: 2
|
||||
m_LineEndingsForNewScripts: 2
|
||||
@ -16,10 +16,20 @@ EditorSettings:
|
||||
m_EtcTextureFastCompressor: 1
|
||||
m_EtcTextureNormalCompressor: 2
|
||||
m_EtcTextureBestCompressor: 4
|
||||
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp
|
||||
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref
|
||||
m_ProjectGenerationRootNamespace:
|
||||
m_CollabEditorSettings:
|
||||
inProgressEnabled: 1
|
||||
m_EnableTextureStreamingInEditMode: 1
|
||||
m_EnableTextureStreamingInPlayMode: 1
|
||||
m_AsyncShaderCompilation: 1
|
||||
m_EnterPlayModeOptionsEnabled: 0
|
||||
m_EnterPlayModeOptions: 3
|
||||
m_ShowLightmapResolutionOverlay: 1
|
||||
m_UseLegacyProbeSampleCount: 1
|
||||
m_AssetPipelineMode: 1
|
||||
m_CacheServerMode: 0
|
||||
m_CacheServerEndpoint:
|
||||
m_CacheServerNamespacePrefix: default
|
||||
m_CacheServerEnableDownload: 1
|
||||
m_CacheServerEnableUpload: 1
|
||||
|
@ -1,2 +1,2 @@
|
||||
m_EditorVersion: 2019.1.10f1
|
||||
m_EditorVersionWithRevision: 2019.1.10f1 (f007ed779b7a)
|
||||
m_EditorVersion: 2019.3.0f6
|
||||
m_EditorVersionWithRevision: 2019.3.0f6 (27ab2135bccf)
|
||||
|
35
README.md
35
README.md
@ -1,21 +1,28 @@
|
||||
# MA_TextureAtlasser
|
||||
Texture atlas creator for Unity
|
||||
|
||||
[]()
|
||||
|
||||
You can combine textures and/or remap the UV’s for the 3D models.
|
||||
By having full control over the size and position of the textures that are being placed in the atlas you will never stand for surprises when exporting. This will cost some more time than auto-generating your texture atlases but you know whats going on and which models/textures are getting priority. The tool can also be used to make 2D sprite sheets.
|
||||
|
||||
# MA_TextureAtlasser
|
||||
Texture atlas creator tool for Unity. <br> This tool is made to combine textures and/or remap the UV’s for 3D models. The tool can also be used to make 2D sprite sheets. The visual editor gives you the ability to set and prioritize the sizes and positions in the texture atlas/sprite sheet.
|
||||
- Combine textures/sprites.
|
||||
- Automatically adjusts the UV's of the assigned meshes to match the new texture atlas.
|
||||
- Exports meshes as OBJ.
|
||||
- Exports texture atlas as PNG.
|
||||
- Exports texture atlas as a (sliced) sprite sheet.
|
||||
|
||||
[Example video](https://youtu.be/PBRKlopkZP0)
|
||||
|
||||
Download the UnityPackage here: https://github.com/maxartz15/MA_TextureAtlasser/releases
|
||||
|
||||
### Download unitypackage
|
||||
https://github.com/maxartz15/MA_TextureAtlasser/releases <br>
|
||||
[]()
|
||||
|
||||
For more information: https://maxartz15.com/ma-textureatlasser/
|
||||
### Tested Unity versions
|
||||
[]() []() []()
|
||||
|
||||
## Export options
|
||||
### Meshes
|
||||
- UnityMesh (with prefab setup)
|
||||
- OBJ
|
||||
- Replace orginal (this will replace the orginal model, make sure to backup before doing this!)
|
||||
### Textures
|
||||
- PNG
|
||||
- PNG (sliced) sprite sheet
|
||||
### Materials
|
||||
- Material (with assigned textures and selected shader)
|
||||
|
||||
## Resources
|
||||
[Youtube video](https://youtu.be/PBRKlopkZP0) <br>
|
||||
[Website](https://maxartz15.com/ma-textureatlasser/)
|
||||
|
Reference in New Issue
Block a user