How to register a fall from height in unity 2D - unity3d

So i'm working on a 2D game, first stage is a platformer so i'm trying to make it look nicer. I added a particle system with dust, so in case he falls down from height animation should be played. How do i register a fall from height to play the animation?

You can play animation on collision with the ground collider, when player's falling velocity is higher than 0. Using specific positive value may be nicer, cos it's gonna look like only achieving enough speed will spread dust.

I can see another way of doing this, but it takes more calculations:
To define the last position and current position of Y coordinates of the player.
If it is going down currentPos < lastPos
If it is going up currentPos > lastPos
public GameObject player;
public GameObject particleDust;
Vector3 lastPos;
Vector3 currentPos;
float _time = 0;
private bool up = false;
private bool down = false;
private bool equal = false;
void Awake()
{
lastPos = player.transform.position;
}
void Update()
{
//assign player's position to current position
currentPos = player.transform.position;
//going up
if (lastPos.y < currentPos.y)
{
up = true;
down = false;
equal = false;
}
//going down
else if (lastPos.y > currentPos.y)
{
up = false;
down = true;
equal = false;
}
//same level
else if (lastPos.y == currentPos.y)
{
equal = true;
}
if (down == true && equal == true)
{
particleDust.Play();
}
lastPos = currentPos;
}
You can define the up and down functions to define player's movement with bool.
When the direction down is True and lastPos = currentPos
then it means that he was going down and he stopped because the player hit the ground.
I choose this option without using colliders because it can be versatile and be used on every level without adding new things.
I assume this will work but it need more things, i hope this will get you started.
(If i said something wrong please correct me , it help me improve too, thank you!)

Just thinking of how to detect falls from a specific height, I think this should work just fine in most cases:
private float startingHeight = 0.0f;
private bool grounded = true;
private bool landed = false;
//this is the distance the player needs to fall before dust shows up
private float fallingDist = 5.0f;
private void Start()
{
startingHeight = transform.position.y;
}
private void Update()
{
if(grounded) //set this to false when not colliding with the ground
{
startingHeight = transform.position.y;
}
else if(landed) //set this to true when hitting the ground while grounded is false
{
landed = false;
if((startingHeight - transform.position.y) >= fallingDist)
{
//trigger dust particles or animation
}
}
}

Related

Why my character won't jump with my code?

I have this problem with my 2D game project,I pasted and modified it a little bit from the code can be found in this video:https://www.youtube.com/watch?v=dwcT-Dch0bA
But the problem is it won't jump I added Debug.Log to see if the input is really the reason why my character won't jump,I tested it and it won't jump but it still shows me that the "q" button is pressed.I tried with another way is that changing input in unity but it just doesn't work.I used the same code in Brackeys's project and it works like normal.
Here is the code:
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool jump = false;
bool crouch = false;
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
if (Input.GetKeyDown("q"))
{
Debug.Log("Jump button works");
jump = true;
}
if (Input.GetButtonDown("Crouch"))
{
crouch = true;
}
else if (Input.GetButtonUp("Crouch"))
{
crouch = false;
}
}
void FixedUpdate()
{
controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump);
jump = true;
}
}
CharacterController2D:
public class CharacterController2D : MonoBehaviour
{
[SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps.
[Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100%
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement
[SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping;
[SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character
[SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded.
[SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings
[SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
private bool m_Grounded; // Whether or not the player is grounded.
const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
private Rigidbody2D m_Rigidbody2D;
private bool m_FacingRight = true; // For determining which way the player is currently facing.
private Vector3 velocity = Vector3.zero;
private void Awake()
{
m_Rigidbody2D = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
m_Grounded = true;
}
}
public void Move(float move, bool crouch, bool jump)
{
// If crouching, check to see if the character can stand up
if (!crouch)
{
// If the character has a ceiling preventing them from standing up, keep them crouching
if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
{
crouch = true;
}
}
//only control the player if grounded or airControl is turned on
if (m_Grounded || m_AirControl)
{
// If crouching
if (crouch)
{
// Reduce the speed by the crouchSpeed multiplier
move *= m_CrouchSpeed;
// Disable one of the colliders when crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = false;
}
else
{
// Enable the collider when not crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = true;
}
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);
// If the input is moving the player right and the player is facing left...
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
}
// If the player should jump...
if (m_Grounded && jump)
{
// Add a vertical force to the player.
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
First of all, your code is not very optimized.
You call Physics2D.OverlapCircleAll () every frame and it's not very good for performance.
As an alternative you can use Physics2D.OverlapCircleNonAlloc(), which will save some memory, or even better, use OnCollisionEnter2D () and OnCollisionExit2D () to understand when it collides with something.
Speaking of the scripts, they seem to have to work. Try adding a print(m_Grounded + “ " + jump) and say what appears in the console.
When you press q both should be true, but apparently one of them isn't, and with that print() we'll find out what it is and fix the problem.
public void Move(float move, bool crouch, bool jump)
{
// If crouching, check to see if the character can stand up
if (!crouch)
{
// If the character has a ceiling preventing them from standing up, keep them crouching
if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
{
crouch = true;
}
}
//only control the player if grounded or airControl is turned on
if (m_Grounded || m_AirControl)
{
// If crouching
if (crouch)
{
// Reduce the speed by the crouchSpeed multiplier
move *= m_CrouchSpeed;
// Disable one of the colliders when crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = false;
}
else
{
// Enable the collider when not crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = true;
}
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref velocity, m_MovementSmoothing);
// If the input is moving the player right and the player is facing left...
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
}
// If the player should jump…
print(“m_Grounded = " + m_Grounded + " && jump = " + jump);
if (m_Grounded && jump)
{
// Add a vertical force to the player.
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
if you think my answer helped you, you can mark it as accepted and vote positively. I would very much appreciate it :)

Tried to edit Brackeys 2d Movement script to have 2 ground checks

So I'm working on a 2d platformer. I'm new to Unity so I figured I should find a simple player controller for now and make a new one once I know what I'm doing. I followed Brackeys 2D movement controller tutorial and it worked perfectly. I noticed that since it uses 1 ground check if you stand on a ledge it thinks you are in the air. I tried to add a second ground check and space them out on the right and left. I added a new variable and edited the code to look like this:
using UnityEngine;
using UnityEngine.Events;
public class CharacterController2D : MonoBehaviour
{
[SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps.
[Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100%
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement
[SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping;
[SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character
[SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded.
[SerializeField] private Transform m_GroundCheck2; // A position marking where to check if the player is grounded.
[SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings
[SerializeField] private Transform m_CeilingCheck2; // A position marking where to check for ceilings
[SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
private bool m_Grounded; // Whether or not the player is grounded.
const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
private Rigidbody2D m_Rigidbody2D;
private bool m_FacingRight = true; // For determining which way the player is currently facing.
private Vector3 m_Velocity = Vector3.zero;
[Header("Events")]
[Space]
public UnityEvent OnLandEvent;
[System.Serializable]
public class BoolEvent : UnityEvent<bool> { }
public BoolEvent OnCrouchEvent;
private bool m_wasCrouching = false;
private void Awake()
{
m_Rigidbody2D = GetComponent<Rigidbody2D>();
if (OnLandEvent == null)
OnLandEvent = new UnityEvent();
if (OnCrouchEvent == null)
OnCrouchEvent = new BoolEvent();
}
private void FixedUpdate()
{
bool wasGrounded = m_Grounded;
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
}
//WHAT I ADDED
Collider2D[] colliders2 = Physics2D.OverlapCircleAll(m_GroundCheck2.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders2[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
}
}
//END OF WHAT I ADDED
public void Move(float move, bool crouch, bool jump)
{
// If crouching, check to see if the character can stand up
if (!crouch)
{
// If the character has a ceiling preventing them from standing up, keep them crouching
if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
{
crouch = true;
}
if (Physics2D.OverlapCircle(m_CeilingCheck2.position, k_CeilingRadius, m_WhatIsGround))
{
crouch = true;
}
}
//only control the player if grounded or airControl is turned on
if (m_Grounded || m_AirControl)
{
// If crouching
if (crouch)
{
if (!m_wasCrouching)
{
m_wasCrouching = true;
OnCrouchEvent.Invoke(true);
}
// Reduce the speed by the crouchSpeed multiplier
move *= m_CrouchSpeed;
// Disable one of the colliders when crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = false;
} else
{
// Enable the collider when not crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = true;
if (m_wasCrouching)
{
m_wasCrouching = false;
OnCrouchEvent.Invoke(false);
}
}
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);
// If the input is moving the player right and the player is facing left...
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
}
// If the player should jump...
if (m_Grounded && jump)
{
// Add a vertical force to the player.
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
When I run the code I cant jump and get this error whenever groundcheck2 isn't touching the ground but groundcheck 1 is.
IndexOutOfRangeException: Index was outside the bounds of the array.
CharacterController2D.FixedUpdate () (at Assets/Scripts/Player/CharacterController2D.cs:66)
Sorry if the problem was obvious. Thank you.
This might be because your second for is checking for the wrong collider array. It should be colliiders2.length.
//WHAT I ADDED
Collider2D[] colliders2 = Physics2D.OverlapCircleAll(m_GroundCheck2.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders2.Length; i++)
{
if (colliders2[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
}

(Big unity noob here) I can jump while in the air, and I can't jump while moving on the x-axis

Have tried a few things but they didn't seem to work, so I was hoping that you guys could help me.
I've trying to make this demo for a little time now, but I can't seem to get the jumping to work.
When I try to jump while running, I can't. But I can however jump forever when i get up in the air, which is something that I would like to remove from the game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
Rigidbody2D rb2d;
public float moveVelocity = 8f;
public float jumpVelocity = 15f;
public float fallMultiplier = 2.5f;
public float lowJumpMultiplier = 2f;
public const string RIGHT = "right";
public const string LEFT = "left";
public const string UP = "up";
string buttonPressed;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
if (rb2d.velocity.y < 0)
{
rb2d.velocity += Vector2.up * Physics2D.gravity.y * (fallMultiplier - 1) *
Time.deltaTime;
}
else if (rb2d.velocity.y > 0 && !Input.GetButton ("Jump"))
{
rb2d.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpMultiplier - 1) *
Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
buttonPressed = RIGHT;
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
buttonPressed = LEFT;
}
else if (Input.GetKey(KeyCode.UpArrow))
{
buttonPressed = UP;
}
else
{
buttonPressed = null;
}
}
private void FixedUpdate()
{
if (buttonPressed == RIGHT)
{
rb2d.velocity = new Vector2(moveVelocity, rb2d.velocity.y);
}
else if (buttonPressed == LEFT)
{
rb2d.velocity = new Vector2(-moveVelocity, rb2d.velocity.y);
}
else if (buttonPressed == UP)
{
rb2d.velocity = Vector2.up * jumpVelocity;
}
else
{
rb2d.velocity = new Vector2(0, rb2d.velocity.y);
}
}
}
I am not sure why you are trying to control the gravity of the player when gravity is already applied to any gameObject with the RigidBody or RigidBody2D component attached to it. It is good that you are reading input in the Update() function and applying the motion inside of the FixedUpdate(). Here is a slight tweak to your current code, let me know how this goes.
Rigidbody2D rb2d;
public float moveVelocity = 8f;
public float jumpVelocity = 15f;
private float horizontalInput = 0.0f;
// did the player just try to jump
private bool justJumped = false;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
// grab how the player is moving - this value is mapped to your arrow keys
// so horizontal is left / right arrow and Vertical is up/down arrow
// the value is between [-1, 1] respectively
horizontalInput = Input.GetAxis("Horizontal");
// player tried to jump, we are not currently jumping and the player is grounded
if(IsGrounded() && Input.GetKeyDown(KeyCode.UpArrow))
{
justJumped = true;
}
}
private void FixedUpdate()
{
// handle our jump
if(justJumped)
{
// we just applied a jump so do not apply it again
justJumped = false;
// you can either apply the jump by setting velocity, but I would recommend using AddForce instead
rb2d.AddForce(Vector2.up * jumpVelocity);
}
// we are moving in either the left or right direction
if(horizontalInput != 0)
{
// move in the horizontal axis, but keep our Y component of velocity the same in case we jumped
rb2d.velocity = new Vector2 (horizontalInput * moveVelocity, rigidBody.velocity.y);
}
else
{
// just in case we are not moving, assure this by setting the horizontal component of velocity to 0
rb2d.velocity = new Vector2 (0f, rigidBody.velocity.y);
}
}
// determines if this object is currently touching another object that is marked as ground
private bool IsGrounded() {
// our current position (the player)
Vector2 position = transform.position;
// the direction we are going to aim the raycast (down as that is where the ground is)
Vector2 direction = Vector2.down;
// the ground should be close, so check it very close to the player
float distance = 1.0f;
// check if we hit anything that is on the layer of just ground - ignore all other layers
// IMPORTANT:: Make sure to make a Layer and set all of your ground to this layer
RaycastHit2D hit = Physics2D.Raycast(position, direction, distance, LayerMask.GetMask("GroundLayer"));
// we hit a ground collider, so we are grounded
if (hit.collider != null) {
return true;
}
return false;
}
Let me know if this works for you. I changed a few things around such as using GetAxis() instead of using the arrow keys as in Unity, these are the same. I also changed your jump to use an AddForce2D instead of setting velocity. The one addition was I added a IsGrounded() which will detect if whatever object this script is on (I assume it is on your player object) is near or touching objects below them that are marked as GroundLayer. If you have questions comment below.

Unity 2D player movement

I had my unity movement working on my computer, however when i try to play on my android it is not moving for me at all. I am sure it is probably a small error i am overlooking but i would be very appreciative of any help! I do not get any errors when i try yo run my code if that is of any assistance! I will supply the code below:
using UnityEngine;
using System.Collections;
//Adding this allows us to access members of the UI namespace including Text.
using UnityEngine.UI;
public class PlayerControler : MonoBehaviour {
public Text countText; //Store a reference to the UI Text component which will display the number of pickups collected.
//public Text winText; //Store a reference to the UI Text component which will display the 'You win' message.
private double count; //Integer to store the number of pickups collected so far.
//Player movement controls
private Vector3 touchPosition; //where your finger touches screen
private Vector3 direction; //direction you drag sprite
private Rigidbody2D rb2d; //Store a reference to the Rigidbody2D component required to use 2D Physics.
public float speed = 10f; //Floating point variable to store the player's movement speed.
// Use this for initialization
void Start()
{
//Get and store a reference to the Rigidbody2D component so that we can access it.
rb2d = GetComponent<Rigidbody2D> ();
//Initialize count to zero.
count = 0;
//Initialze winText to a blank string since we haven't won yet at beginning.
//winText.text = " "; //error here??
//Call our SetCountText function which will update the text with the current value for count.
//SetCountText ();
}
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
touchPosition.z = 0;
direction = (touchPosition - transform.position);
rb2d.velocity = new Vector2(direction.x , direction.y) * speed;
if(touch.phase == TouchPhase.Ended)
{
rb2d.velocity = Vector2.zero;
}
}
}
//OnTriggerEnter2D is called whenever this object overlaps with a trigger collider.
void OnTriggerEnter2D(Collider2D other)
{
//Check the provided Collider2D parameter other to see if it is tagged "PickUp", if it is...
if (other.gameObject.CompareTag ("PickUp"))
{
//... then set the other object we just collided with to inactive.
other.gameObject.SetActive(false);
//Add one to the current value of our count variable.
count = count + 1;
//Update the currently displayed count by calling the SetCountText function.
//SetCountText ();
}
}
Here is my 2D Player Movement Controller.
Code(Character Controller) -
using UnityEngine;
using UnityEngine.Events;
public class CharacterController2D : MonoBehaviour
{
[SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps.
[Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100%
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement
[SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping;
[SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character
[SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded.
[SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings
[SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching
const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
private bool m_Grounded; // Whether or not the player is grounded.
const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
private Rigidbody2D m_Rigidbody2D;
private bool m_FacingRight = true; // For determining which way the player is currently facing.
private Vector3 m_Velocity = Vector3.zero;
[Header("Events")]
[Space]
public UnityEvent OnLandEvent;
[System.Serializable]
public class BoolEvent : UnityEvent<bool> { }
public BoolEvent OnCrouchEvent;
private bool m_wasCrouching = false;
private void Awake()
{
m_Rigidbody2D = GetComponent<Rigidbody2D>();
if (OnLandEvent == null)
OnLandEvent = new UnityEvent();
if (OnCrouchEvent == null)
OnCrouchEvent = new BoolEvent();
}
private void FixedUpdate()
{
bool wasGrounded = m_Grounded;
m_Grounded = false;
// The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
// This can be done using layers instead but Sample Assets will not overwrite your project settings.
Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
}
}
public void Move(float move, bool crouch, bool jump)
{
// If crouching, check to see if the character can stand up
if (!crouch)
{
// If the character has a ceiling preventing them from standing up, keep them crouching
if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
{
crouch = true;
}
}
//only control the player if grounded or airControl is turned on
if (m_Grounded || m_AirControl)
{
// If crouching
if (crouch)
{
if (!m_wasCrouching)
{
m_wasCrouching = true;
OnCrouchEvent.Invoke(true);
}
// Reduce the speed by the crouchSpeed multiplier
move *= m_CrouchSpeed;
// Disable one of the colliders when crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = false;
}
else
{
// Enable the collider when not crouching
if (m_CrouchDisableCollider != null)
m_CrouchDisableCollider.enabled = true;
if (m_wasCrouching)
{
m_wasCrouching = false;
OnCrouchEvent.Invoke(false);
}
}
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
// And then smoothing it out and applying it to the character
m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);
// If the input is moving the player right and the player is facing left...
if (move > 0 && !m_FacingRight)
{
// ... flip the player.
Flip();
}
// Otherwise if the input is moving the player left and the player is facing right...
else if (move < 0 && m_FacingRight)
{
// ... flip the player.
Flip();
}
}
// If the player should jump...
if (m_Grounded && jump)
{
// Add a vertical force to the player.
m_Grounded = false;
m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
}
}
private void Flip()
{
// Switch the way the player is labelled as facing.
m_FacingRight = !m_FacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
And here is the actual Character Movement Code -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool jump = false;
private void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
if(Input.GetButtonDown("Jump"))
{
jump = true;
}
}
private void FixedUpdate()
{
controller.Move(horizontalMove * Time.fixedDeltaTime, false, jump);
jump = false;
}
}
Maybe the movement on android device is too small to be noticed. Try multiplying speed to delta time and then tweak the speed value to reach your desired movement speed.
rb2d.velocity = new Vector2(direction.x , direction.y) * speed * Time.deltaTime;
Make sure the script is attached to the game object with Rigidbody2D component. Also if your computer doesn't support touch, you can use mouse input to have the same result on computer and mobile device.
if (Input.GetMouseButtonUp(0))
{
rb2d.velocity = Vector2.zero;
}
else if (Input.GetMouseButton(0))
{
touchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
touchPosition.z = 0;
direction = (touchPosition - transform.position);
rb2d.velocity = new Vector2(direction.x, direction.y) * speed * Time.deltaTime;
}
This code is also works on mobile devices.
Try adding Time.deltaTime or increasing the force with Time.deltaTime.

Object X pos is drastically changing after screen shake ends

I'm using the code below to move my player, named balloon, left and right on the x axis by calculating the difference between where you first touched (or clicked) and where you're currently touching, using ScreenToWorldPoint.
void Update()
{
if (gameStarted)
if (Input.GetMouseButtonDown(0))
{
firstTouch = Camera.main.ScreenToWorldPoint(Input.mousePosition);
startPos = balloon.position;
}
if (Input.GetMouseButton(0))
CheckTouchPosition();
}
}
void CheckTouchPosition()
{
Vector2 currentTouch = Camera.main.ScreenToWorldPoint(Input.mousePosition);
float horizontalDif = currentTouch.x - firstTouch.x;
balloon.position = new Vector2(startPos.x + horizontalDif * 1.2f, balloon.position.y);
}
This works normally except after I run into an obstacle and call my trigger shake function, which performs a typical screen shake. After the screen shake ends the player is translated across the X axis, from what I can tell in the inspector roughly doubling its X position.
public class ScreenShake : MonoBehaviour {
Vector3 initialPosition;
float shakeDuration;
public bool shaking;
[SerializeField] float shakeMagnitude = 0.5f;
[SerializeField] float dampingSpeed = 1.0f;
void Update()
{
if (shakeDuration > 0)
{
shaking = true;
transform.localPosition = initialPosition + Random.insideUnitSphere * shakeMagnitude;
shakeDuration -= Time.unscaledDeltaTime * dampingSpeed;
}
else
{
shakeDuration = 0f;
transform.localPosition = initialPosition;
shaking = false;
}
}
public void TriggerShake(float duration, Vector3 position)
{
shakeDuration = duration;
initialPosition = position;
}
}
I can't figure out why the balloon's X is changing after the screen shake, but it doesn't happen if I don't call that function. I think maybe it has to do with ScreenToWorldPoint being messed up because I'm changing the position of the camera?
EDIT: I forgot to add that the weird repositioning of the balloon ONLY occurs if youre currently holding touching the screen (or holding down the mouse button) when the screen shake occurs. Otherwise everything happens normally.