Some background: My camera is set to a position of 5 in the y axis and -10 in the z axis with a rotation of 22.5.
Does the position and rotation of the camera affect how accurate the raycasting behaviour will be? I ask because there are clickable objects in my scene which detect if they've been clicked on, and it more or less works. I mean it works, but it's not perfect.
If I click somewhere on the object, it's likely to register the click, but if I go to test the boundaries, something interesting occurs. There is an area of several pixels under the object which registers a click even though it isn't physically a part of the object. Likewise, there is an area of several pixels on the top of the object (within the object) which does not register a click even though it is a part of the object. Does this have something to do with the angle formed by the ray between the camera and the screen point? My project is more or less bare, so I'm pretty certain that the issue must be caused by the camera's transform and my click script which is really simple at the moment.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform == gameObject.transform)
{
Debug.Log(gameObject.name);
}
}
}
}
Related
Are there any built-in means to compute an intersection, corresponding to a ray, representing mouse pointer (or touching finger) with some object in the scene?
For example, if I have a sphere, can I compute UV coordinates on it (without writing math myself)?
If you have a mesh than there is a UV property on it already. As far as sending a raycast out from where the user clicks / touches, you will need to do a little bit of work yourself.
RaycastHit hit;
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit)) {
Transform objectHit = hit.transform;
// Do something with the object that was hit by the raycast.
}
I pulled that chunk of code from the Unity docs.
If you need the exact location of the ray hit on the object, than you can use hit.point (docs for hit.point)
I guess you are looking for this https://docs.unity3d.com/ScriptReference/RaycastHit-textureCoord.html
I've tried Atan2, I've tried whatever is euler angles, I've tried everything Unity3d's site, and I get three results:
I can move my mouse slowly, I can move it at the speed of light, the rotation of the player is fixed, either looking up, or down.
The player rotates, not looking at the mouse though. It's as though it's doing it's own thing.
It rotates on anything but the z axis.
I'm completely out of ideas, completely out. I've tried everything, including downloading several slither.io knockoff projects to figure out how they accomplish the task, but none of them work.
If you're having trouble grasping what I need to achieve, well, I have no code at this moment. But there's a website with the same thing I'm trying to accomplish.
Play surviv.io Look at how the player rotates in accordance with the mouse. That's what I'm trying to accomplish.
I didn't test this, but....
The code below should work if you have a background screen that can be raycasted against so the ray collides with it. Then play around a bit with the coordinates in the Transform.LookAt().
Basically it does these steps.
1 - Fire a ray from the screen to the mouse position, save a reference to whatever is hit in the 'Hit' variable.
2 - If anything was hit, rotate the players transform to look where it hit.
public LayerMask RaycastCollidableLayers;
public RaycastHit Hit;
public float CheckDistance = 200f;
public Transform Player;
void PerformRaycast(){
//Set up ray
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//Fire ray
Physics.Raycast(ray, out Hit, CheckDistance + 0.1f, RaycastCollidableLayers);
if (Hit.collider == null)
{
//Debug.Log("Raycast hit nothing");
return;
}
else //Ray hit something
{
//Look at Hit.point on x and y axes.
Player.LookAt(new Vector3(Hit.point.x, Hit.point.y, 0f), Vector3.up); //Ignoring z axis, may need to be another axis. Vector3.up sets the up direction.
}
}
Sources:
Transform.LookAt: https://docs.unity3d.com/ScriptReference/Transform.LookAt.html
Camera.ScreenPointToRay: https://docs.unity3d.com/ScriptReference/Camera.ScreenPointToRay.html
Let me know how it works for you.
Now, I have an object wherein I only know the x and z location. If I place it at a very high y coordinate, I would get an animation of it falling down towards the ground. I want to skip this and instantly make it be on the ground. How do I do that?
Place the object at an arbitrary Y-position well above the ground, then cast a ray down to the ground and move the object to the hit position.
Pseudo-code:
transform.position.y = 200f;
if (Physics.Raycast(transform.position, -Vector3.up, out hit)) {
transform.position = hit.transform.position;
}
You could use Raycast or Boxcast to determine the distance from the bottom of your object to the next collider below it. Then just subtract this distance from the objects transform.position.y.
I am creating a 3rd person action game where the player is a helicopter and he can shoot other objects while moving. The problem is I am trying to find the enemy objects who are inside a circle in the center of the camera and I need to track them and shoot them.
Raycast wouldn't help as i need a thicker raycast and so I tried spherecast and capsulecast.
I have a GUI element which gives the player idea on where he can shoot.When using Spherecast or Capsulecast, It is working when the enemy is near but when the enemy is far behind I guess the spherecast becomes small while traveling along z and doesn't hit the object most times.
if (Physics.SphereCast (startPoint, 1f, transform.forward, out hit)) {
if (hit.collider.CompareTag ("Shootable") ){
Debug.Log(hit.collider.name);
Destroy(hit.collider.gameObject);
}
}
I have seen raycast from camera and so i was wondering if there is something to do like circlecast from the camera which would be appropriate for this. If not how can I proceed?
Any help is really appreciated.
If you want to detect whether enemies lie within a conical area in front of your camera, using a SphereCast or RayCast will not be able to meet your needs.
Instead, you might consider checking the angle between an enemy's relative position and your camera's forward vector, to see if it is below a particular value, and hence within the cone.
For a 60-degree field of view, and assuming you store your enemy Transform components in an array/List, your code might look like:
foreach (Transform enemy in enemies){
if (Vector3.Angle(transform.forward, enemy.position - transform.position) < 30){
Destroy(enemy.gameObject);
}
}
Hope this helps! Let me know if you have any questions. (Answer adapted from this Unity question.)
Looking at various bulletin boards, this is a common problem, yet I could not find any good answers online.
My project has a first-person car that moves via the arrow keys. I want a gun mounted on the car to be able to shoot via crosshair that can aim anywhere on the current screen. Right now the bullets just shoot right through the middle all the time, except for the times when I click on the screen and nothing happens (which is about 50%). Here is the code which I got via various scripts on the web:
var speed = 20;
var bullet: GameObject;
function Update () {
var hit : RaycastHit;
if(Input.GetButtonDown("Fire1")){
var ray = Camera.main.ScreenPointToRay (Input.mousePosition); //ray from
// through the mousePosition.
if(Physics.Raycast(ray, hit, 1000)) { //does the ray collide with
// anything.
//add stuff here for finding type of object and such.
Debug.Log("Hit Something at mouse position");
Debug.DrawRay (ray.origin, ray.direction * 10, Color.yellow);
//Display the ray.
var projectile:GameObject = Instantiate(bullet,transform.position,transform.rotation);
projectile.rigidbody.velocity = transform.forward * speed;
}
}
}
If anyone could help, it would be very much appreciated.
Your ray is correct (pointing to middle of screen), but it has nothing to do with the way your making the bullet travel. The bullet travels based on a transform.forward * speed. What you need to do is get the hit point of your ray, then get a direction from your bullets origin to that point.
Vector3 direction = hit.point - projectile.transform.position;
projectile.rigidbody.velocity = direction * speed;
1000 is pretty low for a screenPointToRay, so you might want to up that by a lot if you want to avoid future problems.
Also rigidbody has been deprecated, im not sure if you should be doing a (GameObject).rigidbody directly like that
http://docs.unity3d.com/ScriptReference/GameObject-rigidbody.html
Without actually posting you any code, I can tell you that what you should probably be looking into is why your projectile is setting its rotation from the transform's rotation instead of the rotation of your ray if I understand your attempt.
The projectile is clearly gaining all of it's properties (including those which are supposed to be detached from the origination) from the vehicle and just following along accordingly.
Try setting your projectile's rotation to that of your ray.
Also, your ray is more than likely only ever hitting half of the time because of your amount of distance to test. Try upping that number, or creating walls for it to collide with at shorter range.