Rigidbody is being dragged back to bouncy object - unity3d

I have an object tagged "Bouncy object" that pushes my player on collision; it works but after collision, my player is like being dragged back to the object tagged "Bouncy object", then does the same thing again like a cycle. The code I used is:
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Bouncy object")
GetComponent<Rigidbody2D>().AddForce(transform.right * 38, ForceMode2D.Impulse);
}
I then set the drag on the player's Rigidbody to: 1.49. How would I stop this from happening? What I want is for the object tagged "Bouncy object" to push my player on collision (trigger) then freeze Rigidbody2D for like 2 seconds, then allows me to control my player.

Here is the code you want. I tested just now.
If Cube collide with Block, it bounce to back 0.1 sec and freeze 1 sec.
The key is '-GetComponent ().velocity'.
Here is the screenshot of editor.
public class PlayerController : MonoBehaviour {
public float force = 10f;
float speed = 5f;
float freezeTime = 1f;
bool isCollide = false;
void FixedUpdate ()
{
float dirX = Input.GetAxis ("Horizontal");
float dirY = Input.GetAxis ("Vertical");
Vector3 movement = new Vector2 (dirX, dirY);
if(isCollide==false)
GetComponent<Rigidbody2D> ().velocity = movement * speed;
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Boundary") {
isCollide = true;
GetComponent<Rigidbody2D> ().AddForce (-GetComponent<Rigidbody2D> ().velocity * force, ForceMode2D.Impulse);
Invoke("StartFreeze", 0.1f);
}
}
void StartFreeze()
{
GetComponent<Rigidbody2D> ().constraints = RigidbodyConstraints2D.FreezeAll;
Invoke("ExitFreeze", freezeTime);
}
void ExitFreeze()
{
GetComponent<Rigidbody2D> ().constraints = RigidbodyConstraints2D.None;
isCollide = false;
}
}

Related

How to jump when player is upside down in a spherical world, using FauxGravity?

What I try to do
I'm trying to get jumping working all over the sphere and not just at the top while using FauxGravity.
How it works currently
My character jumps correctly when he is on top but when he is in the bottom of the sphere the jump doesn't take place.
FauxGravityAttractor
[SerializeField] private float gravity = -9.81f;
public void Attract(Rigidbody body) {
Vector3 gravityUp = (body.position - transform.position).normalized;
Vector3 localUp = body.transform.up;
// Apply downwards gravity to body
body.AddForce(gravityUp * gravity);
// Align bodies up axis with the centre of planet
body.rotation = Quaternion.FromToRotation(localUp,gravityUp) * body.rotation;
}
FauxGravityBody
FauxGravityAttractor planet;
new Rigidbody rigidbody;
void Awake()
{
planet = GameObject.FindGameObjectWithTag("Planet").GetComponent<FauxGravityAttractor>();
rigidbody = GetComponent<Rigidbody>();
// Disable rigidbody gravity and rotation as this is simulated in GravityAttractor script
rigidbody.useGravity = false;
rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
}
void FixedUpdate()
{
// Allow this body to be influenced by planet's gravity
planet.Attract(rigidbody);
}
Sample Jumping
void Jump()
{
if(Input.GetKeyDown(KeyCode.Space) && isOnGround)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isOnGround = false;
}
}
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.CompareTag("Planet"))
{
isOnGround = true;
}
}
FauxGravity jumping problem solved
All you need to do is AddRelativeForce to your rigidbody
Read more about RelativeForce
// JUMPING
private void Jump()
{
if (Input.GetKeyDown(KeyCode.Space) && onGround)
{
rb.AddRelativeForce(0, forceConst, 0, ForceMode.Impulse);
onGround = false;
}
}

Why is there a constant stutter when i move in Unity 2d?

So i have a simple scene in unity, a player with a parallax background and a Tilemap as a ground, as well as some very simple post processing. I know this isn't a The minute i move, there is a consistent stutter just under ever second. I'm not sure whether it's to do with my player movement code, camera movement or anything else. I'm also using a Cinemachine virtual camera. My rigidbody interpolation is set to interpolate and collision detection set to continuous. Here's my player movement if this helps. Here is a sample of what it looks like, if you look at the background or the tilemap it's quite noticeable. https://youtu.be/h2rSheZWtKs
[SerializeField] private LayerMask groundLayerMask;
public float speed;
public float Jump;
public sword swordScript;
public GameObject swordSprite;
private float move;
private Rigidbody2D rb;
private BoxCollider2D boxCollider2d;
private bool facingRight;
public SpriteRenderer spr;
public Animator PlayerAnims;
public bool movementAllowed;
void Awake()
{
Application.targetFrameRate = 60;
Application.targetFrameRate = Screen.currentResolution.refreshRate;
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Start is called before the first frame update
void Start()
{
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void FixedUpdate()
{
if(movementAllowed == true)
{
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (isGrounded() && Input.GetButtonDown("Jump"))
{
rb.AddForce(new Vector2(rb.velocity.x, Jump));
}
}
}
void Update()
{
move = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (movementAllowed == true)
{
Flip(move);
if (move == 0)
{
PlayerAnims.SetBool("isRunning", false);
}
else
{
PlayerAnims.SetBool("isRunning", true);
}
}
}
private bool isGrounded()
{
float extraHeightText = .1f;
RaycastHit2D raycasthit2d = Physics2D.BoxCast(boxCollider2d.bounds.center, boxCollider2d.bounds.size, 0f, Vector2.down, extraHeightText, groundLayerMask);
Color rayColour;
if (raycasthit2d.collider != null)
{
rayColour = Color.green;
PlayerAnims.SetBool("isJumping", false);
}
else
{
rayColour = Color.red;
PlayerAnims.SetBool("isJumping", true);
}
Debug.DrawRay(boxCollider2d.bounds.center + new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, boxCollider2d.bounds.extents.y + extraHeightText), Vector2.right * (boxCollider2d.bounds.extents.x), rayColour);
return raycasthit2d.collider != null;
}
private void Flip(float move)
{
if (move > 0 && !facingRight || move < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
if (swordScript.isFollowing == true)
{
Vector3 swordScale = swordSprite.transform.localScale;
swordScale.x *= -1;
swordSprite.transform.localScale = swordScale;
}
}
}
You are setting rb.velocity in both the Update() and FixedUpdate() methods. I would try only using one of those.
On top of that, your jump check also re-applies the X velocity along with the upward force. So if you're jumping the player will be pushed forward at double speed.
You also have an error being outputted in the console about an Index being out of range... I would look into that.
Can you also post your code for the parallax background?
FixedUpdate is a method where you want to do everything physics, player-controller and simulation related.
Update is just for rendering-related fluff i.e. code of no real consequence other than making things look correctly.
Hence:
Move all your player/physics controller code to FixedUpdate.
Move bg parallax code to Update.
Use Time.deltaTime (in Update) and Time.fixedDeltaTime (in FixedUpdate) time steps when animating or interpolating between values.
Ad #3.: Although - as #Menyus noted (below) - Time.deltaTime is all you really need.
Time.fixedDeltaTime is for that extra intent explicitness (but was necessary in earlier unity versions).

How to stop the player from jumping while in the air?

I don't want my player to jump in the air but I can't seem to find anything out.
This is what I have. They can jump, but they can jump forever and that's a problem.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
public bool alive;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start () {
rigidBody = GetComponent<Rigidbody2D> ();
// Use this for initialization
}
// Update is called once per frame
void Update () {
movement = Input.GetAxis ("Horizontal");
if (movement > 0f) {
rigidBody.velocity = new Vector2 (movement * speed, rigidBody.velocity.y);
}
else if (movement < 0f) {
rigidBody.velocity = new Vector2 (movement * speed, rigidBody.velocity.y);
}
else {
rigidBody.velocity = new Vector2 (0,rigidBody.velocity.y);
}
if(Input.GetButtonDown ("Jump")){
rigidBody.velocity = new Vector2(rigidBody.velocity.x,jumpSpeed);
}
}
}
An simple option is to maintain a boolean such as _inAir that gets set to true when the player first jumps, and to false when their RigidBody2D collides with the ground (see, e.g., OnCollisionEnter2D).
Then, the check if(Input.GetButtonDown ("Jump")){ becomes
if (!_inAir && Input.GetButtonDown("Jump")) {

Stop an Object if it reached the transform value

So I have a 2d gameObject that behaves likes a spike trap that springs out of the ground when the character collides on the trigger. I use AddForce to the rigidbody 2D of the gameObject to manipulates its speed when coming out of the ground and I want it to just sticking out of the ground. How can I stop it when it reaches a certain tranform Y value.
Here is my code:
public float speed;
Rigidbody2D rb;
void Start () {
rb = GetComponent<Rigidbody2D>();
}
void Update () {
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
rb.AddForce(new Vector2(0, speed * Time.time), ForceMode2D.Impulse);
}
}
Certain transform value, or certain transform.position value?
I'll do it like this:
private float threshold = 10f;
private float startPosition = 0;
private RigidBody2D pikeRigidbody;:
private void Start()
{
startPosition = = this.transform.position;
pikeRigidbody = this.GetComponent<RigidBody2D>();
}
private void Update(){
if(this.transform.position.y >= (startPosition.y + threshold))
{
pikeRigidbody.velocity = Vector3.zero;
}
}
And attach the script to the pike object.
Edited to position.y instead of position

Trying to create a nice character controller?

I'm kind of new in the 2D environment of Unity.
I'm trying to create a platformer. For now, I have a simple map and my player.
My simple map and my player
My player have one script attached :
public class Player : MonoBehaviour
{
public float speed;
public float jump;
public GameObject raycastPoint; // Positioned at 0.01 pixel below the player
private SpriteRenderer spriteRenderer;
private Rigidbody2D body; // Gravity Scale of the Rigidbody2D = 50
private Animator animator;
private void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
body = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
}
private void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
if (horizontal == 1 && spriteRenderer.flipX)
{
spriteRenderer.flipX = false;
}
else if (horizontal == -1 && !spriteRenderer.flipX)
{
spriteRenderer.flipX = true;
}
body.velocity = new Vector2(horizontal * speed, body.velocity.y);
animator.SetFloat("Speed", Mathf.Abs(horizontal));
float vertical = Input.GetAxisRaw("Vertical");
if (vertical == 1)
{
RaycastHit2D hit = Physics2D.Raycast(raycastPoint.transform.position, Vector2.down, 0.01f);
if (hit.collider != null)
{
body.AddForce(new Vector2(0f, jump));
}
}
}
}
For now I have achieved the right and left movements.
For the jump, I have a child gameobject just under the player and I'm firing a raycast to the bottom so I can know if my player is grounded or not.
I have two problems.
PROBLEM NUMBER ONE.
Sometimes I feel like my "AddForce" line is executed multiple times my player is jumping really high
Problem number one image
PROBLEM NUMBER TWO.
When I'm jumping to the left or right wall, if I keep pressing the left or right key my player is not falling anymore and stay against the wall.
Problem number two image
I tried to put my code into the FixedUpdate method (I know it's better) but I had the same results.
And I tried to set the Collision Detection on Continuous but I had the same results.
Try this code for your first problem :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(BoxCollider2D))]
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Animator))]
public class Player_Controller : MonoBehaviour {
private Rigidbody2D body;
private bool canJump, facingRight;
private Animator anim;
[SerializeField]
private float moveSpeed, jumpForce;
void Start ()
{
SetStartValues();
}
void FixedUpdate ()
{
float horizontal = Input.GetAxis("Horizontal");
animator.SetFloat("Speed", Mathf.Abs(horizontal));
Flip(horizontal);
Move(horizontal);
Jump();
}
private void SetStartValues()
{
body = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
canJump = true;
facingRight = true;
}
private void Jump()
{
if (Input.GetKeyDown(KeyCode.Space) && canJump)
{
body.AddForce(new Vector2(0, jumpForce));
canJump = false;
}
}
private void Move(float x)
{
body.velocity = new Vector2(x * moveSpeed * Time.deltaTime, body.velocity.y);
}
private void Flip(float x)
{
if (x > 0 && !facingRight|| x < 0 && facingRight)
{
facingRight = !facingRight;
transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y) ;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
canJump = true;
}
}
}
And don't forget to put the "Ground" tag on your ground object.