Skip to content

Instantly share code, notes, and snippets.

@inoook
Created November 10, 2023 12:24
Show Gist options
  • Save inoook/41c092b517e1e386393ecbc482ee9927 to your computer and use it in GitHub Desktop.
Save inoook/41c092b517e1e386393ecbc482ee9927 to your computer and use it in GitHub Desktop.
UnityでMeshの色取得。subMesh対応
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class MeshTextureColorPicker : MonoBehaviour
{
/// <summary>
/// Meshをstaticにしているとbatchで結合されsubmeshIndexが異なり正常に取得できなくなる。
/// 対応方法 (対象となるMeshをBatchingの対応外にする)
/// - 対象となるMeshColliderのMeshRendererを非表示にする
/// - 対象となるMeshのBatching Staticをオフにする
/// もしくは、プログラムを変更する必要はあるが、Meshが1つだけであればmf.sharedMeshの代わりにMeshを設定(Physics.Raycastでmeshを取得するのではなく、あらかじめ地面のMeshを設定する)する。
/// UVの値が正常に取得できない
/// - fbxの設定でMeshがReadWriteを有効にしていないと、Vector2 uv = hit.textureCoord;が取得できない。※ビルド時のみこの問題は発生する。
/// </summary>
[SerializeField] int debug_submeshIndex = 0;
// https://answers.unity.com/questions/291853/raycasthit-triangleindex-and-submeshes-which-subme.html
int GetSubmeshIndex(int triangleIndex, Mesh mesh)
{
int triangleCount = 0;
for (int i = 0; i < mesh.subMeshCount; ++i)
{
var count = mesh.GetSubMesh(i).indexCount;
triangleCount += count / 3;
if (triangleIndex < triangleCount) return i;
}
return -1;
}
Color GetRaycastHitColor(Ray ray, LayerMask layerMask)
{
Color color = Color.black;
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
{
Vector2 uv = hit.textureCoord;
Renderer renderer = hit.collider.GetComponent<Renderer>();
MeshFilter mf = hit.collider.GetComponent<MeshFilter>();
Mesh m = mf.sharedMesh;
int triangleIndex = hit.triangleIndex;
//Debug.LogWarning($"triangleIndex: {triangleIndex} / subMeshCount: {m.subMeshCount}");
int submeshIndex = GetSubmeshIndex(triangleIndex, m);
debug_submeshIndex = submeshIndex;
//Debug.Log(mf.mesh.subMeshCount + " / "+hit.triangleIndex);
//Debug.Log($"submeshIndex: {submeshIndex} / {mf.mesh.subMeshCount} ");
if (renderer && submeshIndex > -1)
{
Material mat = renderer.sharedMaterials[submeshIndex];
if (mat != null)
{
Texture2D tex = (Texture2D)(mat.mainTexture);
Vector2 tiling = mat.mainTextureScale;
Vector2 offset = mat.mainTextureOffset;
uv.x *= tex.width * tiling.x;
uv.y *= tex.height * tiling.y;
uv.x += tex.width * offset.x;
uv.y += tex.width * offset.y;
color = tex.GetPixel((int)uv.x, (int)uv.y, 0);
}
}
}
return color;
}
// Test
[SerializeField] Transform m_transform = null;
[SerializeField] Color pickColor = Color.black;
[SerializeField] LayerMask layerMask = 0;
// Update is called once per frame
void Update()
{
Ray ray = new Ray(m_transform.position, m_transform.forward);
pickColor = GetRaycastHitColor(ray, layerMask);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment