Unity2d: the player stop moving when I add an animation - c#

I have a problem in unity , the player mouvement is going good until I add an animation the player stop moving even if I press the keyboard keys,when I remove the animator compenent the player move normaly without problems !
I tried separate the animation script from the movement script and still theame problem , I don't think that the problem is comming from the code
playerAnimation code :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerAnim : MonoBehaviour
{
Animator anim;
Rigidbody2D rb;
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
anim = gameObject.GetComponent<Animator>();
}
void FixedUpdate()
{
if (rb.velocity.x == 0)
anim.SetBool("isRunning", false);
else
anim.SetBool("isRunning", true);
if (rb.velocity.y > 0)
anim.SetBool("isJumping", true);
else
anim.SetBool("isJumping", false);
}
}
playerMovement script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerControl : MonoBehaviour
{
Rigidbody2D rb;
private float horizontal;
public float runSpeed;
public float jumpPower;
public bool inTheGround;
private SpriteRenderer sp;
Animator anim;
// Start is called before the first frame update
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
sp = gameObject.GetComponent<SpriteRenderer>();
anim = gameObject.GetComponent<Animator>();
}
private void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
}
private void FixedUpdate()
{
rb.velocity = new Vector2(horizontal * runSpeed,
rb.velocity.y);
if (Input.GetButton("Jump")&& inTheGround)
{
rb.velocity = new Vector2(rb.velocity.x,jumpPower);
}
flipping();
Debug.Log(rb.velocity.x);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("ground"))
inTheGround = true;
}
private void OnCollisionExit2D(Collision2D other)
{
if
(other.gameObject.CompareTag("ground")&&rb.velocity.y>0.1)
inTheGround = false;
}
void flipping()
{
if (Input.GetKey(KeyCode.RightArrow))
sp.flipX = false;
if (Input.GetKey(KeyCode.LeftArrow))
sp.flipX = true;
}
}

Check if Apply Root Motion on Animator Component is set to false. This setting can overwrite your changes of the object's position over time. if not - can you please provide more information, perfectly a screenshot of your player components, and Animator Controller.

Related

Unity accessing rigidBody component with input system

I have just started a new Unity tut using its input system to move a ball. However, the script doesn't seem to be working when I try to move the ball
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem; //Namespace for accessing InputSystem to control ball
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
private float movementX;
private float movementY;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Onmove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
void FixedUpdate()
{
Vector3 movement = new Vector3(movementX, 0.0f, movementY);
rb.AddForce(movement);
}
}
If you did everything else right and the problem is only in your script then changing from Onmove to OnMove should fix problem
Create in Unity a new InputControl with the name PlayerInputActions and into
Inspector select Generate C# class, Unity autogenerate for you Action Maps , Actions and Binding Property, double click on it to watch, than in a new c# script named NewInputSystem
using UnityEngine;
using UnityEngine.InputSystem;
public class NewInputSystem : MonoBehaviour
{
public Rigidbody rb;
public float moveSpeed = 7.0f;
Vector2 moveDirections = Vector2.zero;
public PlayerInputActions playerControls;
private InputAction move;
private void Awake()
{
playerControls = new PlayerInputActions();
}
private void OnEnable()
{
move = playerControls.Player.Move;
move.Enable();
}
private void OnDisable()
{
move.Disable();
}
void Start()
{
rb =gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
moveDirections = move.ReadValue<Vector2>();
}
private void FixedUpdate()
{
//change how you want
rb.velocity = new Vector3(moveDirections.y * moveSpeed, 0, moveDirections.x * -moveSpeed);
}
}

How to use a bool to determine whether the player is jumping over

I'm working on some animations for a game I'm working on (Still in the very early stages, and new to coding). Right now I'm trying to use a bool to detect whether or not the player is jumping, and then if it returns true, then the animation will play.
Character Controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character2dController : MonoBehaviour
{
public float MovementSpeed = 8;
public float JumpForce = 5;
public Transform feet;
public bool isJumping;
private Rigidbody2D rb;
public LayerMask groundLayers;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
isJumping = false;
}
// Update is called once per frame
void Update()
{
Jump();
//LR movement
var movement = Input.GetAxis("Horizontal");
transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * MovementSpeed;
isJumping = false;
}
//Jumping
void Jump()
{
if (Input.GetButtonDown("Jump") && IsGrounded())
{
isJumping = true;
rb.AddForce(new Vector2(0, JumpForce), ForceMode2D.Impulse);
}
}
//Grounding
public bool IsGrounded()
{
Collider2D groundCheck = Physics2D.OverlapCircle(feet.position, 0.5f, groundLayers);
if (groundCheck.gameObject != null)
{
return true;
}
return false;
}
}
CharacterAnimation:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterAnimation : MonoBehaviour
{
private Animator anim;
private bool isJumping;
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
isJumping = GetComponent<Character2dController>().isJumping;
isJumping = false;
}
// Update is called once per frame
void Update()
{
//Walking Anim
if (Input.GetKey("a") || Input.GetKey("d"))
{
anim.SetBool("isWalking", true);
}
else
{
anim.SetBool("isWalking", false);
}
//Character flipping
if (Input.GetKey("a"))
{
transform.localScale = new Vector3(-1, 1, 1);
}
if (Input.GetKey("d"))
{
transform.localScale = new Vector3(1, 1, 1);
}
if(isJumping == true)
{
anim.SetTrigger("Up");
}
}
}
However, the isJumping bool never seems to change to true, and thus the animation will never play. I've tried putting it in a variety of places within the character controller code, but none of them seem to work. I'm wondering if there's something I'm doing wrong or if I should just use a different way to animate the player jumping.
Again I'm fairly new to coding so if there's anything that's wrong feel free to let me know. Thanks!
public class CharacterAnimation : MonoBehaviour
{
private Animator anim;
private bool isJumping;
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
isJumping = GetComponent<Character2dController>().isJumping;//assigns value
isJumping = false;
}
.
.
.
The line that I commented only assigns the value of isJumping variable in the Character2dController class, to the isJumping variable in your CharacterAnimation class. Therefore when you change the isJumping variable in the Character2dController class, the isJumping variable in the CharacterAnimation class is not updated.
So instead, you could check the isJumping variable from the Character2dController class:
public class CharacterAnimation : MonoBehaviour
{
private Animator anim;
private Character2dController character2dController;
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
character2dController = GetComponent<Character2dController>();//now we are holding a reference to the Character2dController component
}
// your other code here
if(character2dController.isJumping == true)
{
anim.SetTrigger("Up");
}
Also, in the Character2dController, you are setting isJumping to false at every frame, which is I believe not what you want to do. Instead of setting it directly to false, you should check whether you are grounded or not, and update the isJumping accordingly.
Try to get inputs with Keycode. like this:
if (Input.GetKey(KeyCode.A)) {
Debug.LogError("A");
}
You can try to Debug.LogError("Message on key pressed") to be sure you are capturing the input.
If you are sure you are capturing your input properly you can indicate that in your question so that a possible helper knows that to dive deep into the code.
Also post any console error you might be getting.
Also be sure that the parameters that control the animation are set, for example in the anim.SetBool("isWalking", true); you are able to check in the editor itself if setting the parameter the animation takes place.

Having problems with "OnCollisionEnter2D" in Unity2D

I'm using this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionPlayer : MonoBehaviour
{
public bool alreadyDied = false;
public GameObject player;
public float timeDeath;
public ParticleSystem particles;
public GameObject explosionGO;
private SpriteRenderer sr;
private BoxCollider2D bc;
private PlayerController walkScript;
void Start()
{
sr = GetComponent<SpriteRenderer>();
bc = GetComponent<BoxCollider2D>();
walkScript = GetComponent<PlayerController>();
}
void OnCollisionEnter2D (Collision2D collide)
{
if (collide.gameObject.CompareTag("Dead"))
{
Instantiate(particles, player.transform.position, Quaternion.identity);
Instantiate(explosionGO, player.transform.position, Quaternion.identity);
CinemachineShake.Instance.ShakeCamera(30f, .1f);
alreadyDied = true;
}
}
void Update()
{
if(alreadyDied == true)
{
timeDeath -= Time.deltaTime;
sr.enabled = false;
bc.enabled = false;
walkScript.enabled = false;
}
if(timeDeath <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
This is the bullet's code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeftBulletScript : MonoBehaviour
{
// Start is called before the first frame update
public float speed;
public float destructionLeftTime;
public ParticleSystem particles;
private GameObject thisGameObject;
void Start()
{
thisGameObject = this.gameObject;
Destroy(gameObject, destructionLeftTime);
}
void Update()
{
transform.Translate(Vector2.left * speed * Time.deltaTime);
if(destructionLeftTime > 0.05f)
{
destructionLeftTime -= Time.deltaTime;
}
else
{
Instantiate(particles, thisGameObject.transform.position, Quaternion.identity);
}
}
}
This code should spawn some particles and a sound effect when the player gets hit by something with tag "Dead". But that does not happen. I have a box collider 2D on both the bullet (that should kill me) and the player. My Rigidbody2D is dynamic on the player with z freezed. The bullet does not have a rigidbody. I made sure that the bullet actually has the tag "Dead", spelled the exact same way as the way I wrote on the script. The weirdest thing is that I used this code on another game and nothing changed (just the name of a script). Both the player and the bullet are on the same layer. Anyone could tell me what could have happened?

How to make a player die while falling?

I am developing a basic game on Unity to improve myself. It's a basic endless runner platform game.
If you right click when the player is on the ground, it jumps; if it's not on the ground, it falls faster.
But I couldn't figure out how to make a player die while falling when it couldn't catch the platform. Could you please check my code? I am trying to find an "if" command to make it happen.
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerControls : MonoBehaviour
{
public Rigidbody2D rb;
public Transform groundCheck;
public float groundCheckRadius;
public LayerMask whatIsGround;
private bool onGround;
float CurrentFallTime;
public float MaxFallTime = 7;
bool PlayerIsFalling;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
rb.velocity = new Vector2(5, rb.velocity.y);
onGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
CurrentFallTime += Time.deltaTime;
if (Input.GetMouseButtonDown(0) && onGround)
{
rb.velocity = new Vector2(rb.velocity.x, 12);
}
if (Input.GetMouseButtonDown(0) && !onGround)
{
rb.velocity = new Vector2(rb.velocity.x, -10);
}
// I want it to die and go to game over screen when it exceeds the CurrentFallTime
if ()
{
if (CurrentFallTime >= MaxFallTime)
{
SceneManager.LoadScene("GameOver");
}
}
}
}
EDIT: It solved! I simpy added "if(onGround)" and reset the CurrentFallTime. Here is the new code:
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerControls : MonoBehaviour
{
public Rigidbody2D rb;
public Transform groundCheck;
public float groundCheckRadius;
public LayerMask whatIsGround;
private bool onGround;
float CurrentFallTime;
public float MaxFallTime = 7;
bool PlayerIsFalling;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
rb.velocity = new Vector2(5, rb.velocity.y);
onGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
CurrentFallTime += Time.deltaTime;
if (onGround)
{
CurrentFallTime = 0f;
}
if (Input.GetMouseButtonDown(0) && onGround)
{
rb.velocity = new Vector2(rb.velocity.x, 12);
}
if (Input.GetMouseButtonDown(0) && !onGround)
{
rb.velocity = new Vector2(rb.velocity.x, -10);
}
if (CurrentFallTime >= MaxFallTime)
{
SceneManager.LoadScene("GameOver");
}
}
}
This is something that I just thought of now, so I'm not sure how well it will work, but you can create a 1-sided plane collider and position it to follow the x- and y-coordinate of the player, but stay slightly lower than the height of the ground, e.g. 1unit. Then check when the player collides with the plane, if it does then you know that the player has fallen.
So, create an empty GameObject and add the collider, no need for any mesh properties and set the collider trigger to true. Then in player controls add something like in update.
colliderGo.transform.location = new Vector3(transform.x, groundHeight - 1, transform.z)
Also in the player controller function
function onTrigger(Collider col) {
if (col.tag == "fallDetector") {
Debug.Log("What a cruel world")
playHasFallen = true;
}
}
Something like this should work.

I get the warning "Field 'Enemy.AI.animator' is never assigned"

I made a code to move an enemy between 2 points, when he reaches the minimum he will stop.
I get the error because it says that the animator has no assigned variable, but I set it in the start method. It also says that and the animator will always have its default value null, I don't know what to do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAI : MonoBehaviour
{
//assigning variables
public float moveSpeed;
public Transform target;
public float chaseRadius;
public float attackRadius;
private Rigidbody2D rb;
private Animator animator;
// Start is called before the first frame update
void Start()
{
//getting the necessary components
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
CheckDistance();
}
//checking distance between 2 points and setting the rigid body to move
void CheckDistance()
{
if(Vector3.Distance(target.position, transform.position) <= chaseRadius && Vector3.Distance(target.position, transform.position) > attackRadius)
{
Vector3 temp = Vector3.MoveTowards(transform.position, target.position, moveSpeed * Time.deltaTime);
ChangeAnim(temp - transform.position);
rb.MovePosition(temp);
}
}
//changing animations of the object
private void ChangeAnim(Vector2 direction)
{
if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
{
Debug.Log("x is greater");
if(direction.x > 0)
{
animator.SetFloat("moveX", direction.x);
}
else if(direction.x < 0)
{
animator.SetFloat("moveX", direction.x);
}
}else if (Mathf.Abs(direction.x) < Mathf.Abs(direction.y))
{
Debug.Log("y is greater");
if (direction.y > 0)
{
animator.SetFloat("moveX", direction.y);
}
else if (direction.y < 0)
{
animator.SetFloat("moveX", direction.y);
}
}
}
}
Player Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed;
private Rigidbody2D myRigidbody;
private Vector3 change;
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
change = Vector3.zero;
change.x = Input.GetAxisRaw("Horizontal");
change.y = Input.GetAxisRaw("Vertical");
UpdateAnimationAndMove();
}
void UpdateAnimationAndMove()
{
if (change != Vector3.zero)
{
MoveCharacter();
animator.SetFloat("moveX", change.x);
animator.SetFloat("moveY", change.y);
animator.SetBool("moving", true);
}
else
{
animator.SetBool("moving", false);
}
}
void MoveCharacter()
{
myRigidbody.MovePosition
(
transform.position + change * speed * Time.deltaTime
);
}
}
You should add a constructor to your EnemyAI class which can be passed an animator object.
public EnemyAI(Animator animator)
{
this.animator = animator;
}
If you look at your start function in PlayerMovement you see this:
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
and your EnemyAI has this:
void Start()
{
//getting the necessary components
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
You can see the last one does not assign the animator.
Change your EnemyAI start function to this:
void Start()
{
//getting the necessary components
this.animator = animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}

Categories