Raycasting from the camera center doesn't work - c#

I'm using the following code to raycast from the center of the camera.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraPointer : MonoBehaviour {
private GameObject hitObject = null;
private Vector3 reticlePosition = Vector3.zero;
public Camera mcamera;
public float Distance = 10f;
void Update () {
reticlePosition = mcamera.transform.position;
Ray ray = mcamera.ScreenPointToRay(reticlePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Distance)) {
if (hitObject != hit.transform.gameObject) {
if (hitObject != null) {
hitObject.SendMessage("OnReticleExit", SendMessageOptions.DontRequireReceiver);
}
hitObject = hit.transform.gameObject;
hitObject.SendMessage("OnReticleEnter", SendMessageOptions.DontRequireReceiver);
} else {
hitObject.SendMessage("OnReticleHover", SendMessageOptions.DontRequireReceiver);
}
} else {
if (hitObject != null) {
hitObject.SendMessage("OnReticleExit", SendMessageOptions.DontRequireReceiver);
}
hitObject = null;
}
}
}
Unfortunately, it doesn't work at all. It is not hitting any object at all. How can I sort this out?

Ray ray = mcamera.ScreenPointToRay(reticlePosition);
this function is the wrong approach.
vector3 parameter in screenpoint should be the GameScreen Position(ex:coordinate at screen 1920x1080)
So, you have to use function mcamera.ViewportPointToRay(new Vector3(0.5f,0.5f));
or you can use
if (Physics.Raycast(reticlePosition, transform.forward,out hit Distance))...

The reason why this may note be working as you intended is that you're projecting a ray from screen space to world space when you call:
Ray ray = mcamera.ScreenPointToRay(reticlePosition);
See the docs here
So if mcamera is located at the origin, you're Raycasting from the bottom left corner of the screen.
If you want to just cast a ray from the center of the camera's viewport, then something like this would work:
Ray ray = new Ray(mcamera.transform.position, mcamera.transform.forward);
This basically casts a ray along the forward vector of the camera starting at the camera's current position.

Related

How can I detect transparent areas in a sprite in Unity

I have a 1024x1024 pixel sprite with some transparent areas in it. I am rendering it on a game scene using Sprite Renderer. Is there any way check whether the pixel at mouse position is transparent or not when the mouse is hovered over it.
We could cast ray and get the world position of our hit point, Here I am assuming your SpriteRenderer has a collider.
private RaycastHit CastRay()
{
RaycastHit hit;
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
Physics.Raycast(ray, out hit);
return hit;
}
Then we need a method to convert that world space into texture coordinates
public Vector2 TextureSpaceCoord(Vector3 worldPos) {
float ppu = _sprite.pixelsPerUnit;
Vector2 localPos = transform.InverseTransformPoint(worldPos) * ppu;
var texSpacePivot = new Vector2(_sprite.rect.x, _sprite.rect.y) + _sprite.pivot;
Vector2 texSpaceCoord = texSpacePivot + localPos;
return texSpaceCoord;
}
Once we get the texture coordinates we could just use GetPixel() of Texture2D to get the color
private void PickColor()
{
RaycastHit hit = CastRay();
if (hit.collider != null)
{
Vector2 coord = TextureSpaceCoord(hit.point);
Color selectedColor = _sprite.texture.GetPixel((int) coord.x, (int) coord.y);
// Here you can check if color is transparent
if(selectedColor == Color.clear){
// do stuff
}
}
}
You could call the PickColor() in Update(), _camera would be Camera.main and _sprite would be the Sprite of your SpriteRenderer

Unity get collision coordinate with hidden part of a plane

i have a sphere on a plane that stick to my mouse. i want to place that sphere so the position of the pointer, where the pointer would hit the plane. But the plane is hidden by the ball. It works, but the movement of the ball is noisy.
i would like to ignore everything except the plane for the collision.
can anyone help ?
This is what i do actually:
if (Ball!= null) {
RaycastHit raycastHit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out raycastHit, 100f))
{
if (raycastHit.transform != null)
{
//Our custom method.
var x = raycastHit.point.x;
var z = raycastHit.point.z;
Ball.pos().get_x().update_value(x);
Ball.pos().get_z().update_value(z);
}
}
}
You can do this by using the Layers & Layer Masks. Create a new layer and name it MyHiddenLayer and assign your object to it. Then do:
// Define output
RaycastHit raycastHit;
// Define Ray
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Define Layer
int layerMask = 1 << LayerMask.NameToLayer("MyHiddenLayer");
if (Physics.Raycast(ray, out raycastHit, 100f, layerMask))
{
...
}

Drawing a sprite on Raycast collision point

I am trying to emit a raycast from the player object and project a crosshair texture onto the world position the crosshair is aimed at. The crosshair should not overlap with the player and it should also only be emited in front of the Player gameObject.
I have tried this so far:
private float range = 100f;
public Texture crosshair;
private Rect crosshairPos;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Shoot();
}
Ray ray = new Ray(transform.position, transform.forward);
crosshairPos.x = ray.GetPoint(100f).x;
crosshairPos.y = ray.GetPoint(100f).y;
Graphics.DrawTexture(crosshairPos, crosshair);
Edit: After some testing, I am currently on the following snippet of code:
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Shoot();
}
Ray ray = new Ray(transform.position, transform.forward);
crosshairPos.x = ray.GetPoint(5f).x;
crosshairPos.y = ray.GetPoint(5f).y;
crosshairPos = Camera.main.WorldToScreenPoint(crosshairPos);
Vector2 crosshairPosSize = new Vector2(crosshair.width, crosshair.height);
Graphics.DrawTexture(new Rect((Vector2)crosshairPos, crosshairPosSize), crosshair);
}
I am however still unable to see a projected crosshair.
When you use a Ray from a GameObject you get a Vector in the world coordinate system. (The game world where your player is).
Graphics.DrawTexture() uses screen coordinates to draw the texture on screen.
Consider using Camera.Main.WorldToScreenPoint to change the world points that you get from Ray into points you can display on screen.
Here's an example of that
Vectors crosshairPos = new Vector3();
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Shoot();
}
Ray ray = new Ray(transform.position, transform.forward);
crosshairPos.x = ray.GetPoint(100f).x;
crosshairPos.y = ray.GetPoint(100f).y;
crosshairPos = Camera.Main.WorldToScreenPoint(crosshairPos);
Graphics.DrawTexture((Vector2)crosshairPos, crosshair);
}

C# unity Changing a variable using ray cast hit information

The camera in this game has a target that can be changed by clicking on the other models and will then be the cameras focus, the script below is what I got so far however every time I click on an object in game the target just says none rather than any of the models.
Ray toMouse = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool didHit = Physics.Raycast(toMouse, out hitInfo);
if (didHit)
{
if (hitInfo.collider.tag == "Cell" && Input.GetMouseButtonDown(0))
{
Debug.Log("Cell hit");
target = hitInfo.transform.Find(gameObject.name);
}
}
If this script is on the camera, something like this should do it:
GameObject target;
// or
Transform target;
void Update()
{
if(Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hit))
{
target = hit.transform.gameObject;
// or
target = hit.transform;
}
}
}

Unity calculate 3D Mouse position

I'm trying to make a C# script for a free throw ball game and need to get the mouse position in the world, and it should be in 3D to be able to throw in all 3 axes. I'm kinda new to scripting and the script I wrote works, but not right. I am not sure how to get the depth or the y axis working, because the screen is only 2d .
using UnityEngine;
using System.Collections;
public class ShootBall : MonoBehaviour {
private Rigidbody rb;
private RaycastHit hit;
private Vector3 com;
private Vector3 shootDirection;
void Start () {
rb = GetComponent<Rigidbody>();
}
void Update () {
}
void OnMouseDown (){
com = rb.worldCenterOfMass;
Debug.Log (com);
}
void OnMouseDrag (){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.Log(ray);
Physics.Raycast(ray, out hit);
}
void OnMouseUp (){
shootDirection = com - hit.point;
rb.AddForce (shootDirection * 100);
}
}
The distance from the camera needs to be set on the z-value of the vector being passed into ScreenPointToRay. The reason why Input.mousePosition works as a parameter for ScreenPointToRay is because Vector2 can be implicitly cast to Vector3. So try doing something like this:
float distanceFromCamera = Vector3.Distance(ballGameObject.transform.position, Camera.main.transform.position);
Vector3 inputPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, distanceFromCamera);
Ray ray = Camera.main.ScreenPointToRay(inputPosition);
ballGameObject is the gameObject reference to the ball that will be thrown.

Categories