如何在Unity中更改Sprite的uv?

3
我编写了以下脚本:
public class SpriteUV : MonoBehaviour 
{
    private SpriteRenderer _spriteRenderer;
    private Sprite _sprite;

    [SerializeField] public Vector2[] _uv = new Vector2 [4]
    {
        new Vector2(0.4f, 0.5f),
        new Vector2(0.6f, 0.5f),
        new Vector2(0.4f, 0.35f),
        new Vector2(0.6f, 0.35f)
    }; 

    void Start ()
    {
        _spriteRenderer = GetComponent<SpriteRenderer>();
        _sprite = _spriteRenderer.sprite;
    }

    // Update is called once per frame
    void Update ()
    {
        _sprite.uv = _uv;
    }
}

但是这里有一个错误,事实上Sprite.uv没有setter(在文档中不明显)。我该如何改变精灵以映射纹理的不同部分?


1
需要做的是根据某些输入以编程方式更改UV。这不是静态设置。 - Narek
我相信精灵UV将存储在精灵渲染器中的材质上...你能简要解释一下你想做什么吗?比如,你为什么要改变精灵UV? - AresCaelum
1
渲染我想要的纹理部分 :) - Narek
一个不太正规的方法可能是使用粒子系统。它可以非常快速、非常轻便地调整使用精灵表的哪一部分。 - Confused
1
这里有一个解决方案,可以在平面上使用MeshRenderer来规避问题; 这里是一个更复杂的解决方案,包括一个自定义着色器,可能能够达到您想要的效果..没有测试过。 - derHugo
显示剩余7条评论
3个回答

4
这是一种解决方案,它可以与SpriteRenderer一起使用,至少可以选择要显示的Sprite的矩形部分。 (正如程序员在评论中正确地指出的那样,如果您需要完全不同的映射,则无法“变形”UV。)
  1. Create a new Shader and call it BlendVertexColorWithUV

  2. Open it in VisualStudio (or any text editor) and past in the following code
    Source

     // unlit, vertex color, alpha blended, offset uv's
     // cull off
    
     Shader "BlendVertexColorWithUV" 
     {
         Properties 
         {
             _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
         }
    
         SubShader
         {
             Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
             ZWrite Off Lighting Off Cull Off Fog { Mode Off } Blend SrcAlpha OneMinusSrcAlpha
             LOD 110
    
             Pass 
             {
                 CGPROGRAM
                 #pragma vertex vert_vct
                 #pragma fragment frag_mult 
                 #pragma fragmentoption ARB_precision_hint_fastest
                 #include "UnityCG.cginc"
    
                 sampler2D _MainTex;
                 float4 _MainTex_ST;
    
                 struct vin_vct 
                 {
                     float4 vertex : POSITION;
                     float4 color : COLOR;
                     float2 texcoord : TEXCOORD0;
                 };
    
                 struct v2f_vct
                 {
                     float4 vertex : POSITION;
                     fixed4 color : COLOR;
                     float2 texcoord : TEXCOORD0;
                 };
    
                 v2f_vct vert_vct(vin_vct v)
                 {
                     v2f_vct o;
                     o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                     o.color = v.color;
                     o.texcoord = TRANSFORM_TEX (v.texcoord, _MainTex);;
                     return o;
                 }
    
                 fixed4 frag_mult(v2f_vct i) : COLOR
                 {
                     fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
                     return col;
                 }
    
                 ENDCG
             } 
         }
    
         SubShader
         {
             Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
             ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off Fog { Mode Off }
             LOD 100
    
             BindChannels 
             {
                 Bind "Vertex", vertex
                 Bind "TexCoord", texcoord
                 Bind "Color", color
             }
    
             Pass 
             {
                 Lighting Off
                 SetTexture [_MainTex] { combine texture * primary } 
             }
         }
     }
    
  3. Create a new Material

  4. Drag the BlendVertexColorWithUV onto this material

  5. assign this material to the Object that uses the SpriteRenderer

  6. Set the SpriteRenderer's DrawMode to Tiled

  7. Set the TileMode to Continous

enter image description here

注意:我在提取时实际上犯了一个错误:你将Sprite分配给SpriteRenderer而不是材质!您实际上可以将材质留白,只需调整TilingOffset值即可。

现在,您可以通过使用脚本来调整材质中精灵的偏移量。

public Material textureToAnimate;
public Vector2 uvOffset;

....

textureToAnimate.mainTextureOffset = uvOffset;

使用带有透明度的精灵进行此操作。为了使其与之配合,您必须将纹理中的MeshType更改为full rect而不是polygon。这就是我在上面的评论中提到的精灵生成一种网格的内容。 - AresCaelum
1
设置UV偏移量与将UV数组设置为变量是不同的。我认为OP想要更改UV数组... - Programmer
1
关于@程序员所说的,您仍需要更改大小选项以使其确定最后2个UV的位置。 - AresCaelum
@Eddge 我在获取时实际上犯了一个错误:你将 Sprite 设置为了 SpriteRenderer 而不是材质!对我来说,使用透明精灵也同样有效。在 Sprite 设置中选择 SimplePolygon 也没有任何区别。材质中的平铺可以改变大小。 - derHugo
@程序员 无论如何,您是正确的,如果您想“变形”UV映射而不仅仅是选择要映射的部分,则可能无法使用此方法。 - derHugo
编程上你可以做的一件事是通过程序来确定其他UV的位置,例如将SpriteRenderer上的宽度和高度设置为1,然后修改平铺... 如果你想要第二组为{0.3f, 0.35f}而第一组为{0.2f, 0.2f},那么你可以用 determineTiling = secondSet - firstSet 来获得大小, 接着 tiling = {1f/determineTiling.x, 1f/determineTiling.y}。但这本质上是一种hack方法... - AresCaelum

0
现在有一种更直接的方法,只需通过Unity添加额外的Sprite2D包即可:
sprite.SetVertexAttribute<Vector2>(VertexAttribute.TexCoord0, uv);

唯一的注意事项是它需要一个本地数组,但您可以在调用后立即使用Dispose()释放它。 同样还有一个Get()方法。


0

我刚刚使用了Quad,你可以设置uvsverticestriangles。所以基本上从Sprite中获取了所有信息(uv、vertices),并将其传输到Quad中。


在Unity中,有很多东西被称为Quad。在Unity 2019中,有一个3D Quad对象。你也可以创建一个空的GameObject,然后添加一个网格到它上面。接着再给这个网格添加一个Quad纹理。你指的是哪一个Quad呢? - Maxi Wu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接