工具
TexturePacker使用
)
生成prefab
sprite信息类
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class SpriteAsset : MonoBehaviour
{
/// <summary>
/// 图片资源
/// </summary>
public Texture texSource;
/// <summary>
/// 所有sprite信息 SpriteAssetInfor类为具体的信息类
/// </summary>
public List<SpriteInfo> listSpriteInfor;
//根据sprite名称获取Sprite
public Sprite GetSpriteWithName(string name)
{
for(int i = 0; i < listSpriteInfor.Count;i++)
{
if(listSpriteInfor[i].name.Equals(name))
{
return listSpriteInfor[i].sprite;
}
}
return null;
}
}
[System.Serializable]
public class SpriteInfo
{
/// <summary>
/// ID
/// </summary>
public int ID;
/// <summary>
/// 名称
/// </summary>
public string name;
/// <summary>
/// 精灵
/// </summary>
public Sprite sprite;
}
创建图集prefab
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
public static class CreateSpriteAsset
{
[MenuItem("Assets/Create or Update Sprite Asset")] //,false,10
public static void main()
{
Object target = Selection.activeObject;
Create(target,null);
}
public static void Create(Object target,string filePathWithName)
{
if (target == null || target.GetType() != typeof(Texture2D))
return;
Texture2D sourceTex = target as Texture2D;
//整体路径
if (string.IsNullOrEmpty(filePathWithName))
{
filePathWithName = AssetDatabase.GetAssetPath(sourceTex);
}
//带后缀的文件名
string fileNameWithExtension = Path.GetFileName(filePathWithName);
//不带后缀的文件名
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePathWithName);
//不带文件名的路径
string filePath = filePathWithName.Replace(fileNameWithExtension, "");
string assetPath = filePath + fileNameWithoutExtension + ".prefab";
SpriteAsset spriteAsset = AssetDatabase.LoadAssetAtPath(assetPath, typeof(SpriteAsset)) as SpriteAsset;
if (spriteAsset == null)
{
GameObject prefab = null;
GameObject tempGo = new GameObject(fileNameWithoutExtension);
prefab = PrefabUtility.CreatePrefab(assetPath, tempGo);
spriteAsset = prefab.AddComponent<SpriteAsset>();
GameObject.DestroyImmediate(tempGo);
}
spriteAsset.texSource = sourceTex;
spriteAsset.listSpriteInfor = GetSpritesInfor(sourceTex);
EditorUtility.SetDirty(spriteAsset.gameObject);
AssetDatabase.SaveAssets();
}
public static List<SpriteInfo> GetSpritesInfor(Texture2D tex)
{
List<SpriteInfo> m_sprites = new List<SpriteInfo>();
string filePath = UnityEditor.AssetDatabase.GetAssetPath(tex);
Object[] objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(filePath);
for (int i = 0; i < objects.Length; i++)
{
if (objects[i].GetType() == typeof(Sprite))
{
SpriteInfo temp = new SpriteInfo();
Sprite sprite = objects[i] as Sprite;
temp.ID = i;
temp.name = sprite.name;
temp.sprite = sprite;
m_sprites.Add(temp);
}
}
return m_sprites;
}
}
//部分函数说明
//EditorUtility.SetDirty :这个函数告诉引擎,相关对象所属于的Prefab已经发生了更改。方便,当我们更改了自定义对象的属性的时候,自动更新到所属的Prefab中
运行时切换同一图集里的image
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
public class AtlasImage : MonoBehaviour
{
public SpriteAsset Atlas;
public Image SourceImage;
private string m_catche = string.Empty;
private bool m_catchMakePerfect = false;
// Use this for initialization
void Start ()
{
if (SourceImage == null)
{
SourceImage = GetComponent<Image>();
}
if (!string.IsNullOrEmpty(m_catche))
{
Sprite = m_catche;
m_catche = string.Empty;
}
if (m_catchMakePerfect)
{
MakePixelPerfect();
m_catchMakePerfect = false;
}
}
public void SetAtlas(SpriteAsset atlas)
{
Atlas = atlas;
}
public string Sprite
{
get
{
if (SourceImage!=null)
{
return SourceImage.sprite.name;
}
return string.Empty;
}
set
{
if (SourceImage == null)
{
SourceImage = GetComponent<Image>();
}
if (SourceImage!=null && Atlas!=null)
{
SourceImage.sprite = Atlas.GetSpriteWithName(value);
}
else
{
m_catche = value;
}
}
}
public void MakePixelPerfect()
{
if (SourceImage != null)
{
SourceImage.SetNativeSize();
}
else
{
m_catchMakePerfect = true;
}
}
}
使用示例:
//手动或运行时挂载AtlasImage脚本
m_titleIcon = m_title.GetComponent(“AtalsImage”);
//传入需要设置的sprite名称
m_titleIcon.Sprite = SpriteName;
优化替换Image方案
思路:
- 运行时加载图集资源(可以打成bundle并将路径维护在一份表里)
- 将加载过的图集保存在缓存里
示例代码:
--lua代码,因项目为lua,故lua实现,c#思路一样。
--[[说明,方便动态设定图集内的sprite
@param:image 控件上的 Image
@param:assetId 图集 respath id
@param:iconName 图集中sprite名字
@param:keepNativeSize 使用图片原大小
]]
def.static("userdata","number","string","boolean").SetOverrideSpriteFromAtlas = function (image,assetId,iconName,keepNativeSize)
assert(image ~= nil,"image should not nil")
assert(iconName ~= nil,"需要指定一个spriteName");
if image.overrideSprite and image.overrideSprite.name == iconName then
--print("Set a same sprite when SetOverrideSpriteFromAtlas!!!")
return
end
local function setSprite(_image,asset,name)
local sprite = asset:GetSpriteWithName(name)
_image.overrideSprite = sprite
if keepNativeSize then
_image:SetNativeSize()
end
end
--先在缓存里查找
local spriteAsset = _G.PreloadSpriteAsset[assetId]
if spriteAsset == nil then
--维护一份资源id表,根据资源id获取资源路径
local path = GetResPathById(assetId)
-- 异步加载图集
GameUtil.AsyncLoad(path,function (obj)
local spriteAsset = obj:GetComponent("SpriteAsset")
assert(spriteAsset ~= nil,"spriteAsset should not nil")
_G.PreloadSpriteAsset[assetId] = spriteAsset
setSprite(image,spriteAsset,iconName)
end)
else
setSprite(image,spriteAsset,iconName)
end
end
//c#实现部分思路伪代码
public static List<SpriteAsset> spriteAssets = new List<SpriteAsset>();
public static void SetOverrideSpriteFromAtlas(Image image,SpriteAsset spriteAsset,string iconName,bool keepNativeSize)
{
if(image.overrideSprite and image.overrideSprite.name == iconName)
{
//print("Set a same sprite when SetOverrideSpriteFromAtlas!!!")
return;
}
if(!spriteAssets.Contains(spriteAsset))
{
//根据资源id或者路径加载图集,并保存到缓存
}
Sprite sprite = spriteAsset.GetSpriteWithName(name);
image.overrideSprite = sprite;
if(keepNativeSize)
{
image:SetNativeSize();
}
}
优化思路
- TexturePacker提供命令行打图集方式,可写命令行导出.tpsheet和.png文件。