Trying to Select Objects via Linecast

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?

So I’m not sure what you’re trying to do here, you want to select the bottom of the box, but still want to hit 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;
}

Hope that helps you out.

-Raiden

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.

So trying your script out Raiden, it has trouble setting that first Vector -

public static Vector3 PlacePrimitiveColliderOnSurface(Transform TFM, Collider pCollider, float pColliderOffset) {

What variables need to exist in the scene for it to reference them properly?

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);
    }
}

Hope this helps you out.

-Raiden