Cube is half above plane and half below it when following mouse?

Hi all,

Was following this tutorial from Code Monkey where he shows you how to get an object to follow your mouse in 3d space -

I created my scene using a Cube as the object following the mouse and a plane as the ground.

The plane has a mesh collider, no physics. The cube has a box collider no physics.

Code looks like this:

   void Update()
    {
        Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);
        if(Physics.Raycast(ray, out RaycastHit raycastHit, float.MaxValue, layerMas)){
            transform.position = raycastHit.point;
          
        }
    }
}

The problem is, when I start my scene the code is half below the plane, half above it.

And when I move the mouse it stays half below/half above, I can’t even elevate it in the scene.

It seems like when I go to the planes mesh collider and turn on the option “Convex”, it fixes the issue, but I’m not sure if that’s the correct way to fix this or not.

I also am confused on how to build floors. I followed the Unity tutorials and they used planes, so I figured that was the correct way.

if youre just using a primitive cube, then its transform.position is the center of the cube. youre setting that value to where the raycast hit is, which is probably the surface of the plane. so the center of the cube woud be on the plane. if this is the issue, you could add an offset like

transform.position = hit.point + (0.5f * boxHeight * Vector3.up);

or make the cube a child of an empty gameobject and have the cube’s local position be half its height above the parent. you would then need to be making sure that you reference the parent instead of the cube like cubesParent.transform.position = hit.point;
in this case you may want the collisder on the parent.

the second option definitely seems like more work, but i find it to be the more scaleable solution if you plan on working on the project for a while and adding a lot to it. if you’re just learning a little and moving on, not a big deal.

regarding convexity, you should mark convex if your shape is indeed convex or if you want it treated as such. a standard plane i probably convex. ideally you’d want to avoid non-convex colliders, and ideally mesh colliders altogether.

2 Likes

Huh, interesting response for the convex question I asked. In your opinion then, is it better to build floors using cubes that look like planes which have box colliders instead?

And I’ll look at that second option you gave and edit my post later. Thank you for replying man. And nice profile pic…aw jeez

Yes, it is. Mesh colliders consists of triangles and checking collisions with the surface of a triangle net is much more complicated and expensive. Primitive colliders (BoxCollider, SphereCollider, CapsuleCollider) are mathematical convex shapes which are way simpler. A single plane mesh is not convex as it doesn’t have any thinkness. A convex mesh must enclose a volume and is always closed from all sides. A MeshCollider is just a collider on the surface and does not necessarily enclose any volume. When you tick the “convex” checkbox, Unity will calculate a completely new collider for your mesh that is the convex hull of the provided mesh. In the past Unity had thrown an error when you used it on a MeshCollider with a mesh without any depth. However afair now if you mark a flat mesh as convex, Unity adds some thickness to the collider. Though primitive colliders are almost always better.

1 Like

I used your offset method and it worked. I attached a pic and it’s flush against the wall. I created a new project just to test out the ray-casting.

Did a quick mousePositionInWorld = hit.point + (Vector3.back * 0.5f);

Ill take a look at the second option you mentioned. I’m not totally familiar with moving child objects within local space of a parents object, but I think for my use case which will be to just place buildings down the offset prob works.

8723172--1179678--cube.JPG

You shouldn’t use + (Vector3.back * 0.5f); but just use + hit.normal * 0.5f. Or if the cube you place at your mouse position is scaled, you may want to scale that offset vector according to the scale of the cube object. For that you can use cube.TransformVector(cube.InverseTransformDirection(hit.normal) * 0.5f). Here cube would be the transform of your cube object that should follow the mouse.

2 Likes

Ok i think I see what you are saying.

is there any reason this

+ (Vector3.back * 0.5f);

is better than this

+ hit.normal * 0.5f

Was just using a primitive cube with the default scale, but thank you for the heads up as I was going to need to know that for the future

Uhm, not sure if you didn’t understood what I said or if you swapped the two code samples. Anyways, hit.normal gives you the normal vector of the surface that you hit. So when you hit a vertical wall the normal points outwards, if you hit the floor from the top, the normal would point upwards. If you hit the ceiling from below, the normal would point downwards. So always away from the surface. Vector3.back is just (0,0,-1) in worldspace.

1 Like

Oh sorry that was a mistype,I did understand what you were saying, I did mousePositionInWorld = hit.point + hit.normal * 0.5f;

Another quick question. Other than the blind eye, what is the best way to tell if an object is flush on the ground?

Sometimes ill duplicate objects, one will have a coordinate that is 0.5. the other will have a coordinate that is 0.55, both on y-axis. They both look flush to the ground to me. Does it matter this small difference or is there a special way to tell?

Well, is the surface actually completely level? If the ground is tilted slightly, of course objects you place at different locations would have different y coordinates.

Well, that’s not an easy task in general because it depends on the kind of objects. If we still just talk about a cube and a flat surface, as long as the cube has the exact same rotation / orientation as the ground below it (so that that contact surfaces are parallel), placing the cube half its size above the hit point would always work. If the ground you want to place the object on is not tilted, you can reorient the cube so one of its sides is parallel to the surface. You can also use the hit normal to do that. Though now it gets way too abstract as it’s not clear what kind of orientation the object should have and if it’s always a cube.

Bingo. This makes your life a lot easier: you figure out how to get everything positioned correctly once, and that’s it.