如果本文章对您有帮助,请不要吝啬您的赞
前言
之前在没使用Lua框架的时候一直都在使用NGUI, Atlas图集其实用的很爽。
但是改到UGUI之后呢没有Atlas这个东西了,挺不习惯的。遂根据NGUI的形式写了这个工具
原理
我简单的说下UGUI动态更改sprite的方法,一般情况是在Reasouce里面加载图片然后转成sprite,然后改变Image的sprite,但是这样做其实很麻烦。而且结合TP打包图集也不是很好做,因为这样你需要LoadAll。
如果把TP的png放在Resouce里面也会产生*2的包大小,他会重新打包两边。
我的做法
相当于自己建立一个Atlas的工具类,然后用所有图片都是保存在prefab上,把prefab放在Resouce下。这样打包出来的体积也会小很多。
接下来就开始上代码咯
为了方便,我把从png转化为prefab的过程写了个插件。
ps:TP打包出来png图片必须是sprite格式。
using UnityEngine;
using System.Collections;
using UnityEditor;
public class UIAtalsEditor
{
[MenuItem("Assets/Create/创建当前选中图集")]
public static void CreateAtlasPrefab()
{
if(Selection.activeObject !=null)
{
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
TextureImporter importer =AssetImporter.GetAtPath(path) as TextureImporter;
if(importer != null && importer.textureType ==TextureImporterType.Sprite &&importer.spriteImportMode == SpriteImportMode.Multiple)
{
UIAtals atlas = ScriptableObject.CreateInstance<UIAtals>();
object[] objs = AssetDatabase.LoadAllAssetsAtPath(path);
atlas.spriteLists.Clear();
foreach (object o in objs)
{
if(o.GetType() == typeof(Texture2D))
{
atlas.mainText = o as Texture2D;
}
else if(o.GetType() == typeof (Sprite))
{
atlas.spriteLists.Add(o as Sprite);
}
}
AssetDatabase.CreateAsset(atlas, path.Replace(".png", "_Atlas.prefab"));
AssetDatabase.Refresh();
}
else
{
Debug.Log("当前选中的不是图集图片");
}
}
}
}
``` C#
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(UIAtals))]
public class UIAtlasInspector : Editor
{
public override void OnInspectorGUI()
{
UIAtals atlas = target as UIAtals;
atlas.mainText = EditorGUILayout.ObjectField("MainTextture", atlas.mainText, typeof(Texture2D)) as Texture2D;
if (GUILayout.Button("刷新数据"))
{
if (atlas.mainText == null)
{
string path = EditorUtility.OpenFilePanel("选着一张图集", Application.dataPath, "png");
if (!string.IsNullOrEmpty(path))
{
atlas.mainText = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D;
}
}
if (atlas.mainText != null)
{
string path = AssetDatabase.GetAssetPath(atlas.mainText);
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer != null && importer.textureType == TextureImporterType.Sprite
&& importer.spriteImportMode == SpriteImportMode.Multiple)
{
Object[] objs = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(atlas.mainText));
atlas.spriteLists.Clear();
foreach (Object o in objs)
{
if (o.GetType() == typeof(Texture2D))
{
atlas.mainText = o as Texture2D;
}
else if (o.GetType() == typeof(Sprite))
{
atlas.spriteLists.Add(o as Sprite);
}
}
}
else
{
atlas.mainText = null;
}
}
}
if (atlas.spriteLists.Count > 0)
{
foreach (Sprite s in atlas.spriteLists)
{
EditorGUILayout.ObjectField(s.name, s, typeof(Sprite));
}
}
}
}
以上两个类都是编辑器类, 需要放在Editor特殊文件夹里面,放进去之后,对着打包好的tppng图片邮件,create就有创建当前这个选项了。
会在当前目录下 生成一个atlas,放入resouce.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class UIAtals : ScriptableObject
{
public Texture2D mainText;
public List<Sprite> spriteLists = new List<Sprite>();
/// <summary>
/// 根据图片名称获取sprite
/// </summary>
/// <param name="spritename">图片名称</param>
/// <returns></returns>
public Sprite GetSprite(string spritename)
{
return spriteLists.Find((Sprite s) => { return s.name == spritename; });
}
/// <summary>
/// 设置Image的Sprite
/// </summary>
/// <param name="im">Image</param>
/// <param name="spritename">图片名称</param>
public void SetSprite(ref Image im, string spritename)
{
if(im == null)
{
return;
}
Sprite sp = GetSprite(spritename);
if(sp !=null)
{
im.overrideSprite = sp;
}
else
{
Debug.Log("图集没有对应的图片:"+ spritename);
}
}
}
这是一个图集管理类,其中有获取sprite 和 设置sprite的方法。
测试类如下:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class DrawNote
{
public static Dictionary<string, UIAtals> atlasmanage = new Dictionary<string, UIAtals>();
/// <summary>
/// 设置滑动条宽度
/// </summary>
/// <param name="obj">滑动条</param>
/// <param name="posx">x坐标</param>
/// <param name="posy">y坐标</param>
public static void SetContent(GameObject obj,int posx,int posy)
{
obj.gameObject.GetComponent<RectTransform>().sizeDelta =new Vector2(posx,posy);
}
/// <summary>
/// 动态生成图片
/// </summary>
/// <param name="spitename">图片名称</param>
/// <returns></returns>
public static Image LoadImage(Sprite sprite,Transform parenttrs,int posx ,int posy,float offsetX)
{
GameObject go = new GameObject(sprite.name);
go.layer = LayerMask.NameToLayer("UI");
go.transform.parent = parenttrs;
Image image = go.AddComponent<Image>();
image.sprite = sprite;
image.rectTransform.pivot = new Vector2(0, 0);
image.rectTransform.localPosition = new Vector3(posx+ offsetX, posy, 0);
image.SetNativeSize();
return image;
}
/// <summary>
/// 加载图集
/// </summary>
/// <param name="spriteName">图集名称</param>
public static UIAtals LoadAtals(string atlasName)
{
UIAtals atlas = Resources.Load<UIAtals>(atlasName);
atlasmanage.Add(atlasName, atlas);
return atlas;
}
/// <summary>
/// 生成note图片
/// </summary>
/// <param name="atlasName">Altas名称</param>
/// <param name="spriteName">精灵名称</param>
/// <param name="parenttrs">父节点</param>
/// <param name="posx">x坐标</param>
/// <param name="posy">y坐标</param>
public static Image CreateImage(string atlasName,string spriteName,Transform parenttrs,string posx ,string posy ,float offsetX)
{
int iposx = int.Parse(posx);
int iposy = int.Parse(posy);
UIAtals atlas;
if(!atlasmanage.ContainsKey(atlasName))
{
atlas=LoadAtals(atlasName);
}
else
{
atlas = atlasmanage[atlasName];
}
Image img=LoadImage(atlas.GetSprite(spriteName),parenttrs, iposx,iposy, offsetX);
atlas.SetSprite(ref img, spriteName);
img.raycastTarget = false;
return img;
}
/// <summary>
/// 小节线图片生成
/// </summary>
/// <param name="atlasName">图集名称</param>
/// <param name="spriteName">图片名称</param>
/// <param name="parenttrs">父节点</param>
/// <param name="posx">坐标</param>
/// <param name="offsetX">偏移量</param>
/// <param name="wight">图片宽度</param>
/// <param name="height">图片高度</param>
/// <returns></returns>
public static Image CreateMeasure(string atlasName, string spriteName,Transform parenttrs, string posx, float offsetX, float wight, float height)
{
int iposx = int.Parse(posx);
UIAtals atlas;
if (!atlasmanage.ContainsKey(atlasName))
{
atlas = LoadAtals(atlasName);
}
else
{
atlas = atlasmanage[atlasName];
}
Sprite sprite = atlas.GetSprite(spriteName);
GameObject go = new GameObject(sprite.name);
go.layer = LayerMask.NameToLayer("UI");
go.transform.parent = parenttrs;
Image image = go.AddComponent<Image>();
image.sprite = sprite;
image.rectTransform.pivot = new Vector2(0, 0);
image.rectTransform.localPosition = new Vector3(iposx + offsetX, 0, 0);
image.SetNativeSize();
image.rectTransform.sizeDelta = new Vector2(wight, height);
return image;
}
}
大家可以根据我这个测试类改,我是因为需要导入lua所以写的繁琐了一点,不过相信代码还是很清楚的。