Raycast 2d is not working in Unity3d - c#

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

Related

Instantiate a prefab pointing in the direction of another object

The Issue
I'm making a 2D Unity game where the main weapon of your character is a fireball gun. The idea is that a fireball will shoot out of the player's hand at the same angle the player's hand is pointing. I have 3 issues:
When I shoot the fireball, since the fireball is a RididBody, it pushes the player. This is because I've made the centre of the player's arm (the same place where the fireball shoots from) the point at which the arm rotates around the player (what is meant to be the shoulder);
To instantiate the fireball prefab on the arm, the only way I know how to do it is by using a piece of code which requires the arm to be a RigidBody. This means that the arm is affected by gravity and falls off the player on start unless I freeze the arm's y-axis movement, which means that when the player jumps, while the arm does not fall, it floats at the same y-position as where it started while moving along the x-axis; and
When the fireball is shot, the angle from which it is propelled after being shot is not the same angle as the angle of the player's arm.
Instantiating the Fireball
if (Input.GetKeyDown(KeyCode.Space))
{
pew.Play();
var fireballTransform = Instantiate(fireballPrefab); //creates a new shot sprite
fireballTransform.position = new Vector3(transform.position.x + horizMultiplier, transform.position.y, transform.position.z);
fireballTransform.rotation = orientation;
fireballTransform.transform.Rotate(0, 0, transform.rotation.z);
}
if (Input.GetKeyDown(KeyCode.D)) // moves right
{
orientation = 0;
horizMultiplier = 0.08F;
}
if (Input.GetKeyDown(KeyCode.A)) // moves left
{
orientation = 180;
horizMultiplier = -0.08F;
}
This piece of code is located within the script applied to the player's arm. The movement of the arm works fine and the problem seems to be either within this piece of code or the code for my fireball (which I will put next). A few definitions:
pew is a sound effect played when the fireball is shot;
horizMultiplier is the distance from the arm's centre which I would like the fireball to instantiate (also dependant of if the player) is facing left or right); and
orientation is which direction the player is facing (left or right). The fireball is then instantiated facing that same direction.
Fireball Script
public Vector2 speed = new Vector2(); // x and y forces respectively
private Rigidbody2D rb; // shorthand
private float rotation;
void Start()
{
rb = GetComponent<Rigidbody2D>(); // shorthand
rotation = rb.rotation;
if (rotation == 0)
{
rb.AddForce(Vector3.right * speed.x); // propels right
}
if (rotation == 180)
{
rb.AddForce(Vector3.left * speed.x); // propels left
}
}
I believe this code is explanatory enough with comments (if not please comment and I'll address any question). I believe an issue could also be in this piece of code because of the lines: rb.AddForce(Vector3.right * speed.x); and rb.AddForce(Vector3.left * speed.x); as these add directional forces to the object. I don't know is this is objective direction (right or left no matter what direction the object the force is being applied to is facing) or if it's right or left in terms of the object-- say if an object was rotated 90 degrees clockwise and that object had a force applied so that it moves right making the object move downwards.
What I'm expecting to happen is the player's arm will turn so that when a fireball is fired it is fired in the direction the arm is facing. The arms turning mechanics are fine, it's just trying to properly instantiate the fireball. Can anyone help with any of the issues I've laid out?
How I would go about this:
Add an empty transform as child of the arm and move it to where the fireball should spawn. Also make sure the rotation of it is such that its forward vector (the local z-axis) points to where the fireball should go. To see this, you need to set "Local" left of the play button.
Spawn the fireball at the transform's position with its rotation.
Ignore collision between the arm's/player's collider and the fireball's collider with https://docs.unity3d.com/ScriptReference/Physics.IgnoreCollision.html. If necessary, you can enable the collision between the two colliders again after 1s or so.
Set the fireball rigidbody's velocity to speed * rigidbody.forward.
If you need help with the code, please post it so I can see what's going on.
Edit:
The arm definitely doesn't require a Rigidbody.
You can just use Instantiate(prefab, position, rotation) as shorthand.
Is this for a 2D game?
Also, I'm going to sleep now but I'll gladly try to help tomorrow.
Your Issues
1) You should be masking the fireball's layer not to collide with your player's layer.
You can find more info about this here: https://docs.unity3d.com/Manual/LayerBasedCollision.html
(note: make sure you're on the Physics2D panel, and not the Physics one, as that's for 3D)
2) There is a setting called gravityScale in RigidBody2D. You should set this to 0 if you don't want gravity to be affecting your object. More info: https://docs.unity3d.com/Manual/class-Rigidbody2D.html
Fireball Instantiate
if (Input.GetKeyDown(KeyCode.Space))
{
pew.Play();
var position = hand.transform.position + hand.transform.forward * horizMultiplier;
var rotation = hand.transform.rotation;
var fireball = Instantiate<Fireball>(fireballPrefab, position, rotation);
fireball.StartMoving();
}
Fireball Script
private Rigidbody2D rb; // shorthand
private float rotation;
public float Speed;
public void StartMoving()
{
rb = GetComponent<Rigidbody2D>(); // shorthand
rb.velocity = transform.forward * Speed;
}
void OnTriggerEnter(....) { .... }

Checking for Collisions with Raycasts - Collider not being registered when it clearly should be

I'm trying to implement player movement such that the player can't collide with other collidable objects, such as tiles, but the recasts I'm using aren't registering any other collider when it clearly should be
So the problem I'm trying to solve is to check if there is a collision with a raycast that extends exactly how far the player will move, and get information on the object that was collided with. After that, I would adjust the player's movement accordingly so that the player is not colliding with the object after the raycast finds such a collidable. Here is the source code:
// Move body towards a certain direction, by a certain value
protected void MoveBody(Vector3 direction, float speed)
{
Vector3 newPos = transform.position + (direction * speed * Time.deltaTime);
//int layerMask = 1 << 8; // bit sequence 1000 0000 - Only 'collidable' layer
RaycastHit hit;
Vector3 ySize = new Vector3(0, GetComponent<BoxCollider2D>().size.y/2, 0);
Vector3 startPos = transform.position - ySize;
if (Physics.Raycast(startPos, direction, out hit, speed * Time.deltaTime))
{
Debug.DrawRay(startPos, direction * speed * Time.deltaTime, Color.yellow);
Debug.Log("Did Hit");
}
else
{
Debug.DrawRay(startPos, direction * speed * Time.deltaTime, Color.yellow);
Debug.Log("Did Not Hit");
}
// Update gameObject's transform.position here based on whether a collidable was found
}
When I run the game, the first frame ensures that the raycast is colliding with another box collider, as shown by this image:
The expected Debug.Log would be "Did hit", but it's logging "Did not hit". The yellow line shows the full raycast, and it's clearly intersecting the box collider of the tile below the purple man.
The MoveBody function is being run each frame to simulate gravity (I omitted the part where the object falls so the player object just stays in place for the entire time), but as you can see, the raycast never registers a collision. Both player and tile1 have a box collider, so I don't understand what's going on. Would really appreciate any help I can get!!! Thanks!
The problem was that I was using Physics.Raycast, but I should have been using Physics2D.Raycast, as my Unity game is in 2D. Physics.Raycast isn't compatible with 2D Unity games.

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.

Unity 2D C# - Collider not working

I am working on a 2D TopDown game in Unity 5. The collision is not working at all.
The player and the obstacle both have a 2D Collider and they are not Trigger. The player has a 2D Rigidbody with Kinematic set to false, gravity scale is equal to zero. Maybe the movement code has something to do with it.
The code is a bit long so I'll just show you the code for moving up:
if (Input.GetAxis ("Up") > 0) {
if (movingDown == false) {
posY += speed * Time.deltaTime;
movingUp = true;
}
} else {
movingUp = false;
}
/.../
transform.position = new Vector3 (posX, posY, 0);
It is always setting the value of the position as long as you are pressing the up button. Is there a way to fix this?
I think that the problem is that you are setting the position directly. So at each frame, you are telling unity exactly were the object should be, which overrides the position that would be computed from collision.
To fix this, you need to modify your movement code to add a force to your rigidbody and leave the position untouched ( see rigidbody doc, and function AddForce (https://docs.unity3d.com/ScriptReference/Rigidbody.html)
Try using
rb.velocity = new Vector3 (rb.velocity.x, rb.velocity.y, ConstantZValue);
This replaces your system with a velocity-based system as updating the transform.postition of a rigidbody is not recommended. With the system you have, the collision is not being detected because the rigidbody isn't being updated.

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