如果场景中存在很多物体,电脑会变得卡顿甚至程序崩溃,合并为一张图可以节约性能。
using UnityEditor;
using System.IO;
public Transform[] Boundarys; //合并图像的边界,用来选取左下点和右上点,确定合并图像的大小
public List<Transform> My_Units; //单元图的集合,必须位于边界内,没有图片也行,主要功能为记录位置
public Prefab_Unit; //单元图的模板,用以提取texture进行复制,(运行功能前,需要将其sprite,在属性面板改为可读,否则将报错)
public SpriteRenderer My_CombineSprite; //合并图像的载体
//*********************************************************************************** Combine
[ContextMenu("TextureCombine")]
void Combine()
{
//***************** 确定长宽
float width, height;
Vector2 v_ld = new Vector2(100, 100);
Vector2 v_ru = new Vector2(0, 0);
for (int i = 0; i < Boundarys.Length; i++)
{
if (Boundarys[i].transform.position.x < v_ld.x)
v_ld.x = Boundarys[i].transform.position.x;
if (Boundarys[i].transform.position.x > v_ru.x)
v_ru.x = Boundarys[i].transform.position.x;
if (Boundarys[i].transform.position.y < v_ld.y)
v_ld.y = Boundarys[i].transform.position.y;
if (Boundarys[i].transform.position.y > v_ru.y)
v_ru.y = Boundarys[i].transform.position.y;
}
width = v_ru.x - v_ld.x;
height = v_ru.y - v_ld.y;
//***************** 拼合
int pix_width = (int)(width * 1000); // 其中的1000为场景中实际距离和像素的比例
int pix_height = (int)(height * 1000);
Texture2D oTex = Prefab_Unit.GetComponent<SpriteRenderer>().sprite.texture;
Texture2D targetTex = new Texture2D(pix_width, pix_height);
for (int i = 0; i < targetTex.width; i++)
{
for (int j = 0; j < targetTex.height; j++)
{
targetTex.SetPixel(i, j, new Color(0f, 0f, 0f, 0f));
}
}
Vector2 v_rela;
Vector2Int v_pix_rela;
Color color;
for (int i = 0; i < My_Units.Count; i++)
{
v_rela = (Vector2)My_Units[i].transform.position - v_ld;
v_pix_rela = new Vector2Int((int)(v_rela.x * 1000 - oTex.width / 2), (int)(v_rela.y * 1000 - oTex.height / 2));
for (int q = 0; q < oTex.width; q++)
{
for (int p = 0; p < oTex.height; p++)
{
color = Superpose_Color(targetTex.GetPixel(q + v_pix_rela.x, p + v_pix_rela.y), oTex.GetPixel(q, p));
targetTex.SetPixel(q + v_pix_rela.x, p + v_pix_rela.y, color);
}
}
}
targetTex.Apply();
string path = "Assets/out.png";
File.WriteAllBytes(path, targetTex.EncodeToPNG());
AssetDatabase.Refresh();
TextureImporter ti = AssetImporter.GetAtPath(path) as TextureImporter;
ti.spritePixelsPerUnit = 1000; // 根据实际情况,调整资源的像素比例
AssetDatabase.ImportAsset(path);
//**************** 安放位置
My_CombineSprite.sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);
My_CombineSprite.transform.position = (v_ld + v_ru) / 2;
}
// 返回叠加的像素颜色,但该方法很烂,只能勉强处理完全透明和完全不透明的图片
Color Superpose_Color(Color c01,Color c02) //c01为前置像素,c02为后置像素
{
float show_rata = (1f - c01.a) * c02.a;
Color c03;
if (show_rata > 0.9f)
c03 = c02;
else
c03 = new Color(c01.r + c02.r * show_rata, c01.g + c02.g * show_rata, c01.b + c02.b * show_rata, show_rata + c01.a);
return c03;
}
小结:
1.这些都是在网上查找资料,拼合在一起的代码,效果还算可以,但叠加像素颜色的方法是自己瞎写的,只能勉强处理完全透明和完全不透明的像素颜色,可能存在问题,最好找一找另外的方法。
2.单元图的叠加,也会存在先后和遮挡的问题,所以还需另外添加单元图排序的代码。
3.代码中的数值1000可改变,若运行上述功能时太卡而导致崩溃,可将其调低,比如100
4.该代码,只能合并同种图片,即模板的单元图,若要合并多个不同的图片,需适当修改代码,但原理不变,依旧是提取texture,然后写入新texture。