You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何将碰撞点转换为Texture2D的像素点?

如何将射线检测得到的3D碰撞点转换为Texture2D的像素坐标?

首先先修正你代码里的一个明显问题:每次调用Draw都新建Texture2D会完全覆盖之前的绘制内容,应该把Texture2D作为脚本的成员变量,在初始化时创建一次。

接下来解决3D坐标转纹理像素坐标的问题,核心思路是把世界空间的碰撞点转换为绘制平面的局部空间坐标,再归一化后映射到纹理的像素范围,步骤如下:

  1. 将世界碰撞点转为平面局部坐标
    使用transform.InverseTransformPoint(hit.point)把射线检测到的世界坐标,转换为挂载该脚本的平面物体的局部坐标(假设你的绘制平面是Quad/Plane,脚本挂在这个物体上)。

  2. 归一化局部坐标到[0,1]范围
    默认的Quad/Plane在局部空间的尺寸是1x1(比如Quad的局部x范围是-0.5到0.5,z范围也是-0.5到0.5),所以把局部坐标的x和z(对应平面的横向和纵向)加上0.5,就能得到0到1之间的归一化值。

  3. 映射到纹理像素坐标
    用归一化值分别乘以纹理的宽度和高度,再取整就得到Texture2D需要的(x,y)像素坐标。

下面是修改后的完整代码:

using UnityEngine;

public class DrawOnPlane : MonoBehaviour
{
    // 定义纹理尺寸和绘制颜色
    public int textureSize = 128;
    public Color drawColor = Color.black;
    
    private Texture2D drawTexture;

    void Start()
    {
        // 初始化纹理,只执行一次
        drawTexture = new Texture2D(textureSize, textureSize);
        // 初始化纹理为白色(可选,根据你的需求调整)
        Color[] clearColor = new Color[textureSize * textureSize];
        for (int i = 0; i < clearColor.Length; i++)
        {
            clearColor[i] = Color.white;
        }
        drawTexture.SetPixels(clearColor);
        drawTexture.Apply();
        
        // 给物体的Renderer赋值纹理
        GetComponent<Renderer>().material.mainTexture = drawTexture;
    }

    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out RaycastHit hit))
            {
                // 只处理当前平面的碰撞(避免误触其他物体)
                if (hit.transform == transform)
                {
                    Draw(hit.point);
                }
            }
        }
    }

    void Draw(Vector3 worldPos)
    {
        // 1. 转换为局部坐标
        Vector3 localPos = transform.InverseTransformPoint(worldPos);
        
        // 2. 归一化到[0,1]范围(这里假设平面是XZ平面,Y轴向上)
        float normalizedX = localPos.x + 0.5f;
        float normalizedY = localPos.z + 0.5f;
        
        // 3. 转换为像素坐标,取整
        int pixelX = Mathf.RoundToInt(normalizedX * drawTexture.width);
        int pixelY = Mathf.RoundToInt(normalizedY * drawTexture.height);
        
        // 确保像素坐标在纹理范围内(防止超出边界报错)
        pixelX = Mathf.Clamp(pixelX, 0, drawTexture.width - 1);
        pixelY = Mathf.Clamp(pixelY, 0, drawTexture.height - 1);
        
        // 设置像素颜色并应用
        drawTexture.SetPixel(pixelX, pixelY, drawColor);
        drawTexture.Apply();
    }
}

注意事项:

  • 如果你的绘制平面不是默认的XZ朝向(比如是XY平面),需要调整局部坐标的轴,比如用localPos.y代替z来计算normalizedY。
  • 添加了hit.transform == transform的判断,确保只在当前平面上绘制,不会误操作场景中的其他碰撞体。
  • 初始化纹理时填充了白色背景,你可以根据需求改成其他颜色。

内容的提问来源于stack exchange,提问作者MUSA ZENBİLCİ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 05:18:16