So I have a scene where I have a grid on the ground. I want to select a box ontop of the grid with my mouse, then move it to a corresponding position on a grid. However, when I try to raycast from the camera to the object it hits the top of the object (x, 2.0, z), instead of the bottom of the object (x,0,z). I’ve tried the following code without success -
void OnMouseDown(){
var NoObjects =~(1<<8);
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray, out hit);
hitPoint = hit.point;
Camera.main.ScreenToWorldPoint(CameraPosition);
Physics.Linecast(CameraPosition,hitPoint,NoObjects);
}
}
Ground/Grid is Default Layer
Box is Layer 8
How can I alter the code to have it return the proper X and Z coordinates without the Y getting stuck on the box?
if I am following you correctly, I’m guessing your wanting the bottom of the box for correct placement purposes? I would suggest a little different approach. Instead of wanting to return the “bottom” or “top” of the box, just return the position (hitPoint = hit.transform.position), then use a snapping method to align it on the surface of the position your want to place it.
Here is some code I use for collider positioning:
// method to place the primitive collider on a surface
public static Vector3 PlacePrimitiveColliderOnSurface(Transform TFM, Collider pCollider, float pColliderOffset) {
// we need a RaycastHit field to pass as a parameter to be set as the hit point
RaycastHit hit;
// we also need a return Vector3 for the initialized position from the raycast
Vector3 newPosition = Vector3.zero;
// we perform a raycast downwards to detect the surface
if (Physics.Raycast(TFM.position, -Vector3.up, out hit, 100.0f)) {
// have detetected the ground, create a position from the hit
// point, and half the size of the character controller, and
// the character cntroler height setting, as a return position
// to properly place the character (we add a slight amount to
// ensure the character is barely above the ground
// variable to store a position in the "y" axis, this simplifies
//the code in the Vector3 for the new position
float upPosition = hit.point.y + (pCollider.bounds.size.y + pColliderOffset);
// our new position
newPosition = new Vector3(TFM.position.x, upPosition, TFM.position.z);
}
// return the Vector3 (will be (0,0,0) if not hit.point was returned
if (newPosition.Equals(Vector3.zero)) {
Debug.Log("No hit point returned");
}
return newPosition;
}
I’ll try that suggestion out, I’m trying to make a base-building style mechanic similar to Dungeon Keeper, Clash of the Clans, Evil Genius, etc. where you can position and move things around. However, rather then deal with objects that have a height parameter, having a simple 0 for the Y axis just helps to keep things clean. So the raycast would hit the top of the object, but I’d use the bottom position for grid snapping, etc.
mweyna, you would call it from within your function of the transform you are wanting to snap.
You can use this script on your colliders you want to snap, just attach it to them.
// apply this to a gameobject in your scene you want to snap to a surface
using UnityEngine;
using System.Collections;
public class SnapCollider : MonoBehaviour
{
// public fields
public float heightOffset = 0.5f; // snap it to surface, then raise it up this height
// Use this for initialization
void Start ()
{
transform.position = transform.position + new Vector3(0, 10, 0); // give a little height to start
transform.position = ColliderHelper.PlacePrimitiveColliderOnSurface(transform, transform.collider, 0.0f);
}
}