Raycast2D not detecting Rigidbody2D - c#

I have a box that fires a 2D raycast forward every few seconds, and want it to detect the player's rigidbody2D. I am able to get the raycast firing (the debug draws it correctly), but for some reason it is not detecting the player's rigidbody2D component.
void Shoot()
{
// convert this object's Rigidbody2D [_rb] rotation to radians
float rad = _rb.rotation * Mathf.Deg2Rad;
// use some math I found who-knows-where to make a Vector2 projecting forward
Vector2 firingAngle = new Vector2(Mathf.Cos(rad), Mathf.Sin(rad));
// project a 2D raycast from the position of the Rigidbody2D out to [range]
RaycastHit2D hit = Physics2D.Raycast(_rb.position, firingAngle, range);
if (hit.rigidbody != null)
{
// **This part of the code never runs, even if the player is clearly intersecting the raycast.**
Debug.DrawRay(this.transform.position, firingAngle*hit.distance, Color.yellow, 1f);
Debug.Log("Hit");
} else {
// **Instead, this part always runs.**
Debug.DrawRay(this.transform.position, firingAngle*range, Color.white, 1f);
Debug.Log("Did not hit");
}
}

Make sure when doing raycasts against GameObjects with a Rigidbody or Rigidbody2D component, that there is also a corresponding Collider or Collider2D component (either on the GameObject itself, or one of its children).
Otherwise, raycasts and collision events won't trigger.

Related

unity : rotating a gun 360 dgrees around the player in a 2d platfrom shooter

trying for 2 days to rotate a gun around a player in a 2d platfromer and i have 3 problems
1: the item or rotate uncontrolebly (my grammer isnt the best my mother language isnt even latin base)
around the player even if i dont move my mouse .or its rotate on its self like a wheel.
2:its seems phisycs some how work on the gun even though its dosnt has a rigibid body. givin in rb on kinimatic halped but not fully.
3: its rotate way to quickly . little movment will cause it to fly
4(bonus) the sqauer module i gave it strach and band in a really weird way.
heres the code:your text
[SerializeField] float fireRate = 0.3f;
[SerializeField] float rocketSpeed = 20f;
[SerializeField] GameObject rocketType;
[SerializeField] Transform firePoint;
Player player;
Vector3 mousePos;
Camera mainCam;
void Start()
{
player = FindObjectOfType<Player>();
mainCam = FindObjectOfType<Camera>().GetComponent<Camera>();
}
// Update is called once per frame
void Update()
{
mousePos = mainCam.ScreenToWorldPoint(Input.mousePosition);
}
private void FixedUpdate()
{
Vector3 aimDirection = mousePos - transform.position;
float aimAngle = Mathf.Atan2(aimDirection.y, aimDirection.x) * Mathf.Rad2Deg ;
// Quaternion rotation = Quaternion.AngleAxis(aimAngle, Vector3.forward);
// transform.rotation = rotation;
transform.rotation = Quaternion.Euler(0, 0, aimAngle);
// transform.RotateAround(player.transform.position, Vector3.forward, aimAngle);
}
here a picture of the componets:
enter image description here
wanted a gun obj to rotate around my charcter whan its move or still, wanted to shoot stuff while i jump.
Mathf.Atan2 returns the value in Radians, but Quaternion.Euler uses Degrees. You'll have to multiply the value by Mathf.Rad2Deg first.
It also sounds like the parent of the gun has a rigidbody which is causing it to Rotate. Remove the rigidbody you put on the gun and toggle on "Freeze Rotation" on the parent's rigidbody.

Conflicting IF statements in Unity C# , Soccer Game

I am a starter in Unity and developing a soccer game. I have a problem ,my IF statements conflict each other. Let me explain it in detail.
In order for a ball to stick to player, I have used IF operator, so whenever the distance between the player and the ball is less than < 0.5 , the ball sticks to player and move together with it. Now when I try to set up shooting the ball (I try with "addforce") it doesnt let me, cause the ball is still attached to player and distance is <0.5.
This one is the balls script.
public bool sticktoplayer;
public transform player;
//gameobject Player is attached
float distancetoplayer;
Rigidbody rb;
//balls rigidbody
void Awake ()
{
rb = getComponent<Rigidbody>();
}
void Update()
{
If (!sticktoplayer)
{
float distancetoplayer = Vector3.Distance (player.position, transform.position);
if(distancetoplayer < 0.5f)
{
sticktoplayer = true;
}
}
else
{
transform.position = player.position;
}
if(Input.GetKeyDown(KeyCode.Space))
{
rb.addforce(20, 0, 0, ForceMode.Impulse);
sticktoplayer = false;
}
When the player is not controlling the ball the force is succesfully applied to the ball, but when the ball is attached (distancetoplayer<0.5) then the other IF statements blocks it from shooting.
Maybe there are some work arounds ? Thanks.
I tried to make another if statement.
why dont you try sticking the ball to the player by collision? instead of checking the distance, create a collider with the radius or scale you desire and whenever the ball is inside the collider (when it triggers with the collider) stick it to the player. Because you will not be able to let the ball go since the ball will always be less then 0.5f away from the player once it sticks
have you tried it this way?
if(Input.GetKeyDown(KeyCode.Space))
{
sticktoplayer = false;
rb.addforce(20, 0, 0, ForceMode.Impulse);
}

Rigidbody2D.MovePosition cause lags in physic, for example, gravity

I tested and this script cause lags in physic. It seems to me that it call physic not per 0,2 seconds, but much-much more rarely and because of this object falling much more slower.
Here's a gif to demonstrate what happens: The purple one without script, the blue one with script.
So how can I fix that?
public class PlayerMovement : MonoBehaviour
{
Rigidbody2D rb;
Vector2 movement = new Vector2(0, 0);
public float movementSpeed = 10f;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
movement = new Vector2(Input.GetAxisRaw("Horizontal"), 0);
}
void FixedUpdate()
{
rb.MovePosition(rb.position + movement * movementSpeed * Time.fixedDeltaTime);
}
}
As said MovePosition overrules the movement => don't use it if you want physics (force) based movements and reaction to collisions etc.
You want to use the input only for the horizontal movement but use physics for the vertical. MovePosition affects both directions.
Try directly setting the Rigidbody.velocity instead
private void Update()
{
// Get the current velocity
var velocity = rb.velocity;
// Only overwrite the x velocity
// since the velocity is only applied in the FixedUpdate anyway
// there is no problem setting this already in Update
// And since it is the velocity which is already frame-rate independent
// there is no need for Time.deltaTime
velocity.x = Input.GetAxisRaw("Horizontal") * movementSpeed;
// Assign back the changed velocity
rb.velocity = velocity;
}
There is an issue with the logic of your code if I understand what you want to do.
You seem to be moving in a vertical fashion yet only have the x component of your vector2 from the horizontal input.
new Vector2(Input.GetAxisRaw("Horizontal"), 0);
If the GIF you attached, the object is just in freefall, so that would be a vertical drop, or the y component of the vector2, which you are setting to 0. Think of this as (x,y) or (move horizontally (left/right), move vertically (up/down)).
I would change the above line to:
movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
You can now move vertically using vertical input. Something else which would not cause your issue, but is mentioned on the MovePosition docs is to mark your Rigidbody2D as Interpolate. It is the bottom field in the Rigidbody2D component labeled Interpolate, set it from None to Interpolate.
The reason your object is moving slowly without any input is because you still have your Gravity Scale on the Rigidbody set to 1 instead of 0. If you are trying to simulate gravity with this script, add the vertical component to your input vector and set the Gravity Scale field on the Rigidbody to 0. The MovePosition is fighting the current gravity attempting to affect it.

Ricochets dоn't wоrk prоperly

Hi I want to make ricochet for my bullet. But when my bullet collides with a wall, bullet starts to fly along wall:
What did I do wrong? Here are my code parts:
public Rigidbody2D rb;
Vector2 m_dir;
private void Start()
{
m_dir = rb.GetRelativeVector(Vector2.right);
rb.velocity = m_dir * speed;
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "Wall")
{
Vector2 _wallNormal = col.contacts[0].normal;
m_dir = Vector2.Reflect(rb.velocity, _wallNormal).normalized;
Debug.Log("Collide!"); // debug works
rb.velocity = m_dir * speed;
}
}
Bullet Inspector - CircleCollider2D + Rigidbody2D. Wall Inspector - BoxCollider2D + Rigidbody 2D (Kinematic)
First of all:
The default behavior in Unity physics should already ricochet the bullet from the wall without your help.
As the bullet collider is round, it should not fly in a random direction.
What causes your problem:
The problem you have, seems to come from the order in which the methods are called.
Basically unity physics first resolves the collisions for this physics frame, and afterwards calls all the OnCollisionEnter methods. (More information)
This causes your rb.velocity to already be the ricochet velocity.
When you now calculate the reflect angle with the velocity pointing away from the wall, you get an inward pointing velocity.
In essence, your bullet keeps on ricocheting from the wall, but you change direction back to the wall in every frame.
How to solve it:
Use the Collision2d.relativeVelocity instead of rb.velocity.
This is the velocity that was recordet at the time of impact instead of the changed one.
Note: As it is relative to an unmoving object, you get the absolute velocity.
m_dir = Vector2.Reflect(rb.velocity, _wallNormal).normalized;
becomes
m_dir = Vector2.Reflect(-col.relativeVelocity, _wallNormal).normalized;

Player animation don't trigger if bool changed from value

I'm following the Player Character tutorial on the Unity site. There say that the player can move, idle or can be dead. Here is the situation in the 'Animator' panel:
The parameters are:
IsWalking type of bool
Die type of trigger
The normal situation is when the IsWalking parameters is true, he must begin whit walking. When false, he must stop. Here are some screenshots.
And here is the C# script I've made:
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 6f; // The speed that the player will move at.
Vector3 movement; // The vector to store the direction of the player's movement.
Animator anim; // Reference to the animator component.
Rigidbody playerRigidbody; // Reference to the player's rigidbody.
int floorMask; // A layer mask so that a ray can be cast just at gameobjects on the floor layer.
float camRayLength = 100f; // The length of the ray from the camera into the scene.
void Awake()
{
// Create a layer mask for the floor layer.
floorMask = LayerMask.GetMask("Floor");
// Set up references.
anim = GetComponent<Animator>();
playerRigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
// Store the input axes.
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
// Move the player around the scene.
Move(h, v);
// Turn the player to face the mouse cursor.
Turning();
// Animate the player.
Animating(h, v);
}
void Move(float h, float v)
{
// Set the movement vector based on the axis input.
movement.Set(h, 0f, v);
// Normalise the movement vector and make it proportional to the speed per second.
movement = movement.normalized * speed * Time.deltaTime;
// Move the player to it's current position plus the movement.
playerRigidbody.MovePosition(transform.position + movement);
}
void Turning()
{
// Create a ray from the mouse cursor on screen in the direction of the camera.
Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
// Create a RaycastHit variable to store information about what was hit by the ray.
RaycastHit floorHit;
// Perform the raycast and if it hits something on the floor layer...
if (Physics.Raycast(camRay, out floorHit, camRayLength, floorMask))
{
// Create a vector from the player to the point on the floor the raycast from the mouse hit.
Vector3 playerToMouse = floorHit.point - transform.position;
// Ensure the vector is entirely along the floor plane.
playerToMouse.y = 0f;
// Create a quaternion (rotation) based on looking down the vector from the player to the mouse.
Quaternion newRotation = Quaternion.LookRotation(playerToMouse);
// Set the player's rotation to this new rotation.
playerRigidbody.MoveRotation(newRotation);
}
}
void Animating(float h, float v)
{
// Create a boolean that is true if either of the input axes is non-zero.
bool walking = h != 0f || v != 0f;
// Tell the animator whether or not the player is walking.
anim.SetBool("IsWalking", walking);
}
}
The problem is now, when I'll walk whit the player he stays in the idle state. It's sometimes that he goes to the move state, but not always. What is the problem here I've got? I've exactly the same code and animations I've made in the animator and inspector tabs.
You should try setting ExitTime to false.
When on, it means the animation will still be played by the ExitTime value. So for instance if ExitTime is 1, the whole idle animation has to be finished before it transits. If you stop moving within that time, then the boolean is back to idle and you won't see the animation for walking. Setting it to false means you want transition to happen instantly.

Categories

Resources