Unity get collision coordinate with hidden part of a plane - c#

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))
{
...
}

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

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.

Obstacle Avoidance

I'm trying to implement obstacle avoidance within steering behaviors for a university project.
When I run the project, the AI agent seems to get confused and 'spaz' out moving from left to right very quickly and still doesn't avoid obstacles correctly.
I'm trying to cast a box in front of the agent so that when that box collides with an obstacle, it'll steer away from it and continue to move wander.
Here is the code for the Obstacle Avoidance
public Vector3 ObstalceAvoidance()
{
//Cast a ray from the centre of the agent, in it's forward direction
Ray ray = new Ray(transform.position, transform.forward);
//Name a raycastHit
RaycastHit hitInfo;
//Set avoidanceForce to ZERO for all axis
Vector3 avoidanceForce = Vector3.zero;
//Calculate the 'Avoidance Force'
if(Physics.BoxCast(transform.forward, new Vector3(2.5f, 2.5f, 20.0f), transform.forward, out hitInfo, transform.rotation, maxDistance))
{
if(Vector3.Angle(hitInfo.normal, transform.up) > floorAngle)
{
//Reflect the Vector
avoidanceForce = Vector3.Reflect(agent.velocity, hitInfo.normal);
//Calculate the dot product between the Force and Velocity
if (Vector3.Dot(avoidanceForce, agent.velocity) < -0.9f)
{
//Transform Right
avoidanceForce = transform.right;
}
}
}
if(avoidanceForce != Vector3.zero)
{
//Calculate desired velocity
desiredVelocity = (avoidanceForce).normalized * agent.maxSpeed;
//Calculate the steering Force
steeringForce = desiredVelocity - agent.velocity;
oldSteeringForce = steeringForce;
forceTimer = 0;
}
else
{
steeringForce = Vector3.zero;
}
return steeringForce;
}

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

Categories