- Home /
Mouse click a collision mesh
There is a lot of material on these forums about how to detect mouse presses on collision meshes, but I've been unable to adapt other user's solutions for my own situation.
I dynamically create a game object at run time and give it a mesh (the meshes have come from an xml file and are just simple 2D flat polygons at y=0. There's very little overlap (if any) between polygons).
So I have something like this when I parse in the xml file.
/
// Create the rendered mesh for the Game Object
//
Mesh mesh = new Mesh();
mesh.vertices = verticesTemp.ToArray();
mesh.colors = colors;
mesh.triangles = triangles;
//
// Dynamically create the GameObject and add the required components
//
GameObject gameObj = new GameObject(building.name);
gameObj.AddComponent("MeshFilter");
gameObj.AddComponent("MeshRenderer");
gameObj.AddComponent ("MouseHandler"); // Used for mouse events
gameObj.AddComponent("MeshCollider");
gameObj.renderer.material.shader = Shader.Find("PlainColorShader");
gameObj.GetComponent<MeshFilter>().mesh = mesh;
//
// Create a collision mesh (it's the same data as the rendered mesh)
//
Mesh collisionMesh = new Mesh();
collisionMesh.vertices = verticesTemp.ToArray();
collisionMesh.triangles = triangles;
MeshCollider meshCollider = gameObj.GetComponent<MeshCollider>();
meshCollider.sharedMesh = collisionMesh;
As a result, I have many GameObjects in the hierarchy and selecting each shows an attached Mesh Collider and Mouse Handler component (amongst other things)
When in Scene mode, I can see the green wireframe representing the collision mesh, but I can't seem to be able to mouse click it using my MouseHander script/component that I've dynamically added to the GameObject.
I've tried casting rays upon mouse press inside the update() method...
void Update() {
if (Input.GetMouseButtonDown(0)) {
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit)) {
Debug.Log("hit");
}
}
}
...and I've also tried to use the OnMouseOver() method...
void OnMouseOver() {
if (Input.GetMouseButtonDown(0)) {
Debug.Log("hit");
}
}
Does anyone have any ideas why this might not be working?
Thanks.
Answer by aldonaletto · Sep 01, 2013 at 04:47 AM
I suspect that the winding order of your triangles is incorrect: the vertices must be in clockwise order when you look at the triangle. I tested OnMouseDown with a single triangle mesh and it worked as expected. When reversing the triangle winding order, the mesh became invisible and could not be clicked. NOTE: I used the regular Diffuse shader in my tests - depending on the shader you're using, your mesh may be rendered even if backfaced.
Wouldn't this be fixed if I just reversed the normal direction? I'll try it though. Thanks.
Ah, yes! It works. Thank you so much. I'd up vote your answer, but I don't have the rep yet.
Glad to know that this solved your problem. About the normals: they are used mainly for lighting purposes - the winding order is what really matters in defining the front/back face of a triangle.
Answer by fherbst · Aug 31, 2013 at 12:46 PM
Your mesh normals are probably inverted. Raycasts/clicks will only be detected if the surface normals point towards the origin of the ray.
I took your suggestion and added some normals to the collision mesh. Something like...
for (int j=0; j<verticesTemp.Count; j++)
{
normals[j] = new Vector3(0f,1f,0f);
}
collision$$anonymous$$esh.normals = normals.
I also tried Vector3.up and Vector3(0f,-1f,0f)
None of which work.
I know the Update() method of the $$anonymous$$ouseHandling script is being called, it just can't get a true result from the ray cast. Is it possible something else is interferring with the ray cast?
[update] I just tried something similar...
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (collider.Raycast (ray, out hit, 1000.0f)) {
Debug.DrawLine (ray.origin, hit.point);
}
But again, this will not work. However, if select the GameObject from the hierarchy and set $$anonymous$$esh Collider-> Convex to true, so that my green mesh (in scene view) becomes much larger 3D box, then I will get collisions. I need the custom collision mesh though.
Just to add to this since you already accepted an answer: that was exactly what I meant :D.
Answer by unity_scotty · Oct 22, 2019 at 03:21 PM
this doesn't work for me either. How to change the normal for a mesh object (not created from scratch),What is vertexTemp here. I got the same problem, trying to fix the clockwise thing. Not clear how to fix it. Can you share you code a little more?
public class ClickableObject : $$anonymous$$onoBehaviour {
public GameObject definedButton;
public UnityEvent OnClick = new UnityEvent();
Collider coll;
// Use this for initialization
void Start()
{
definedButton = this.gameObject;
coll = this.gameObject.GetComponent<Collider>();
$$anonymous$$eshFilter r = definedButton.GetComponent< $$anonymous$$eshFilter >();
if (r != null)
{
$$anonymous$$esh m = r.shared$$anonymous$$esh;
if (m != null)
{
int[] tris = m.triangles;
for (int i = 0; i < tris.Length; i += 3)
{
int t = tris[i];
tris[i] = tris[i + 1];
tris[i + 1] = t;
}
m.triangles = tris;
}
}
}
// Update is called once per frame
void Update()
{
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (coll.Raycast(ray, out hit, 1000.0f))
Debug.Log(">>> $$anonymous$$ouse Down Hit the following object: " + hit.collider.name);
else
Debug.Log(">>> Nothing was hit!");
}
}
$$anonymous$$y script was assigned to a mesh object. How to make it clockwise here?