Unity mesh collider raycast not working - c#

I can not seem to get the raycast to hit the mesh collider. I need this to get the texture uv coordinates.
if (Input.GetMouseButtonUp(0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f))
{
// We've hit this mesh b/c its the only one we have ...
var texture = meshRenderer.material.mainTexture as Texture2D;
var pixelUV = hit.textureCoord;
print("pixs uvs" + pixelUV.ToString());
pixelUV.x *= texture.width;
pixelUV.y *= texture.height;
var position = new Position(pixelUV.x, pixelUV.y);
print("Position: " + position.x + " " + position.y);
texture.FloodFillBorder(position.x, position.y, fillColor, borderColor);
texture.Apply();
}
}
My game object has this script with the update function checking for input, as well as mesh filter, mesh renderer, and mesh collider. The mesh is a simple quad made from unity's menu.
What am I doing wrong? I just do not understand why it is not hitting the mesh. The camera's z position is -10 and the mesh is at 0. Placing differently gives the same results.

You can check the Mesh component and see if 'IsTrigger' is checked but may i suggest something else?
Unity does whole this ray casting for you by default. MonoBehaviour class has functions such as OnMouseDown() or onMouseDrag() etc. where a GUIElement or in your case an object with Collider component gets these events. So if your game object has a collider component just implement one of these methods and you are ready to go.
This may you can keep your update function clean.
Check: http://docs.unity3d.com/ScriptReference/MonoBehaviour.html

Related

Unity3D - Using Raycasting to detect Game Objects. Top-down view

I'm making a top down space resource-gathering game, with 3D models.
I'm trying to cast a ray towards my mouse position, to detect collisions with the objects in my game,
for my little spaceship to know which direction to head to find resources.
The resources are in the form of asteroids the player has to break to gather.
In the code, I use the "center" vector to find the middle of the screen/player position, as the camera follows the player around. All movement happens along the X,Y axis. center.Z is set to 15 simply to counteract the -15Z position of the main camera in worldspace.
So far, the code "works" to the extent that it can detect a hit, but the ray doesn't travel in the direction of the mouse. I have to hold it way off for it to hit, and it's difficult to replicate, to the point where it almost seems random. Might the ray not be able to make sense of the mouse position?
In case I've worded myself poorly, this search ability is not meant to break the asteroid, simply locate it. The breaking ability is a separate script.
Code:
public class AbilitySearch : MonoBehaviour
{
Vector3 center;
Vector3 mousePos;
Vector3 direction;
private float range = 100f;
void Update()
{
center = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 15.0f));
mousePos = Input.mousePosition;
direction = mousePos - transform.position;
if (Input.GetMouseButton(1))
{
Search();
}
}
void Search()
{
RaycastHit hit;
if (Physics.Raycast(center, direction, out hit, range))
{
Debug.Log("You hit " + hit.transform.name);
}
}
}
Thanks in advance
When using Input.mousePosition the position is a pixel coordinate on your screen, so if your mouse was in the bottom left corner of your screen it would be 0,0. This causes the direction to be inaccurate. When what you need is to use the game space coordinates, which is done by using Camera.ScreenToWorldPoint(Input.mousePosition), as an example.
This solution allows you to click on a gameObject (provided it has a collider attached), move the current gameObject towards the clicked object, as well as gather an array of possible gameObjects (RaycastHit[s]) in the direction of the clicked one.
Vector3 destination;
RaycastHit[] possibleTargets;
bool isTravelling;
float searchDistance = 5f;
private void Update()
{
//If right mouse button has been pressed down
if (Input.GetMouseButtonDown(1))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit)) //If ray collides with something
{
Search(hit);
}
}
//If going to destination
if (isTravelling)
{
float step = 2f * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, destination, step);
//If approx arrived
if (Vector3.Distance(transform.position, destination) < 0.1f)
{
isTravelling = false; //Stop moving to destination
Debug.Log("You've arrived");
}
}
}
private void Search(RaycastHit _hit)
{
//Normalise directional vectors, so (if needed) they can be multipled as expected
Vector3 direction = (_hit.point - transform.position).Normalized();
RaycastHit secondHit;
//Grab objects in direction of clicked object (including the one clicked)
possibleTargets = Physics.RaycastAll(transform.position, direction, searchDistance);
Debug.Log($"There are {possibleTargets.Length} possible targets ahead");
Debug.Log($"You hit {_hit.transform.name}");
//Set destination, and set to move
destination = _hit.point;
isTravelling = true;
}
You used the ViewportToWorldPoint method, which expects normalized viewport coordinates in range 0 to 1, but you supplied what seems to me as world coordinates of your camera as its parameter.
You only need to cast a ray from camera to mouse pointer world position (see first line of code in method FindAsteroid) to check for collision with asteroid. The returned RaycastHit provides you with information about the collision - hit position, gameobject, collider - which you can use for other game logic, e.g. shooting a projectile from spaceship to asteroid hit point.
I edited your class and included a screenshot from my simple scene below, which shows the two different "rays":
The yellow ray goes from camera to asteroid hit point
The magenta ray goes from spaceship position to asteroid hit point.
I would also recommend filtering the raycast to affect only specific colliders -
see LayerMask (section Casting Rays Selectively)
public class AbilitySearch : MonoBehaviour
{
private float range = 100f;
private Camera mainCam;
private void Awake()
{
// TIP: Save reference to main camera - avoid internal FindGameObjectWithTag call
mainCam = Camera.main;
}
private void Update()
{
if (Input.GetMouseButton(1))
{
if (FindAsteroid(out var asteroidHit))
{
// Draw a line from spaceship to asteroid hit position
Debug.DrawLine(transform.position, asteroidHit.point, Color.magenta, Time.deltaTime);
Debug.Log($"You hit {asteroidHit.transform.name}");
}
}
}
private bool FindAsteroid(out RaycastHit hit)
{
// Create a ray going from camera position to mouse position in world space
var ray = mainCam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, range))
{
// Draw a line from camera to world mouse position
Debug.DrawLine(ray.origin, hit.point, Color.yellow, Time.deltaTime);
// An asteroid was found
return true;
}
// An asteroid was NOT found
return false;
}
}
Sample spaceship scene

Raycast 2d is not working in Unity3d

I'm new to Unity and blocked 2nd day with a simple try to raycast. This is the script which I use to raycast:
void Update () {
Debug.DrawLine(transform.position, transform.position - transform.up);
RaycastHit2D[] hits = Physics2D.RaycastAll(transform.position, transform.position - transform.up, Mathf.Infinity);
if(hits.Length > 0)
{
Debug.Log("Hit");
}
}
I have attached this script to a square and put near it another square which acts like a target, also added a 2d box collider to the target. I have disabled the "hit itself" feature like is described here:
http://answers.unity3d.com/questions/756380/raycast-ignore-itself.html
After performing all this steps the raycast hits nothing, the collider of the hit object is always null (checked this in debug mode, also nothing is written in console) . I drew a debug line, and indeed it points to the target square like in screenshots.
Please help me figure out what I'm doing wrong.
Physics.Raycast is for 3D Colliders and this includes Box Collider, Sphere Collider and others. No 2D in their names.
Physics2D.Raycast is for 2D colliders. You need a Box Collider 2D since this is a Sprite Renderer which is a 2D Object.
EDIT:
With your edit, the problem is that the direction of the raycast is too short. You have to multiply it by a number. The value of 100 should be fine.
public float distance = 100f;
void Update()
{
Debug.DrawLine(transform.position, transform.position + transform.right);
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.position + transform.right * distance, Mathf.Infinity);
if (hit.collider != null)
{
Debug.Log("hit: " + hit.collider.name);
}
}

raycast wont hit collider after using NGUI?

after turn the main UI framework to NGUI, we found that We couldn't hit object with collider anymore with following code which was working fine we not using NGUI:
private void checkRayCast()
{
if ((Input.GetMouseButtonDown(0)))
{
Debug.Log("shoot ray!!!");
Vector2 point = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit2;
if (Physics.Raycast(ray, out hit2, 100))
{
//this should hit a 3d collider
Debug.Log("we may hit something");
Debug.Log(hit2.collider.gameObject.tag);
}
RaycastHit2D[] hits = Physics2D.RaycastAll(point, Vector2.zero, 0f);
if (hits.Length != 0)
{
//this should all 2d collider
Debug.Log(" ohh, we hit something");
}
else
{
Debug.Log("you hit nothing john snow!!!");
}
//if (hit.transform.gameObject.GetComponent<Rigidbody2D>() != null)
//{
//}
}
}
And we found that we could not hit a 2d collider or 3d collider anymore
Here is the target object's inspector:
EDIT
After following #programmer 's advice and resize the collider to a very big one, hit was detected(thanks, #programmer)
But the collider was changed to so big that it not event make scene. And We should find how big this should be now.
before resizing the collider in the scene
note the green border which indicts the collider size made scene
here is the one that the collider works, but should be unreasonably large:
After digging around And I have figured this out:
The trick is we should use UICamera.currentCamera instead of Camera.main to shoot the ray when we using NGUI.
If we click here in the game view to shoot the ray:
And If we add a line like:
Debug.DrawLine(ray.origin, ray.origin + ray.direction * 100, Color.red, 2, true);
After
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
We should see the actual ray in the scene in a 3d mode:
Note the red line which represents the ray and It could not shoot at the desired position since Camera.main have a different scale.
But if we change the carmera to UICamera to shoot the ray, We could shoot the ray that was desired.
Ray ray = UICamera.currentCamera.ScreenPointToRay(Input.mousePosition);
Hope this could help guys meet with the same pit.

C# Unity Raycast

I have a reversed mesh sphere, with the normals pointing inside, and 6 planes making a cubemap outside this sphere, algo with the normals pointing inside.
I want to know the position of a raycast hit from camera in (0,0,0), also the center of those two figures, to the sphere.
I tryed to use convex mesh collider but the sphere has to much vertex and Unity doesn´t support it. My idea was to check the collision to the cube, and then make a collision to the sphere (with a normal sphere collider) with the direction reversed from the camera.
The second Raycast should come to the point of the first collision and collide with the sphere, but it reports that "print("I'm looking at nothing!");"
public void launchBttn()
{
GameObject.FindGameObjectWithTag("coordText").GetComponent<Text>().text = transform.forward.ToString();
Ray rayBox = GetComponent<Camera>().ViewportPointToRay(transform.forward);
RaycastHit hit;
if (Physics.Raycast(rayBox, out hit))
print("I'm looking at " + hit.transform.name);
else
print("I'm looking at nothing!");
GameObject.FindGameObjectWithTag("collText").GetComponent<Text>().text = hit.transform.position.ToString();
Vector3 fwd = -transform.TransformDirection(Vector3.forward);
RaycastHit hitSphere;
if (Physics.Raycast(hit.transform.position, fwd, out hitSphere))
{
print("I'm looking at " + hitSphere.transform.name);
}
else
{
print("I'm looking at nothing!");
}
GameObject.FindGameObjectWithTag("sphereCollText").GetComponent<Text>().text = hitSphere.transform.position.ToString();
}

Raycast can not detect collider

My bullet can not detect the collider and raycast can not detect the collision. It's very weird since the only way to get a message on the console is whenever I shoot bullets within the range of my terrain(either on or above), I instantly get "Terrain" printed on my console, but the raycast cannot detect any other objects and print anything, and if I go out of the range and shoot at a sphere, nothing gets printed. Everything in my game has a collider except the bullet.
Thanks!
Here's an image of my game .
void Update () {
if (Input.GetKey(KeyCode.KeypadEnter) && counter > delayTime)
{
Instantiate(bullet, transform.position, transform.rotation);
counter = 0;
RaycastHit hit;
if (Physics.Raycast(transform.position, -Vector3.up, out hit))
{
Debug.Log(hit.collider.gameObject.name);
}
}
counter += Time.deltaTime;
}
Add a collider to your bullet prefab. You should have tags on your enemies or other destructible objects. Use OnCollisionEnter OR OnTriggerEnter. For enemies, I prefer to use OnCollisionEnter for the most part.
void OnCollisionEnter(Collision collision){//Assuming bullet touches enemy
if(collision.tag=="Bullet"){
// insert your code here for damage
}
}
As far as your RayCast, I'd do something like this:
Vector3 fwd = transform.TransformDirection(Vector3.forward) * 3; // length of ray
//forward-facing. ( * 3 is equal to 3 units/Meters )
Debug.DrawRay(transform.position, fwd, Color.red); // Can Make any color
if (Physics.Raycast(transform.position, fwd, out hit))
{
print(hit.collider.gameObject.name);
}
See, the reason I'd use collision detection is that as long as your enemy is tagged you'll make contact. Otherwise, your raycast should detect contact and you can still set collision damage or whatever.

Categories