There was a problem with Unity animations. When the character jumps, the animation is played, but if the character jumps in either direction, the animation does not stop and the character with this animation rolls on the ground.
https://ibb.co/hLKmK6W
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovent : MonoBehaviour
{
public GameObject player;
public float speed = 10f;
private Rigidbody2D rb;
public int jump = 350 ;
Animator animation;
private bool inground;
// Start is called before the first frame update
void Start()
{
animation = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
}
void FixedUpdate()
{
var moveX = Input.GetAxis("Horizontal");
if (Input.GetKey(KeyCode.Space) && rb.velocity.y == 0)
{
rb.AddForce(Vector2.up * jump);
animation.SetTrigger("Jump");
}
rb.velocity = new Vector2(moveX * speed, rb.velocity.y);
if (animation)
{
animation.SetBool("Run", Mathf.Abs(moveX) >= 0.1f);
}
Vector3 charecterScale = transform.localScale;
if (Input.GetAxis("Horizontal") < 0)
{
charecterScale.x = -7.215315f;
}
if (Input.GetAxis("Horizontal") > 0)
{
charecterScale.x = 7.215315f;
}
transform.localScale = charecterScale;
}
}
You need to check if you are grounded or not. there is an example in this video:
https://youtu.be/CSu7MWv8qEY
The solution to this would be to check if the player is grounded, using Physics2D.Raycast() or Physics2D.OverlapCircle() and passing it as a boolean to the animator, like this:
public float radius = .5f;
public Vector2 offset = new Vector2(0, -.5f, 0);
public LayerMask layermask;
Animator animation;
Rigidbody2D rb;
void Start()
{
animation = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
bool IsGrounded() => Physics2D.OverlapCircle((Vector2)transform.position + offset, radius, layermask);
// to visualize the circle
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position + (Vector3)offset, radius);
}
void FixedUpdate()
{
animation.SetBool("isGrounded", IsGrounded());
}
Related
I've made a small game, since I am a beginner in Unity and I wanted to add a boolean colider to see if my spinning ball was on the ground for it to jup, but it dosen't work.
Thank you ! Here is the code :
`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class script_mouvement : MonoBehaviour
{
Rigidbody rb;
[SerializeField] float movementSpeed = 6f;
[SerializeField] float jumpForce = 5f;
[SerializeField] Transform groundCheck;
[SerializeField] LayerMask ground;
[SerializeField] AudioSource jumpSound;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
rb.velocity = new Vector3(horizontalInput * movementSpeed, rb.velocity.y, verticalInput * movementSpeed);
if (Input.GetButtonDown("Jump")&& isGrounded())
{
Jump();
}
}
void Jump()
{
rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
}
bool isGrounded(){
Collider[] colliders = Physics.OverlapSphere(groundCheck.position, 1.0f, ground);
for (int i = 0; i < colliders.Length; i++) {
if (colliders[i].gameObject != gameObject) {
return true;
}
}
return false;
}
}`
I tried to add a collision check but it didn't work , I expected the ball to jup when It was on the ground
I'm developping a 3D game Unity with a squirrel as the player.
I'm struggling with a problem of slopes. I know, there are a bunch of tutorial to go down a slope whithout 'floating in the air while walking' but I didn't find a fine solution. I think it's because of the horizontal animations of the squirrel (maybe). I have tried with addForce, with a modified speed, with gravity... (maybe I implemented it wrong). I know I can check if I'm in the air or not with CharacterController.isGrounded but I can't force the squirrel to stick on the slope while running or walking. I'm sorry by advance if my question is too vague or simple.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class Squirrel : MonoBehaviour {
Animator squirrel;
public float gravity = 1.0f;
private Vector3 moveDirection = Vector3.zero;
float axisH, axisV;
public static int munitions = 0;
Rigidbody rb;
[SerializeField]
float walkSpeed = 2f, runSpeed = 8f, rotSpeed = 100f, jumpForce = 350;
private bool isJumpKeyDown = false;
[SerializeField] bool isJumping = false;
Animator characterAnimator;
int JumpCount = 0;
public int MaxJumps = 1; //Maximum amount of jumps (i.e. 2 for double jumps)
[SerializeField] GameObject nb_munitions;
CharacterController characterController;
// Use this for initialization
void Start () {
munitions = 0;
squirrel = GetComponent<Animator>();
rb = GetComponentInChildren<Rigidbody>();
characterAnimator = GetComponent<Animator>();
JumpCount = MaxJumps;
characterController = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
GetInput();
nb_munitions.GetComponent<Text>().text = "Glands : " + munitions; //Affichage du score
Move();
}
private void FixedUpdate()
{
if (isJumpKeyDown)
{
squirrel.SetTrigger("jump");
JumpCount -= 1;
isJumpKeyDown = false;
}
}
public void GetInput()
{
axisV = Input.GetAxis("Vertical");
axisH = Input.GetAxis("Horizontal");
}
private void Move()
{
if (characterController.isGrounded)
{
//On the ground
}
else
{
//on the air
}
if (axisV > 0)
{
if (Input.GetKeyDown(KeyCode.LeftControl))
{
transform.position += Vector3.forward * walkSpeed * Time.deltaTime;
squirrel.SetBool("walk", true);
}
else
{
transform.position += Vector3.forward * runSpeed * Time.deltaTime;
squirrel.SetFloat("run", axisV);
squirrel.SetBool("walk", false);
}
}
else
{
squirrel.SetFloat("run", 0);
}
if (axisH != 0 && axisV == 0)
{
squirrel.SetFloat("h", axisH);
}
else
{
squirrel.SetFloat("h", 0);
}
if (axisH != 0)
{
transform.Rotate(Vector3.up * rotSpeed * Time.deltaTime * axisH);
}
if (Input.GetKeyDown(KeyCode.Space))
{
if (JumpCount > 0)
{
isJumpKeyDown = true;
}
}
//Call munitions
if (Input.GetKeyDown(KeyCode.LeftShift))
{
if (Squirrel.munitions > 0)
{
SpawnerScript.Instance.NewSpawnRequest();
munitions--;
}
}
}
}
You can try to get the angle of the slope and make it the pitch for the mesh of the squirrel.
I finally found the problem. My C# script "overwrited" the CharacterController and did not allow the squirrel to go down the slopes. Make sure you follow a move script that "respects" the CharacterController (if you pick one or you'll be fighting windmills).
I have a ball that jumps up a ladder, but when the jump ends, the ball still moves a short distance. It used to travel long distances and I just set freezeRotation = true, but the inertia still remained.
I would be glad to any advice. Here is my code
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class ballcontroller : MonoBehaviour
{
//public int speed = 3;
public int jumpForce;
public bool IsGround;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
//float Vm = Input.GetAxis("Vertical");
//float Hm = Input.GetAxis("Horizontal");
//Vector3 V3M = new Vector3(Hm, 0, Vm);
//rb.AddForce(V3M * speed);
Jump();
}
public void Jump()
{
Ray ray = new Ray(gameObject.transform.position, Vector3.down);
RaycastHit rh;
if (Physics.Raycast(ray, out rh, 0.5f))
{
IsGround = true;
}
else
{
IsGround = false;
}
if (Input.GetKeyDown(KeyCode.Space) && IsGround)
{
rb.AddForce(Vector3.one * jumpForce);
rb.freezeRotation = true;
}
}
}
You can directly manipulate the velocity of your rigidbody using Rigidbody.velocity and Rigidbory.angularVelocity.
You could set it to Vector3.zero (or decrease it slowly to avoid hard freezing) after you hit the ground.
I am doing a 2d game and I want to know how I can make the bullets to shoot right and left . At this moment the bullets go just to the left , even if my player moves right. How I can make them shoot both sides or shoot just when they find an object tagged " enemy "
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
public class Character : MonoBehaviour
{
Rigidbody2D rb;
float dirX;
[SerializeField]
float moveSpeed = 5f, jumpForce = 400f, bulletSpeed = 500f;
Vector3 localScale;
public Transform barrel;
public Rigidbody2D bullet;
// Use this for initialization
void Start()
{
localScale = transform.localScale;
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
dirX = CrossPlatformInputManager.GetAxis("Horizontal");
if (CrossPlatformInputManager.GetButtonDown("Jump"))
Jump();
if (CrossPlatformInputManager.GetButtonDown("Fire1"))
Fire();
}
void FixedUpdate()
{
rb.velocity = new Vector2(dirX * moveSpeed, rb.velocity.y);
}
void Jump()
{
if (rb.velocity.y == 0)
rb.AddForce(Vector2.up * jumpForce);
}
void Fire()
{
var firedBullet = Instantiate(bullet, barrel.position, barrel.rotation);
firedBullet.AddForce(barrel.up * bulletSpeed);
}
}
You're already accounting for the direction of the barrel. You just need to change the direction of the barrel when you move.
One way to do that is to just set that directly:
// Update is called once per frame
void Update()
{
dirX = CrossPlatformInputManager.GetAxis("Horizontal");
if (dirX !=0)
{
barrel.up = Vector3.right * Mathf.Sign(dirX);
}
if (CrossPlatformInputManager.GetButtonDown("Jump"))
Jump();
if (CrossPlatformInputManager.GetButtonDown("Fire1"))
Fire();
}
If the barrel is a child of the player object, then changing the character's rotation so that the barrel's direction points in the correct direction will also work. There's not enough information in the question to know for sure but maybe using Quaternion.LookRotation to set the character's rotation like so would work:
// Update is called once per frame
void Update()
{
dirX = CrossPlatformInputManager.GetAxis("Horizontal");
if (dirX !=0)
{
Vector3 newPlayerForward = Vector3.forward * Mathf.Sign(dirX);
transform.rotation = Quaternion.LookRotation(newPlayerForward, Vector3.up);
}
if (CrossPlatformInputManager.GetButtonDown("Jump"))
Jump();
if (CrossPlatformInputManager.GetButtonDown("Fire1"))
Fire();
}
So I'm trying to add a dash mechanic to a game character im building. However for some reason i can't get the game objects velocity to actually change. I tried using addForce which worked, but i had to add a lot in order to get the desired effect and that behaved strangely sometimes!
Do i need to do anything else to the game objects velocity than i already doing?
Heres my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float dashSpeed;
private int dashDirection;
private float dashCoolDown;
public float startDashCoolDown;
private float dashTime;
public float startDashTime;
public GameObject dashEffect;
public float speed;
public float jumpForce;
private float moveInput;
private Rigidbody2D rb;
private bool isFacingRight = true;
private Animator anim;
private bool isGrounded;
public Transform groundCheck;
public float checkRadius;
public LayerMask whatIsGround;
private int extraJumps;
public int extraJumpsValue;
public GameObject dustEffect;
public GameObject trailEffect;
private void Awake()
{
// Setting up references.
isGrounded = transform.Find("GroundCheck");
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
void Start()
{
extraJumps = extraJumpsValue;
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
dashCoolDown = startDashCoolDown;
}
void FixedUpdate()
{
isGrounded = false;
// Check to see if grounded
Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheck.position, checkRadius, whatIsGround);
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].gameObject != gameObject)
{
isGrounded = true;
anim.SetBool("Ground", isGrounded);
}
}
// Check if movement is allowed
if (!GameMaster.disableMovement)
{
// Move character
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
Instantiate(trailEffect, groundCheck.position, Quaternion.identity);
anim.SetFloat("Speed", Mathf.Abs(moveInput));
}
// Flip character
if (isFacingRight == false && moveInput > 0)
{
Flip();
}
else if (isFacingRight == true && moveInput < 0)
{
Flip();
}
}
private void Update()
{
// Check if the player is grounded
if (isGrounded == true)
{
extraJumps = extraJumpsValue;
}
// Check if movement is allowed
if (!GameMaster.disableMovement)
{
// Check for jump
// If the player has more than one jump available
if (Input.GetKeyDown(KeyCode.Space) && extraJumps > 0)
{
isGrounded = false;
anim.SetBool("Ground", isGrounded);
rb.velocity = Vector2.up * jumpForce;
extraJumps--;
Instantiate(dustEffect, groundCheck.position, Quaternion.identity);
}
// If the player only has one jump available
if (Input.GetKeyDown(KeyCode.Space) && extraJumps == 0 && isGrounded == true)
{
isGrounded = false;
anim.SetBool("Ground", isGrounded);
rb.velocity = Vector2.up * jumpForce;
}
// Check for dash
if (dashCoolDown <= 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
anim.SetBool("Dash", true);
Dash();
dashTime = startDashTime;
}
}
else
{
dashCoolDown -= Time.deltaTime;
}
}
}
void Dash()
{
if (dashTime <= 0)
{
dashCoolDown = startDashCoolDown;
anim.SetBool("Dash", false);
}
else
{
dashTime -= Time.deltaTime;
if (isFacingRight)
{
rb.velocity = Vector2.right * dashSpeed;
}
else if (!isFacingRight)
{
rb.velocity = Vector2.left * dashSpeed;
}
}
}
void Flip()
{
isFacingRight = !isFacingRight;
// Multiply the player's x local scale by -1.
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
If you dont get the desired dash effect with Rigidbody.velocity, you can try using Rigidbody.addForce(). I know you said you already used it, but there are multiple different force modes you can apply here. I would suggest using this one, because it applies full force from the start and then drops it off. You can read more about it yourself here.
So you could modify your code like so:
void Dash()
{
if (isFacingRight)
{
rb.AddForce(Vector2.right*dashSpeed, ForceMode.VelocityChange);
}
else if (!isFacingRight)
{
rb.AddForce(Vector2.left*dashSpeed, ForceMode.VelocityChange);
}
}
Note, that you also dont need to call dash repeatedly to falloff the velocity. this function should now be only called onse the button to dash (shift) has been pressed.
Hope this helped!