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

使用Raycast.TextureCoord在Unity 3D物体上绘制失败问题求助

嘿,我来帮你排查下这个问题~你遇到的立方体无法绘制的情况,我之前刚帮朋友解决过类似的,主要有几个常见的坑,咱们一个个来捋:

可能的原因及解决方案

1. MeshCollider的纹理坐标读取问题(最常见)

Unity自带的立方体这类Primitive物体,用MeshCollider时返回的hit.textureCoord经常会出现不准确的情况,哪怕你关闭了Convex也没用。其实对于立方体来说,用BoxCollider反而更靠谱,而且根本不需要依赖MeshCollider来获取纹理坐标——只要物体有Renderer和正确的UV,hit.textureCoord本身就能返回正确的值。

解决方法:

  • 给立方体替换上BoxCollider(删掉原来的MeshCollider)
  • 修改代码里的判断逻辑,去掉meshCollider == null的检查:
    把这行代码:
    if (rend == null || rend.sharedMaterial == null || rend.sharedMaterial.mainTexture == null || meshCollider == null) return;
    
    改成:
    if (rend == null || rend.sharedMaterial == null || rend.sharedMaterial.mainTexture == null) return;
    

2. 材质实例化导致的修改不生效

你的代码里用了rend.material.mainTexture,每次调用rend.material都会从共享材质复制出一个新的临时实例,这意味着你修改的是这个临时材质的纹理,虽然运行时理论上能看到效果,但很容易出现“看起来没变化”的情况。

优化建议:
如果场景里只有这一个立方体用该材质,直接改成rend.sharedMaterial更稳妥(注意:修改sharedMaterial会影响所有使用该材质的物体):

Texture2D tex = rend.sharedMaterial.mainTexture as Texture2D;

如果后续要用到多物体,建议在Start方法里提前获取一次材质实例,避免每次Update都创建新实例。

3. 纹理的Read/Write Mode设置未真正生效

虽然你说已经开了Read/Write Mode,但很多新手容易忘记点击纹理Inspector面板底部的Apply按钮,导致设置没保存到Asset里。

检查步骤:

  • 选中你的纹理Asset
  • 在Inspector里确认Read/Write Mode是Enabled
  • 点击面板底部的Apply按钮,确保设置生效

4. 代码里的小瑕疵(不影响功能但需要修正)

你的代码开头重复写了using UnityEngine;,虽然不会导致功能失效,但会出现编译警告,建议删掉其中一个。

调整后的完整代码

我给你整理了修改后的代码,解决了上面提到的所有问题,还加了像素边界判断防止越界:

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

public class Paint : MonoBehaviour 
{ 
    public Camera cam; 

    void Start() 
    { 
        cam = GetComponent<Camera>(); 
    } 

    void Update() 
    { 
        if (!Input.GetMouseButton(0)) return; 

        RaycastHit hit; 
        if (!Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition), out hit)) return; 

        Renderer rend = hit.transform.GetComponent<Renderer>(); 

        if (rend == null || rend.sharedMaterial == null || rend.sharedMaterial.mainTexture == null) return; 

        Texture2D tex = rend.sharedMaterial.mainTexture as Texture2D; 
        Vector2 pixelUV = hit.textureCoord; 
        pixelUV.x *= tex.width; 
        pixelUV.y *= tex.height; 

        // 防止坐标超出纹理范围,避免报错
        int x = Mathf.Clamp((int)pixelUV.x, 0, tex.width - 1);
        int y = Mathf.Clamp((int)pixelUV.y, 0, tex.height - 1);

        tex.SetPixel(x, y, Color.black); 
        tex.Apply(); 
    } 
}
额外小提示
  • 测试时建议用分辨率高一点的纹理(比如256x256或512x512),单个黑色像素在立方体上可能不太容易看清
  • 如果想绘制更大的点,可以用SetPixels循环绘制周围像素,效果会更明显
  • 默认立方体的UV是没问题的,但如果是自定义模型,要确保UV映射正确

内容的提问来源于stack exchange,提问作者Lucas Farleigh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:03:59