C# 如果像素是透明的,不要将其设置为纹理2D

C# 如果像素是透明的,不要将其设置为纹理2D,c#,unity3d,C#,Unity3d,所以我试着制作一个完整的雪碧,它分为两部分,一部分是头部,另一部分是身体 我在inspector中设置了两个纹理,并通过代码创建了另一个纹理,这是我想要的。 我所做的是获取我想要的身体像素并设置它们。这里没问题,当我想把头放进去的时候,问题就来了,因为它是128x128,我不用全部,所以它会选择这一个的透明像素,然后删除实体像素 using System.Collections; using System.Collections.Generic; using UnityEngine; publ

所以我试着制作一个完整的雪碧,它分为两部分,一部分是头部,另一部分是身体

我在inspector中设置了两个纹理,并通过代码创建了另一个纹理,这是我想要的。 我所做的是获取我想要的身体像素并设置它们。这里没问题,当我想把头放进去的时候,问题就来了,因为它是128x128,我不用全部,所以它会选择这一个的透明像素,然后删除实体像素

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MSSGameHandler : MonoBehaviour
{

[SerializeField] private Texture2D baseTexture;
[SerializeField] private Texture2D headTexture;
[SerializeField] private Texture2D bodyTexture;
[SerializeField] private Material guestMaterial;
private Sprite mysprite;

private void Awake()
{
    Texture2D texture = new Texture2D(512, 512, TextureFormat.RGBA32, true);

    Color[] spriteSheetBasePixels = baseTexture.GetPixels(0, 0, 512, 512);
    texture.SetPixels(0, 0, 512, 512, spriteSheetBasePixels);



    Color[] bodyPixels = bodyTexture.GetPixels(0, 0, 128, 128);
    texture.SetPixels(0, 256, 128, 128, bodyPixels);

    Color[] headPixels = headTexture.GetPixels(0, 0, 128, 128);
    texture.SetPixels(0, 294, 128, 128, headPixels);

    texture.Apply();

    guestMaterial.mainTexture = texture;
    //mysprite = Sprite.Create(texture)

}

}

SetPixels
中,覆盖所有现有像素

您应该“手动”循环它们并检查alpha值

var finalpixels = new Color[512 * 512];

var spriteSheetBasePixels = baseTexture.GetPixels(0, 0, 512, 512);
for(var i = 0; i < finalpixels.Length; i++)
{
    finalpixels[i] = spriteSheetBasePixels [i];
}

var bodyPixels = bodyTexture.GetPixels(0, 0, 128, 128);
for(var x = 0; x < 128; x++)
{ 
    for(var y = 256; y < 256 + 128; y++)
    {
        finalpixels[x + y * 512] = bodyPixels[x + (y - 256) * 128];
    }
}

var headPixels = headTexture.GetPixels(0, 0, 128, 128);
for(var x = 0; x < 128; x++)
{
    for(var y = 294; y < 294 + 128; y++)
    {
        var pixel = headPixels[x + (y - 256) * 128];

        if(Mathf.Approximately(pixel.a, 0)) continue;

        finalpixels[x + y * 512] = pixel;
    }
}

texture.SetPixels(finalPixels);
var finalpixels=新颜色[512*512];
var spriteSheetBasePixels=baseTexture.GetPixels(0,0,512,512);
对于(变量i=0;i

身体意象

头像

结果(在原始图像中)


对不起,我的绘画技巧:D

将这两种纹理合并在一起会在应用程序开始时增加不必要的加载时间,但每帧的好处很小。而且,如果决定移动头部和身体的相对位置(例如,作为空闲动画的一部分),则必须进行性能测试以重新创建显示新相对位置的新纹理

因此,取而代之的是,将头部和身体放在不同的对象中,然后使用a将它们排序在一起

示例字符:

排序组之前

将排序组应用于根对象(
chomboboy
,在本例中):

排序组后(顶部呈现的字符在其
排序组中的层
顺序较高):

(图片取自Unity文档)

对排序组进行排序

Unity使用排序层的概念,允许您将精灵划分为组以获得覆盖优先级排序层较低的排序组被排序层较高的排序组覆盖。

有时,同一排序层中的两个或多个对象可能重叠(例如,一个侧滚游戏中的两个玩家角色,如下例所示)。“层中的顺序”属性可用于将一致的优先级应用于同一层中的排序组与“排序层”一样,先渲染较低的数字,然后再渲染具有较高层数的排序组。有关编辑排序层的详细信息,请参阅标签和层文档。

排序组的子体根据最近或下一个排序组的其他子体进行排序(取决于排序是按距离还是按层顺序)换句话说,排序组仅为其子代创建本地排序空间。这允许使用排序层和排序层对组内的每个渲染器进行排序,但只能在本地对包含的排序组进行排序。


嗯,在
SetPixels
中,你覆盖了所有现有的像素是的…是的,我想知道如何不设置它的trasnparent,我不知道是否已经存在一个方法或其他什么。你将两个纹理组合成一个而不是只使用两个渲染器是有特殊原因的吗?如果你真的需要创建一个全新的纹理,使用一个计算着色器组合两个纹理可能会得到你想要的结果。@Ruzihm是的,因为如果我在两个不同的对象中有它,头部会在身体后面,如果我改变了头部可以在树前面的顺序,那么层中的排序顺序,原来的现在只会在小组里行动,对吗?世界上的团队呢?@Alexxjaz是的,头部和身体的
精灵渲染器将在顺序后一个渲染(顺序由它们在层中的
顺序决定)然后,整个组将根据
排序组的
分层顺序在树的前面或后面排序
,非常感谢您的帮助!嘿,我在计算指数时发现了错误;)现在,提名这个答案为stackoverflow上的最佳艺术品应该是可行的