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.
Related
I need my unit to move to the enemy when i clicking mouse on enemy and destroy when my unit touch him
For moving i use navmesh and raycast hit
All units have navmesh agent
Enemies moving by points
Lot of ways to do that: i give you the global idea and you adapt to your script
i have set layer for enemy to "enemy" just to be sure to chase a clicked enemy. layer enemy = 8 in my sample
3 phases:
First phase: Click detection and trap the gameobject clicked
private bool chasing = false;
public Transform selectedTarget;
if (Input.GetMouseButtonDown(0))
{
//Shoot ray from mouse position
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach (RaycastHit hit in hits)
{ //Loop through all the hits
if (hit.transform.gameObject.layer == 8)
{ //Make a new layer for targets
//You hit a target!
selectedTarget = hit.transform.root;
chasing = true;//its an enemy go to chase it
break; //Break out because we don't need to check anymore
}
}
}
Second phase: chase the enemy. so you have to use colliders and at least one rigidbody, you have plenty of tutorial which explains how to detect collision.
if (chasing)
{
// here i have choosen a speed of 5f
transform.position = Vector3.MoveTowards(transform.position, selectedTarget.position, 5f * Time.deltaTime);
}
Destroy on Collision with OnCollisionEnter (or InTriggerEnter)
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "enemy")
{
Destroy(col.gameObject);
}
}
The given code is for 3d game, if you are using a 2d game, just adapt the code to 2D, no difficulties to do that .
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.
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);
}
}
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.
I have a Ball(sphere) and a floor in my game scene. Ball.cs is attached to the ball to control its movement in the game(Ball only moves in the vertical direction). Both Ball and floor have colliders attached to them and whenever ball touches the floor, the game should ideally end.
OnCollisionEnter2D Method from the Ball.cs script.
private void OnCollisionEnter2D(Collision2D collision)
{
// Zero out the ball's velocity
rb2d.velocity = Vector2.zero;
// If the ball collides with something set it to dead...
isDead = true;
//...and tell the game control about it.
GameController.instance.PlayerDied();
}
Update function
void Update () {
//Don't allow control if the bird has died.
if (isDead == false)
{
//Look for input to trigger a "flap".
if (Input.GetMouseButtonDown(0))
{
//...zero out the birds current y velocity before...
rb2d.velocity = Vector2.zero;
// new Vector2(rb2d.velocity.x, 0);
//..giving the bird some upward force.
rb2d.AddForce(new Vector2(0, upForce));
}
}
}
But what's happening is whenever ball touches the ground, it starts rolling on the ground. It moves few units on +X-axis then rolls back and then ultimately stops.
position.X should ideally be 0(as the ball is moving only in Y-axis and it is during the game) but as soon as ball collides with the floor it starts moving.
I am new to Unity and I have no idea what is wrong.
Why is this happening?
EDIT:
Programmer's answer does work but I still don't understand where the horizontal velocity is coming from(there is horizontal velocity component associated with the ball). I need to know why ball is moving in horizontal direction.
I noticed that you are setting isDead to true when collision happens. If you don't want the ball to move again then set velocity to Vector2.zero; in the Update not only in the OnCollisionEnter2D function. Do this only if isDead is true.
void Update()
{
if (isDead)
{
rb2d.velocity = Vector2.zero;
}
}
Another option is to freeze the constraints when the collision happens. If you want the ball to start rolling again then unfreeze it.
private void OnCollisionEnter2D(Collision2D collision)
{
//Zero out the ball's velocity
rb2d.velocity = Vector2.zero;
//Freeze constraints
rb2d.constraints = RigidbodyConstraints2D.FreezeAll;
// If the ball collides with something set it to dead...
isDead = true;
//...and tell the game control about it.
GameController.instance.PlayerDied();
}
Execute rb2d.constraints = RigidbodyConstraints2D.None; to unfreeze it after.