0
\$\begingroup\$

I want to show object name whenever mouse over happens on a certain object and here is my code snippet that trying to place World space UI image object on top of the object.

private void OnMouseEnter()
{
    if (!EventSystem.current.IsPointerOverGameObject())
    {
        Vector3 topPosition = MeshTopPoint.GetMeshTopPoint(this.gameObject);
        partNameImage.transform.position = topPosition; 
    }
}

but the problem is it is not placing the object on center top of the object instead of it like this (placing UI on the corner): enter image description here

And here is my mesh top position get function:

public class MeshTopPoint : MonoBehaviour
{


    // Update is called once per frame
    public static Vector3 GetMeshTopPoint(GameObject go)
    {
        Vector3 worldUp = go.transform.InverseTransformDirection(Vector3.up).normalized;
        Plane p = new Plane(worldUp, Vector3.zero);
        Vector3[] verts = go.transform.GetComponent<MeshFilter>().sharedMesh.vertices;
        Vector3 topVertex = Vector3.zero;
        float maxDist = float.NegativeInfinity;
        for (int i = 0; i < verts.Length; i++)
        {
            float dist = p.GetDistanceToPoint(verts[i]);
            if (dist > maxDist)
            {
                maxDist = dist;
                topVertex = verts[i];
            }
        }

        topVertex = go.transform.TransformPoint(topVertex);
        return topVertex;

    }
}

Here is my UI Image: enter image description here

\$\endgroup\$
3
  • \$\begingroup\$ How have you configured your partNameImage UI element in the inspector/hierarchy? \$\endgroup\$
    – DMGregory
    Commented May 5, 2020 at 11:41
  • \$\begingroup\$ I have updated the question Please check. partNameImage is child of canvas. \$\endgroup\$ Commented May 5, 2020 at 11:46
  • \$\begingroup\$ Are you sure you want to loop over all the vertices in your mesh every time the mouse passes over something, instead of just choosing a point above the center of the object's bounds? \$\endgroup\$
    – DMGregory
    Commented May 5, 2020 at 17:14

1 Answer 1

0
\$\begingroup\$

You are getting the topmost vertex, and setting the coordinates to this point. The problem is, on a box you have 4 top vertices if it is placed with a 0 rotation angle. One for each corner of the face.

There are multiple ways to solve this, but using what code you already have, you can add the topvertices in a list if they are equally high and then you can take the average position of those. This will bring it into the middle. However, by doing this you will see artifacts when rotating the object, the UI will jump around as the calculations will be different.

Therefore it would be better to just take the center position of the object, take the bounding volume of the mesh, and add half of the bounding volume height to the center position. Then you would be placing your UI in the center of the object at the same height just above the mesh at all times.

EDIT: Here is some code to do this, however note that I am not at my computer to verify, but it is something along the lines of:

Mesh mesh = GetComponent<MeshFilter>().mesh;
Bounds bounds = mesh.bounds;
Float halfheight = bounds.extents.y;
Vector3 pos = new Vector3(bounds.center.x, bounds.center.y+halfheight, bounds.center.z);
\$\endgroup\$
2
  • \$\begingroup\$ Yes, you are right cube have four corners and all are equal. What is the last approach you mentioned can you code? \$\endgroup\$ Commented May 5, 2020 at 12:20
  • \$\begingroup\$ Updated answer with code \$\endgroup\$
    – Zillo
    Commented May 5, 2020 at 17:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .