大家好,

我正在 Unity 中开发一个游戏其中,玩家可以在 2D 精灵中清除圆形区域的功能。至今,这一功能基本上已经按照预期运作,但是我遇到了一個問題:实际上,清除的是一个环形区域(中心区域依然未被清除)。

目前,我使用 Unity 的 Unlit/Transparent着色器来清除,但是这个方法可能不太适合实现完全圆形的效果。 我怀疑可能需要编写一个自定义着色器,但我对着色器开发一无所知。

以下是一个视频,展示了这个问题:

https://youtu.be/xMcfdo25tf8

以下是主要代码部分:

public void PaintAtUV(Vector2 pos)
{
    GetSpriteUVAtWorldPos(pos, out Vector2 uv);
    RenderTexture prevRT = RenderTexture.active;
    RenderTexture.active = maskRenderTexture;
    GL.PushMatrix();
    GL.LoadPixelMatrix(0, maskRenderTextureSize, maskRenderTextureSize, 0);
    float px = uv.x * maskRenderTextureSize - halfAdjustedBrushSize;
    float py = (1f - uv.y) * maskRenderTextureSize - halfAdjustedBrushSize;
    Graphics.DrawTexture(new Rect(px, py, adjustedBrushSize, adjustedBrushSize), brushTexture2D, brushMat);

    GL.PopMatrix();
    RenderTexture.active = prevRT;
}

以下是与上述代码相关的另一个部分:

[SerializeField] private Material revealMaterial; //Terrain 2 material
[SerializeField] private Texture2D brushTexture2D;
[SerializeField] private Material brushMat;
[SerializeField] private SpriteRenderer spriteRenderer;
[SerializeField] private float brushSize;
private RenderTexture maskRenderTexture;
// private readonly int MaskTexID = Shader.PropertyToID("_MaskTex");
[SerializeField] private Transform spriteTransform;
private Sprite sprite;
private Vector2 spritePivot;
private float spritePpu;
private float adjustedBrushSize;
private float halfAdjustedBrushSize;
// private float adjustedBrushHeight;
private int maskRenderTextureSize;

void Start()
{
    // Create mask RenderTexture
    maskRenderTextureSize = 512;
    maskRenderTexture = new RenderTexture(maskRenderTextureSize, maskRenderTextureSize, 0, RenderTextureFormat.Default);
    maskRenderTexture.Create();
    sprite = spriteRenderer.sprite;
    spritePivot = sprite.pivot;
    spritePpu = sprite.pixelsPerUnit;

    // Clear mask to white
    RenderTexture prevRT = RenderTexture.active;
    RenderTexture.active = maskRenderTexture;
    GL.Clear(true, true, Color.white);
    RenderTexture.active = prevRT;

    // Assign mask to shader
    revealMaterial.SetTexture(Shader.PropertyToID("_MaskTex"), maskRenderTexture);

    adjustedBrushSize = brushSize / spriteTransform.lossyScale.x;
    halfAdjustedBrushSize = adjustedBrushSize * 0.5f;
}

void GetSpriteUVAtWorldPos(Vector2 worldPos, out Vector2 uv)
{
    Vector2 localPos = spriteTransform.InverseTransformPoint(worldPos);

    // Convert to UV coordinates
    uv = new Vector2(
        (localPos.x * spritePpu + spritePivot.x) / sprite.rect.width,
        (localPos.y * spritePpu + spritePivot.y) / sprite.rect.height
    );

    // return uv.x >= 0f && uv.x <= 1f && uv.y >= 0f && uv.y <= 1f;
}

brushMat:

https://preview.redd.it/or7okmsnc5wg1.png?width=585&format=png&auto=webp&s=74f757a89502c12a884945ab33689ac425185260