如何缩放Sprite并后续使用(如另存为PNG)
问题解答
关于Sprite缩放的问题
首先明确:Unity的Sprite类没有scale属性,你贴的代码里sprite.scale = new Vector3(1,8,1);是错误写法,无法运行。
Transform的缩放仅修改渲染时的显示大小,不会改变Sprite对应的原始纹理像素。如果要真正修改Sprite的像素数据(生成缩放后的新纹理/Sprite),完全不需要依赖Transform,直接对Texture2D做像素级缩放处理即可。
你原来的代码思路有误——直接复制原纹理像素到新纹理,根本没有执行缩放逻辑,最终输出的还是原尺寸图片。要实现像素级缩放,需要对纹理进行重采样,推荐两种实用方式:
方式1:使用RenderTexture+Graphics.Blit缩放(高效)
// 加载原始纹理 Texture2D originalTex = new Texture2D(2, 2); originalTex.LoadImage(File.ReadAllBytes(Path.Combine(Application.dataPath + "/Animation/raw/", "test.png"))); // 计算缩放后的目标尺寸(示例为Y轴放大8倍) int targetWidth = originalTex.width; int targetHeight = originalTex.height * 8; // 创建临时RenderTexture作为缩放载体 RenderTexture rt = RenderTexture.GetTemporary(targetWidth, targetHeight); rt.filterMode = FilterMode.Bilinear; // 缩放采样模式,可按需选Bilinear/Point // 将原始纹理渲染到缩放后的RenderTexture Graphics.Blit(originalTex, rt); // 从RenderTexture读取像素生成新纹理 RenderTexture.active = rt; Texture2D scaledTex = new Texture2D(targetWidth, targetHeight); scaledTex.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0); scaledTex.Apply(); // 释放资源 RenderTexture.active = null; RenderTexture.ReleaseTemporary(rt); // 生成缩放后的Sprite Sprite scaledSprite = Sprite.Create(scaledTex, new Rect(0,0,targetWidth,targetHeight), Vector2.one*0.5f); // 保存为PNG文件 File.WriteAllBytes(Path.Combine(Application.dataPath, "/Animation/test_scaled.png"), scaledTex.EncodeToPNG());
方式2:手动重采样像素(适合自定义逻辑)
如果需要更精细的采样控制,可以手动计算每个目标像素对应的原纹理位置:
Texture2D originalTex = new Texture2D(2,2); originalTex.LoadImage(File.ReadAllBytes(Path.Combine(Application.dataPath + "/Animation/raw/", "test.png"))); int targetWidth = originalTex.width; int targetHeight = originalTex.height *8; Texture2D scaledTex = new Texture2D(targetWidth, targetHeight); for(int y=0; y<targetHeight; y++){ // 计算当前目标Y对应的原纹理Y坐标 float originalY = (float)y / 8f; for(int x=0; x<targetWidth; x++){ Color color = originalTex.GetPixelBilinear((float)x/targetWidth, originalY/originalTex.height); scaledTex.SetPixel(x, y, color); } } scaledTex.Apply(); // 后续生成Sprite、保存的代码同方式1
关于Sprite合并的问题
用texture.SetPixel(x,y,color)是可行的,但效率极低,不适合纹理尺寸较大或合并多个Sprite的场景。更高效的做法是:
- 创建足够大的目标
Texture2D,尺寸能容纳所有要合并的Sprite; - 对每个Sprite,获取其对应的像素数组(需对应Sprite的rect区域);
- 计算该Sprite在目标纹理中的位置,用
SetPixels一次性将整个像素块复制到对应区域; - 所有Sprite处理完成后调用
Apply()保存修改,最后导出为PNG。
示例代码:
// 假设已有待合并的Sprite列表List<Sprite> spritesToMerge // 计算目标纹理总尺寸(示例为横向排列,可按需调整布局逻辑) int totalWidth = spritesToMerge.Sum(s => (int)s.rect.width); int maxHeight = spritesToMerge.Max(s => (int)s.rect.height); Texture2D mergedTex = new Texture2D(totalWidth, maxHeight); int currentX = 0; foreach(Sprite sprite in spritesToMerge){ int spriteWidth = (int)sprite.rect.width; int spriteHeight = (int)sprite.rect.height; // 获取Sprite对应的像素数组 Color[] pixels = sprite.texture.GetPixels((int)sprite.rect.x, (int)sprite.rect.y, spriteWidth, spriteHeight); // 将像素块复制到目标纹理的对应位置 mergedTex.SetPixels(currentX, 0, spriteWidth, spriteHeight, pixels); currentX += spriteWidth; } mergedTex.Apply(); // 保存合并后的纹理 File.WriteAllBytes(Path.Combine(Application.dataPath, "/Animation/merged.png"), mergedTex.EncodeToPNG());
内容的提问来源于stack exchange,提问作者Virus
相关产品推荐
相关产品推荐

