unity資源texturepack導入和拆圖-plist2sprite


一.plist導出unity sprite圖集

  texturepack有開源的工具可以導出json文件,然后倒入sprite。但是很多游戲使用的是plist打包,比如cocos2d。我們做demo可能需要這些資源來用用。所以有此需求。

  首先是解析plist。自己xml解析是在麻煩,網上找到個,使用c#的XDocument類,解析成自己的plist類型。代碼基本沒變,因為plist的<!DOCTYPE>那行總是解析出錯,所以在外面載入好字符串,然后去掉這一行。

public void LoadText(string text)
{
Clear();
XDocument doc = XDocument.Parse(text);
XElement plist = doc.Element("plist");
XElement dict = plist.Element("dict");

 
         

var dictElements = dict.Elements();
Parse(this, dictElements);
}

  然后讀取數據載入到自己的TPAtlas類里面(本來想通過這個類,直接緩存讀取),然后是寫入到textureImporter.spritesheet里,再AssetDatabase.ImportAsset就OK。這里有個問題,就設置sheet后,要重寫textureType和spriteImportMode后面ImportAsset才有效,不然內存是改了,但是不會保存到meta文件,下次打開就沒了,可能是unity的bug

[MenuItem("Assets/Texture/PLisToSprites(SelectPList)")]
    static void ConvertSprite()
    {
        //EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");
        Object selobj = Selection.activeObject;
        string selectionPath = AssetDatabase.GetAssetPath(Selection.activeObject);
        if (!selectionPath.EndsWith(".plist"))
        {
            EditorUtility.DisplayDialog("Error", "Please select a plist file!", "OK", "");
            return;
        }

        Debug.LogWarning("#PLisToSprites start:" + selectionPath);
        string fileContent = string.Empty;
        using (FileStream file = new FileStream(selectionPath, FileMode.Open))
        {
            byte[] str = new byte[(int)file.Length];
            file.Read(str, 0, str.Length);
            fileContent = GetUTF8String(str);
            Debug.Log(fileContent);
            file.Close();
            file.Dispose();
        }
        //去掉<!DOCTYPE>,不然異常
        int delStart = fileContent.IndexOf("<!DOCTYPE");
        int delEnd = fileContent.IndexOf("\n", delStart);
        fileContent = fileContent.Remove(delStart, delEnd - delStart);
        Debug.Log(fileContent);
        //解析文件
        PList plist = new PList();
        plist.LoadText(fileContent);//Load(selectionPath);
        TPAtlas at = new TPAtlas();
        at.LoadX(plist);

        //重寫meta
        string texPath = Path.GetDirectoryName(selectionPath) + "/" + at.realTextureFileName;
        Texture2D selTex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D;
        Debug.Log("texture:" + texPath);
        Debug.Log("write texture:" + selTex.name+ "  size:"+selTex.texelSize);
        TextureImporter textureImporter = AssetImporter.GetAtPath(texPath) as TextureImporter;
        if (textureImporter.textureType != TextureImporterType.Sprite && textureImporter.textureType != TextureImporterType.Advanced)
        {
            EditorUtility.DisplayDialog("Error", "Texture'type must be sprite or Advanced!", "OK", "");
            return;
        }
        if (textureImporter.spriteImportMode!=SpriteImportMode.Multiple)
        {
            EditorUtility.DisplayDialog("Error", "spriteImportMode must be Multiple!", "OK", "");
            return;
        }
        SpriteMetaData[] sheetMetas = new SpriteMetaData[at.sheets.Count];
        for (int i = 0; i < at.sheets.Count; i++)
        {
            var frameData = at.sheets[i];
            sheetMetas[i].alignment = 0;
            sheetMetas[i].border = new Vector4(0, 0, 0, 0);
            sheetMetas[i].name = frameData.name;
            sheetMetas[i].pivot = new Vector2(0.5f, 0.5f);
            sheetMetas[i].rect = new Rect(frameData.frame.x, at.size.y - frameData.frame.y -frameData.frame.height,
                frameData.frame.width,frameData.frame.height);//這里原點在左下角,y相反
            //Debug.Log("do sprite:" + frameData.name);
        }
        //textureImporter.spriteImportMode = SpriteImportMode.Multiple;
        textureImporter.spritesheet = sheetMetas;

        //save
        textureImporter.textureType = TextureImporterType.Sprite;       //bug?
        textureImporter.spriteImportMode = SpriteImportMode.Multiple;   //不加這兩句會導致無法保存meta
        AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate);

        Debug.LogWarning("#PLisToSprites end:" + texPath);
    }

二.unity sprite圖集拆分小圖

  有些圖是ui用unity的sprite做ui目前不太靠譜,所以我們還是使用ngui等插件自己打圖,所以要拆分。

  還是使用萬能的TextureImporter類,拿到sheet然后,每個sheet寫入到新圖片。

 
         


[MenuItem("Assets/Texture/Output Sprites(SelectTexture)")]
static void OutputSprite()
{
string selectionPath = AssetDatabase.GetAssetPath(Selection.activeObject);
Texture2D selTex = Selection.activeObject as Texture2D;
string rootPath = Path.GetDirectoryName(selectionPath) +"/"+ Selection.activeObject.name;
TextureImporter textureImporter = AssetImporter.GetAtPath(selectionPath) as TextureImporter;
//textureImporter.textureType = TextureImporterType.Advanced;
//textureImporter.isReadable = true;
Object[] selected = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
if (!Directory.Exists(rootPath))
Directory.CreateDirectory(rootPath);
Debug.Log("output dir :" + rootPath);
//foreach (var item in selected)
//{
// Sprite sprite = item as Sprite;
// if (sprite == null)
// return;
// string path = rootPath + "/" + sprite.name + ".png";
// Debug.Log("output :" + path);
// SaveSpriteToPNG(sprite, path);
//}

 
         

foreach (var spmeta in textureImporter.spritesheet)
{
string path = rootPath + "/" + spmeta.name + ".png";
string subDir = Path.GetDirectoryName(path);
if (!Directory.Exists(subDir))
{
Directory.CreateDirectory(subDir);
}
Debug.Log("output :" + path);
SavePriteToPNG_Meta(selTex, spmeta, path);
}
AssetDatabase.Refresh();
}

 
         

static bool SaveSpriteToPNG(Sprite sprite, string outPath)
{
// 創建單獨的紋理
Texture2D tex = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height, sprite.texture.format, false);
tex.SetPixels(sprite.texture.GetPixels((int)sprite.rect.xMin, (int)sprite.rect.yMin,
(int)sprite.rect.width, (int)sprite.rect.height));
tex.Apply();
// 寫入成PNG文件
File.WriteAllBytes(outPath, tex.EncodeToPNG());
return true;
}

 
         

static bool SavePriteToPNG_Meta(Texture2D sourceImg,SpriteMetaData metaData, string outPath)
{
Texture2D myimage = new Texture2D((int)metaData.rect.width, (int)metaData.rect.height, sourceImg.format,false);
Color[] pixs = sourceImg.GetPixels((int)metaData.rect.x, (int)metaData.rect.y,(int)metaData.rect.width, (int)metaData.rect.height);
myimage.SetPixels(pixs);
myimage.Apply();

//AssetDatabase.CreateAsset(myimage, rootPath + "/" + image.name + "/" + metaData.name + ".PNG");
File.WriteAllBytes(outPath, myimage.EncodeToPNG());
return true;
}

 

代碼工程:http://pan.baidu.com/s/1hLqYM

使用注意事項:

plist轉sprite要選中plist文件右擊操作。元圖要改成sprite的multi格式。里面數據名字可能有區別,主要看texture的名字和每個子圖的rect,我兼容了兩種版本,有其他格式自己改代碼吧。還有plist要改成utf8格式,utf8+有時候無效。

拆小圖要選中png圖右擊操作。格式要改成rgba32,不壓縮的,類型advanced ,勾上read/write enable。還有size不能小於元圖大小。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM