Created
November 10, 2023 12:24
-
-
Save inoook/41c092b517e1e386393ecbc482ee9927 to your computer and use it in GitHub Desktop.
UnityでMeshの色取得。subMesh対応
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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