It started happening after I wrote the script for dashing. Now, whenever I dash into walls, my character gets stuck to that wall. If I dash towards the roof, then I can walk on the roof for example. Also, when I dash next to a wall / on the floor, it never stops dashing after a single press. Any help will be appreciated, thanks.
The code below is the dashing script, if needed I can post the variables set and my character controller script too.
void Start()
{
_rigidbody = GetComponent<Rigidbody2D>();
dashTime = baseDashTime;
}
void Update()
{
isGrounded = Physics2D.OverlapCircle(feet.position, checkRadius, checkGround);
if(isGrounded == true)
{
dashTime = baseDashTime;
}
if (direction == 0)
{
if (Input.GetKey(KeyCode.W) && (Input.GetKeyDown(KeyCode.LeftShift)))
{
direction = 1;
}
else if (Input.GetKey(KeyCode.A) && (Input.GetKeyDown(KeyCode.LeftShift)))
{
direction = 2;
}
else if (Input.GetKey(KeyCode.S) && (Input.GetKeyDown(KeyCode.LeftShift)))
{
direction = 3;
}
else if (Input.GetKey(KeyCode.D) && (Input.GetKeyDown(KeyCode.LeftShift)))
{
direction = 4;
}
}
else
{
if (dashTime <= 0)
{
direction = 0;
_rigidbody.velocity = Vector2.zero;
}
else
{
dashTime -= Time.deltaTime;
if (direction == 1)
{
_rigidbody.velocity = Vector2.up * dashSpeed;
}
else if (direction == 2)
{
_rigidbody.velocity = Vector2.left * dashSpeed;
}
else if (direction == 3)
{
_rigidbody.velocity = Vector2.down * dashSpeed;
}
else if (direction == 4)
{
_rigidbody.velocity = Vector2.right * dashSpeed;
}
}
}
}
In your code you have this statement in the update function. When you dash on the ground, im guessing IsGrounded will stay true, so the player will keep dashing forever. This is probably what causes the player to be stuck.
if(isGrounded == true)
{
dashTime = baseDashTime;
}
Related
I wrote a code for an enemy that, when he sees my character, will chase him. But when he sees my character and chases him, he goes through objects.There is a box collider 2D on it, but it moves with it. I've already tried everything, I don't know how to fix it. Can you please help fix
Here is my code:
void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
idleSpeed = speed;
barDelta = Vector3.Distance(parent.position, barPoint.position);
bar = UIManager.AddEnemy(this);
}
void Update()
{
if (Vector2.Distance(transform.position, point.position) < positionOfPatrol && angry == false)
{
idle = true;
}
if (Vector2.Distance(transform.position, player.position) < stoppingDistance)
{
angry = true;
idle = false;
goBack = false;
}
if (Vector2.Distance(transform.position, player.position) > stoppingDistance)
{
goBack = true;
angry = false;
}
if (idle == true)
{
Idle();
}
else if (angry == true)
{
Angry();
}
else if (goBack == true)
{
GoBack();
}
}
void Idle()
{
if (transform.position.x > point.position.x + positionOfPatrol)
{
moveingRight = false;
}
else if (transform.position.x < point.position.x - positionOfPatrol)
{
moveingRight = true;
}
if (moveingRight)
{
if (!facingRight) Flip();
facingRight = true;
transform.position = new Vector2(transform.position.x + speed * Time.deltaTime, transform.position.y);
}
else
{
if (facingRight) Flip();
facingRight = false;
transform.position = new Vector2(transform.position.x - speed * Time.deltaTime, transform.position.y);
}
}
void Angry()
{
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
speed = idleSpeed + 1;
}
void GoBack()
{
transform.position = Vector2.MoveTowards(transform.position, point.position, speed * Time.deltaTime);
speed = idleSpeed;
}
}
You should try to use a rigidbody with the collider. The collider does not actually do physics, that is what the rigidbody is for. If you add a rigidbody and set its velocity instead of setting the transform's position, it will not only detect collisions with walls but it will stop moving and do all of the physics you would expect.
so I have a script that rotates a cube (by 90 degrees when a direction is pressed) currently im using the oncollision enter to detect walls and when I try to use it to also check if grounded then it will just completely stop everything when i leave one collision and enter another, or it won't fully check when im in mid air and will allow me to move when i don't want to be able to. Any and all help is greatly appreciated.
{
bool isGrounded = true;
private Rigidbody2D rb;
bool leftInput = true;
bool rightInput = true;
public float RollingDuration = 0.2f;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// fixed update is for physics
void FixedUpdate()
{
var dir = Vector3.zero;
if (Input.GetKey(KeyCode.LeftArrow) && leftInput && isGrounded)
{
dir = Vector3.left;
}
if (Input.GetKey(KeyCode.RightArrow) && rightInput && isGrounded)
{
dir = Vector3.right;
}
if (dir !=Vector3.zero && !isRolling)
{
StartCoroutine(Roll(dir));
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
//check to see if our player is grounded
if (collision.gameObject.tag == "Grounded")
{
isGrounded = true;
}
if (collision.gameObject.tag == "LeftWall" || collision.gameObject.tag == "RightWall")
{
StopCoroutine("Roll");
if (collision.gameObject.tag == "LeftWall")
{
leftInput = false;
// we are grounded when touching walls
isGrounded = true;
}
if (collision.gameObject.tag == "RightWall")
{
rightInput = false;
// we are grounded when touching walls
isGrounded = true;
}
if (collision.gameObject.tag == null)
{
isGrounded = false;
}
else
{
isRolling = false;
rb.velocity = Vector2.zero;
rb.velocity = new Vector2(0.0f, 0.0f);
rb.angularVelocity = 0.0f;
rb.transform.rotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
rb.rotation = 0.0f;
}
}
}
bool isRolling = false;
IEnumerator Roll(Vector3 direction)
{
if (direction == Vector3.right && isGrounded)
{
leftInput = true;
}
else if (direction == Vector3.left && isGrounded)
{
rightInput = true;
}
isRolling = true;
var rotAxis = Vector3.Cross(Vector3.up, direction);
var pivot = (rb.transform.position + Vector3.down * 0.5f) + direction * 0.5f;
var startRotation = rb.transform.rotation;
var endRotation = Quaternion.AngleAxis(90.0f, rotAxis) * startRotation;
var startPosition = rb.transform.position;
var endPosition = rb.transform.position + direction;
var rotSpeed = 90.0f / RollingDuration;
var t = 0.0f;
while (t < RollingDuration && isGrounded)
{
t += Time.deltaTime;
if (t < RollingDuration && isGrounded)
{
rb.transform.RotateAround(pivot, rotAxis, rotSpeed * Time.deltaTime);
yield return null;
}
else
{
rb.transform.rotation = endRotation;
rb.transform.position = endPosition;
}
}
isRolling = false;
}
}
I think the most simple and common way to do ground checks is with casting a ray. So just cast a ray into the direction you want to check or try Overlap functions.
Example:
if(Physics.OverlapCircle(point, radius, layerMask)) {
//do stuff
}
So just cast a ray in all direction you want to check or add a overlap function to each side of the cube.
I am new to coding. I've been trying to Frankenstein basic tutorials into something of my own and it seems ive finally hit a wall. I'm really not sure what is causing this and would like some help to weed out the problem.
at the moment when I press the dash button (left shift) my character dashes in the direction he is facing but for a random duration. I would like it to be consistent and working properly.
Thanks in advance!
PS: Sorry for the long script, it contains everything to do with player movment.
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
//Player Movement
public float speed;
public float jumpForce;
public Transform feetPos;
public float checkRadius;
public LayerMask whatIsGround;
public float dashSpeed;
public float startDashTime;
public float dashCooldownTime = 2;
private float nextFireTime = 0;
public Animator animator;
private Rigidbody2D rb;
private float moveInput;
private bool isGrounded;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private float dashTime;
public int direction;
void Start()
{
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
}
void FixedUpdate()
{
moveInput = Input.GetAxisRaw("Horizontal");
if (direction < 1 )
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
}
void Update()
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
// Dashing
if (Time.time > nextFireTime)
{
if (direction == 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
UnityEngine.Debug.Log("beaners");
nextFireTime = Time.time + dashCooldownTime;
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
}
else
{
if(dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
}
else
{
dashTime -= Time.deltaTime;
}
}
}
void Dashleft()
{
direction = 1;
rb.velocity = Vector2.left * dashSpeed;
}
void DashRight()
{
direction = 1;
rb.velocity = Vector2.right * dashSpeed;
}
}
Random duration is because of the use of Rigidbody2D.
See in Unity Rigidbody2D is responsible for each and every single physical interaction. It mean forces from player like player movement and forces from your environment like friction and collision.
Here what is happening is that when your player is dashing there is also player movement force, which is also applied on your player's Rigidbody2d. And friction of ground on which your player is running/dashing on.
I've added a comment on parts that I've changed.
Updated part of your script:
private bool isDashing;
.
.
.
void Update()
{
//Added: putting a Condition to check if you player is not dashing, if it is then
//player won't be able to do anything, As I've scene and done in many games. if you
//don't want this remove it and see what happens, this is not tested so sorry if there
//is something that is not working as intended.
//dashing condition check
if(!isDashing)
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
//Changed: use Add force method instead of changing the velocity.
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
//rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
//Changed: Same this rb.AddForce...
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
//rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
}
//dashing condition ends
// Dashing
if (Time.time > nextFireTime)
{
//Here your Dash timer ends.
isDashing = false;
if (direction == 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
UnityEngine.Debug.Log("beaners");
nextFireTime = Time.time + dashCooldownTime;
//Here your Dash timer Starts.
isDashing = true;
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
}
else
{
if(dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
}
else
{
dashTime -= Time.deltaTime;
}
}
}
visit Unity - Scripting API: Rigidbody2D.AddForce hope it helps.
Happy Coding
My problem is for a wall jump.
I basically want my wall jump to have a bit of force away from to wall to make it look and feel better than just jumping up straight.
The problem is, when I add a force on the x axis, it does not register when I am also holding the arrow towards the wall. If I am not holding down the walking button, then press jump, then the x force works.
I have a feeling that the horizontal axis force is competing with the opposite force that I want to add to the player when he hits the jump button.
Walking code:
private void ApplyMovement()
{
if (isGrounded)
{
myRigidbody.velocity = new Vector2(movementSpeed * movementInputDirection, myRigidbody.velocity.y);
}
else if (!isGrounded && !isWallSliding && movementInputDirection != 0)
{
Vector2 forceToAdd = new Vector2(movementForceInAir * movementInputDirection, 0);
myRigidbody.AddForce(forceToAdd);
if (Mathf.Abs(myRigidbody.velocity.x) > movementSpeed)
{
myRigidbody.velocity = new Vector2(movementSpeed * movementInputDirection, myRigidbody.velocity.y);
}
}
else if (!isGrounded && !isWallSliding && movementInputDirection == 0)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x * airDragMultiplier, myRigidbody.velocity.y);
}
if (isWallSliding)
{
if (myRigidbody.velocity.y < -wallSlideSpeed)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, -wallSlideSpeed);
}
}
}
Jump code:
private void Jump()
{
if (canJump && !isWallSliding)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
numberOfJumpsLeft--;
}
else if ((isWallSliding || isTouchingWall) && !isGrounded && canJump)
{
isWallSliding = false;
numberOfJumpsLeft--;
Vector2 forceToAdd = new Vector2(wallPushForce * -facingDirection, wallJumpForce *
wallJumpDirection.y);
myRigidbody.AddForce(forceToAdd, ForceMode2D.Impulse);
}
}
I am trying to make a player spaceship move between three points when the user enters left or right on the keyboard. I would like the player to move smoothly between these points but it seems that the Lerp function is only interpolated once.
Here is the Game master script which checks for input from the user and passes it onto the Player controller which performs the Lerp:
Game master:
void Update ()
{
if (gameIsRunning)
{
if (Input.GetKeyDown(KeyCode.A))
{
//Go Left
player.MovePlayer("left");
}
else if (Input.GetKeyDown(KeyCode.D))
{
//Go Right
player.MovePlayer("right");
}
//Only run this if the game is running...
if (player.Lives <= 0)
{
gameIsRunning = false;
}
}
}
Player controller:
public void MovePlayer (string dir)
{
if (dir == "left")
{
if (currentPosition == Position.Left)
{
//Do Nothing!
return;
}
if (currentPosition == Position.Middle)
{
transform.position = Vector3.Lerp(middlePos.position, leftPos.position, .5f);
currentPosition = Position.Left;
}
if (currentPosition == Position.Right)
{
transform.position = Vector3.Lerp(rightPos.position, middlePos.position, .5f);
currentPosition = Position.Middle;
}
}
if (dir == "right")
{
if (currentPosition == Position.Right)
{
//Do Nothing!
return;
}
if (currentPosition == Position.Middle)
{
transform.position = Vector3.Lerp(transform.position, rightPos.position, .5f);
currentPosition = Position.Right;
}
if (currentPosition == Position.Left)
{
transform.position = Vector3.Lerp(transform.position, middlePos.position, .5f);
currentPosition = Position.Middle;
}
}
}
Screenshot:
Why is this happening?
lerp must be called with a changing parameter. try something like:
Player controller:
enum Direction
{
Left,
Right
}
Direction moveDir;
float progress;
public void MovePlayer (Direction dir)
{
moveDir = dir;
progress = 0.0f;
}
public void Update()
{
switch(dir)
{
case Direction.Left:
if (currentPosition == Position.Middle)
{
transform.position = Vector3.Lerp(middlePos.position, leftPos.position, progress);
if(progress >= 1.0f)
currentPosition = Position.Left;
else
progress += 0.1f; // change as necessary
}
if (currentPosition == Position.Right)
{
transform.position = Vector3.Lerp(rightPos.position, middlePos.position, progress);
if(progress >= 1.0f)
currentPosition = Position.Middle;
else
progress += 0.1f; // change as necessary
}
break;
case Direction.Right:
// ...
break;
}
}