Raycasting on cube, instantiate on center.

I already know how to ray cast. Right now im a instantiating an object where ever the ray hits. What i really want to do is instantiated the object at the center of the cube’s face which was hit.
Right now they just spawn where ever the raycast hit.
This is my code for that.

Instantiate(ball, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal));

Any help would be appreciated.

This isn’t too hard, you actually already have most of the information you need.

In brief:

Assuming your cuboid has its pivot in the centre then:

Vector3 positionToInstantiateAt = Vector3.Project((hit.point - hit.transform.position), hit.normal) + hit.transform.position;

That should do what you want. This should also work if your cube isn’t regular.

It doesn’t depend on you knowing the size of the cube either, so you’re free to change the size whenever you want without having to worry. All that’s required is that it is cuboid and has its pivot in the centre.

The reasoning:

hit.normal is the normal for where the Raycast hit i.e. the direction pointing out from the cube’s face. Assuming the cube has its pivot in the exact centre (it is in Unity’s Cube primitive), then this also tells you the direction to move from the centre of the cube to the face. The position of the centre of the cube it simply hit.transform.position, of course, since the cube was the object you hit.

The only remaining thing to add is the size of the cube:

  • If you know this number (it’s fixed) then you can simply add it in yourself.
  • If you are using a Unity Cube primitive then the default size (scale (1f, 1f, 1f)) gives you a 1x1x1 cube, so the distance from the centre to a face will be half of that. Assuming it is a cube (i.e. the each face is the same size) then this is as simple as picking a value (e.g. transform.lossyScale.x) and halving it.
  • In the most general case, requiring the least information input from you (i.e. it all comes from the Raycast), you can figure out the distance from the point hit.

If you know the distance then you could do something simple like this:

Vector3 positionToInstantiate = hit.transform.position + (distanceFromCubeCentreToFace * hit.normal);

For the latter, you know the vector pointing from the centre to the point hit (hit.point - hit.transform.position). What you want to know is the part of that vector in the direction of the face you’re interested in. Fortunately you can project a vector, which is what we do here. See the reference here if you don’t know about vector projection.

Using this, then our only requirement is that the pivot is in the cube’s centre and we can even support other cuboids and get the position as:

Vector3 positionToInstantiateAt = Vector3.Project((hit.point - hit.transform.position), hit.normal) + hit.transform.position;

Try this:

Instantiate(ball, hit.transform.position, Quaternion.FromToRotation(Vector3.up, hit.normal));

However, if you want to instantiate a ball on the center of the face, you have to mess a lot with colliders and that stuff is really hard to understand. I can offer you to create a cube from 6 quads and store it as a prefab. Replace all the cubes with this one and use the code above to instantiate your ball in the middle of the cube face.