C# unity Changing a variable using ray cast hit information - c#

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

Related

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

Raycasting from the camera center doesn't work

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.

Referencing a GameObject Tag through Validation in Unity C#

I'm working on a project where you have to move boxes by dragging them. But right now all objects can move and not just boxes. I'm trying to use validation through tags to get this working, but can't quite figure it out. This is my validation code.
{
//Mouse Button Press Down
if (Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo;
getTarget = ReturnClickedObject(out hitInfo);
if (getTarget != GameObject.tag("Box"))
{
isMouseDragging = true;
//Converting world position to screen position.
positionOfScreen = Camera.main.WorldToScreenPoint(getTarget.transform.position);
offsetValue = getTarget.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, positionOfScreen.z));
}
}
//Mouse Button Up
if (Input.GetMouseButtonUp(0))
{
isMouseDragging = false;
}
//Is mouse Moving
if (isMouseDragging)
{
//tracking mouse position.
Vector3 currentScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, positionOfScreen.z);
//converting screen position to world position with offset changes.
Vector3 currentPosition = Camera.main.ScreenToWorldPoint(currentScreenSpace) + offsetValue;
//It will update target gameobject's current postion.
getTarget.transform.position = currentPosition;
}
}
//Method to Return Clicked Object
GameObject ReturnClickedObject(out RaycastHit hit)
{
GameObject target = null;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction * 10, out hit))
{
target = hit.collider.gameObject;
}
return target;
}
if anyone can figure out how to help me it would be greatly appreciated.

Rotating an object at which I am looking (ARFoundation)

2 items are placed in AR. i would like to rotate 1 of those items while its in the middle of the screen (using touch controls and Raycast).
I would like all the rotation part of the code to be executed when the camera is looking at the object.
this is the script i use on an object placed in the scene, the Move function works since that is only activated when you tap on the screen where the object is and drag it away (Raycast to a Collider). however my rotation works on all objects in the scene when i swipe anywhere because if i swipe on the collider i move the object, so for rotation i have to stay outside that collider.
public class MoveObject : MonoBehaviour
{
public bool holding;
private Component rotator;
int doubleTap = 0;
void Start()
{
holding = false;
}
void Update()
{
if (holding)
{
Move();
}
// One finger
if (Input.touchCount == 1)
{
// Tap on Object
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
RaycastHit hitTouch;
if (Physics.Raycast(ray, out hitTouch, 100f))
{
if (hitTouch.transform == transform)
{
holding = true;
}
}
}
// Release
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
holding = false;
}
}
if (Input.touchCount == 1 && !holding) //THIS is the rotation part
{
// GET TOUCH 0
Touch touch0 = Input.GetTouch(0);
// APPLY ROTATION
if (touch0.phase == TouchPhase.Moved)
{
transform.Rotate(0f, touch0.deltaPosition.x * 0.5f, 0f);
}
}
}
void Move()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
// The GameObject this script attached should be on layer "Surface"
if (Physics.Raycast(ray, out hit, 30.0f,
LayerMask.GetMask("Surface")))
{
transform.position = new Vector3(hit.point.x,
transform.position.y,
hit.point.z);
}
}
}
You'll probably want another flag similar to holding to make sure that you don't rotate an object the center of the screen passes over during a swipe, such as when the camera is moving and the object passes through the center of the screen.
You can use Camera.ViewportPointToRay with input of new Vector3(0.5f, 0.5f, 0) to create a ray coming from the center of the screen. From there, the process is similar to your holding code.
Also, with a little rearranging, you can re-use the raycast that is already used to check if this object was touched because it also checks if any object was touched. Only checking to start rotating when the first raycast touches nothing avoids rotating (and raycasting unnecessarily) in the situation where this object is in the center of the screen but another object was touched.
As a sidenote, it's recommended to cache the result of Camera.main because it does a FindGameObjectsWithTag internally every time you reference it and that can add up to extra computation time.
Altogether, it could look like this:
private bool rotating;
private Camera cam;
void Start()
{
holding = false;
rotating = false;
cam = Camera.main;
}
void Update()
{
// One finger
if (Input.touchCount == 1)
{
Touch touch0 = Input.GetTouch(0);
if (touch0.phase == TouchPhase.Began)
{
Ray ray;
RaycastHit hitTouch;
// test hold start
ray = cam.ScreenPointToRay(touch0.position);
if (Physics.Raycast(ray, out hitTouch, 100f))
{
if (hitTouch.transform == transform)
{
holding = true;
}
}
else // avoid rotating/raycasting again in situation
// where this object may be in center of screen
// but this or other object was touched.
{
// test rotate start
ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
if (Physics.Raycast(ray, out hitTouch, 100f)))
{
if (hitTouch.transform == transform)
{
rotating = true;
}
}
}
}
else if (touch0.phase == TouchPhase.Moved)
{
if (holding)
{
Move();
}
else if (rotating)
{
transform.Rotate(0f, touch0.deltaPosition.x * 0.5f, 0f);
}
}
// Release
else if (touch0.phase == TouchPhase.Ended)
{
holding = false;
rotating = false;
}
}
}

Categories