You have to be more specific I think in what type of snapping you want, are you looking for a grid based system? Or do you just simply want a ghost of your object to appear and go to wherever your raycast goes and then you place your building? Ground snapping is a rather vague term, alternatively do you want something where you can pick up any gameobject and drag it around etc.?
I just want to click on a hotkey and have the gameobject’s transform position be set to where a raycast has hit a physics collider in my scene.
Using the code in that thread gives me a consistant slight offset one where the ray is supposed meet the ground.
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class SceneEdits
{
[MenuItem("JeyHotkeys/Set Player To Mouse")]
private static void PlacePlayerToMouse()
{
var player = Object.FindObjectOfType<Player>();
if (player == null) return;
var playerGroup = player.transform.parent;
var hasHit = FindCursorRaycastPosition(out var hit);
Debug.Log("Set Player To Mouse: " + hasHit);
if (hasHit)
{
Undo.RegisterFullObjectHierarchyUndo(playerGroup, "Place to mouse");
var pos = hit.point;
Debug3DExt.DrawCrossXZ(pos, Color.red, 1f, 1f);;
playerGroup.transform.position = new Vector3(pos.x, pos.y, pos.z);
}
}
public static Ray GUIPointToWorldRay(Vector2 position)
{
var sv = SceneView.lastActiveSceneView;
Vector3 mousePos = Event.current.mousePosition;
mousePos.y = sv.camera.pixelHeight - mousePos.y;
return sv.camera.ScreenPointToRay(mousePos);
}
private static bool FindCursorRaycastPosition(out RaycastHit _infoHit)
{
_infoHit = new RaycastHit();
if (Event.current == null) return false;
Ray ray = GUIPointToWorldRay(Event.current.mousePosition);
return Physics.Raycast(ray, out _infoHit, 10000f);
}
}
You’ve given me a top down view when I need to see how the player is being moved on the ground from a side view. Going by what you’ve said though there are some tweaks you can do. It seems that your raycast is pointing directly at the transform of your player which causes a lot of accuracy issues including a very common problem of intersecting halfway into the ground or doing something
The reason for this is that your raycast targets the transform of whatever gameobject it is trying to detect, in this case the centre of the player or wherever the pivot point happens to be. To fix this create an empty gameobject and place it underneath the player then have the raycast work off that empty rather than the player gameobject itself, make the player gameobject a child of the empty gameobject and that should solve a lot of problems with your raycast.
If it doesn’t let me know and give us a gif or screenshot so we can see what’s happening from a better angle but the majority of problems I’ve had with raycasting have been solved with this method. I recommend always using an empty for raycasting rather than using your models etc. as it gives you far more control over how your raycast behaves without messing with your original models and other assets.
The problem is not that there’s an offset with my transform, it’s the result of the raycasting. I draw a cross where the raycast meets the ground, you can see it in the gif.
The reason that the raycast is bad is because it doesn’t shoot exactly from my cursor. Basically somehow this function is not quite correct in my case:
public static Ray GUIPointToWorldRay(Vector2 position)
{
var sv = SceneView.lastActiveSceneView;
Vector3 mousePos = Event.current.mousePosition;
mousePos.y = sv.camera.pixelHeight - mousePos.y;
return sv.camera.ScreenPointToRay(mousePos);
}
OHHH!! So that’s what you’re wondering about, that’s actually a bit more complicated than what I was thinking. I’m not sure how you would get it more accurate on the cursor itself but one option you could try is to maybe hide the cursor and make some kind of phoney cursor and have that as a child of an empty gameobject, you would then have all the raycasting happen from the empty it is attached to rather than the cursor itself.
As far as the player would be concerned that would be the real cursor and you might have more luck with the accuracy using that as opposed to just firing a raycast vaguely from the cursor if that makes sense. The others might have better ideas because as far as I know it might be tricky dealing with raycasting from the mouse cursor.
Empties are great, they give you way more control over raycasting in these sorts of situations, so I’d recommend using that method and seeing how it goes, you could even make a fancier graphic to show the position like a 3D arrow or something and that will help out even more with accuracy.
Again, gamers won’t notice this change, as long as it all works and looks like a real mouse cursor this will probably work better than the option you’re currently using. This is an option by the way I’ve used myself, I use it to help me with accurately picking up other gameobjects and throwing them etc. from an RTS style view you get the added benefit of parenting and switching gameobjects for new graphical effects when you interact with other stuff too rather than relying on the 2D cursor.