- Home /
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.
center of the cube's face which was hit
In the most basic version of this you will need to look into the mesh that makes up the cube in more detail. In particular, you will need to deter$$anonymous$$e the triangle it hit, then you can compute the center of that triangle.
This code has a function that will detect ray/plane intersections, which I suspect will be useful for the above: http://wiki.unity3d.com/index.php/3d_$$anonymous$$ath_functions
But it doesn't end there; what if you have two triangles that are flush AND parallel, like the face of a cube? You will need to detect AND combine all such triangles into a polygon (a tough algorithm that I'm still struggling with), and compute the center of THAT. Doing this at runtime, will be REALLY slow. You CAN create the polygons for each shape at startup though, so that might help.
Oh! I guess if the shape is ALWAYS a cube, that would simplify things quite a bit, and we can CHEAT. Is that the case? An example, store the six cube-face center points. When you detect a hit- loop though all six points(transformed to world space)- select the closest of the points, and use that face center.
Answer by Johat · Mar 23, 2015 at 03:50 PM
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;
Awesome. This works. I was just doing hit.transform.position + (hit.point-hit.transform.position) Which was not working. Thank you for you time and effort it is appreciated.
Answer by AurimasBlazulionis · Mar 23, 2015 at 03:37 PM
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.
I think i can make this work with a lazy shortcut around that problem, and just instantiated at an offset according the the Triangle index hit. It will work until i get more experienced with $$anonymous$$esh and can do it the right way.
Your answer
Follow this Question
Related Questions
Making a simple grid 2 Answers
How to make an object spawn in different positions? 2 Answers
Spawning Cube on empty gameobject 1 Answer
Finding center of a cube 1 Answer
Procedural Spawning Theorems 0 Answers