【问题标题】:Dont set pixels into Texture2D if they are transprant如果像素是透明的,则不要将它们设置为 Texture2D
【发布时间】:2019-09-14 01:52:08
【问题描述】:

所以我试图制作一个完整的精灵,它分为两部分,一个是头部,另一个是身体。

我在检查器中设置了 2 个纹理,并通过我想要的代码创建了另一个纹理。 我所做的是获取我想要的身体像素并设置它们。这里没问题,当我想放头部时问题就来了,因为它是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 中你会覆盖 all 现有像素是​​的 ...
  • 是的,我想知道如果它是透明的,如何不设置,我不知道是否已经存在方法或什么
  • 您将两个纹理组合成一个而不是仅使用两个渲染器是否有特殊原因?如果您真的需要创建一个全新的纹理,使用计算着色器组合这两个纹理可能会得到您想要的结果。
  • @Ruzihm 是的,因为如果我将它放在 2 个不同的物体中,头部会放在身体后面,如果我改变顺序,头部可以放在树和那些东西前面

标签: c# unity3d


【解决方案1】:

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);

身体形象

头像

结果(在 RawImage 中)

对不起我的绘画技巧:D

【讨论】:

  • 嘿,我在计算索引时发现了我的错误;)现在它应该可以工作了^^
  • 提名此答案为 stackoverflow 上的最佳艺术作品
【解决方案2】:

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

因此,相反,将头部和身体放入单独的对象中,然后使用 Sorting Group component 将它们排序在一起。

示例字符:

排序组前

将排序组应用于根对象(本例中为ChombiBoy):

排序后的组(顶部渲染的字符在其Sorting Group中具有更高的Order in Layer):

(图片取自 Unity 文档)

对排序组进行排序

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

有时,同一排序层中的两个或多个对象可能会重叠(例如,横向滚动游戏中的两个玩家角色,如下例所示)。层中的顺序属性可用于将一致的优先级应用于同一层中的排序组。 与排序层一样,较低的数字首先呈现,并被具有较高层数的排序组遮挡,后者稍后呈现。有关编辑排序层的详细信息,请参阅标签和层的文档。

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

【讨论】:

  • 那么按照层中的排序顺序,原来的现在只会在组中起作用,对吧?世界上的集团呢?
  • @Alexxjaz 是的,头部和身体Sprite Renderers将在顺序之后渲染一个(按照他们的order in layer相互比较确定的顺序),然​​后整个组将是根据Sorting Grouporder in layer在树的前面或后面排序
  • 非常感谢你们帮助我!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 2011-08-06
  • 1970-01-01
相关资源
最近更新 更多