I have a script that detect when player is touching a layer named "Ground", and it works pretty well, but my problem is when I use the "Platform Effector 2D" that allows me jump through the plataform. So, when my character is passsing through the plataform, my bool "isGrounded" gets true, but he is actually not in ground, what happens is that the point that I use to check is "colliding" with the object that countains the layer Ground.
I don't think I can explain it very well, so I upload a not listed video on Youtube to show
www.youtube.com/watch?v=EQpF4iSNC0Yt
here's the code
[Header("Components")]
[HideInInspector]public Rigidbody2D _rb;
[Header("Layer Masks")]
[SerializeField] private LayerMask groundLayer;
[Header("Movement Variables")]
[SerializeField] private float _movementAcceleration;
[SerializeField] private float _maxMoveSpeed;
[SerializeField] private float _linearDrag;
[SerializeField] private float dashPower;
private float horizontalDirection;
private bool changingDirection => (_rb.velocity.x > 0f && horizontalDirection < 0f) || (_rb.velocity.x < 0f && horizontalDirection > 0f);
public bool isFalling => _rb.velocity.y < 0.0f;
private bool isRunning => horizontalDirection != 0;
[Header("Jump Variables")]
[SerializeField] private float jumpForce = 12f;
[SerializeField] private float airLinearDrag = 2.5f;
[SerializeField] private float fallMultiplier = 8f;
[SerializeField] private float lowJumpFallMultiplier = 5f;
private bool canJump => Input.GetButtonDown("Jump") && isGround;
[Header("Ground Colission Variables")]
[SerializeField] private float groundRayCastLenght;
private bool isGround;
private bool jumped;
private bool facinRight = true;
private Animator animator;
private SpriteRenderer sprite;
GameController controller;
public Transform groundCheck ;
public bool canPassThrough = false;
void Start()
{
sprite = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
_rb = GetComponent<Rigidbody2D>();
controller = FindObjectOfType<GameController>();
}
// Update is called once per frame
void Update()
{
Debug.Log(_rb.velocity.y);
isGround = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
horizontalDirection = GetInput().x;
if(canJump && !controller.gamePaused){
Jump();
}
if(Input.GetKeyDown(KeyCode.LeftShift)){
ApplyDash();
}
setAnimations();
}
void FixedUpdate()
{
//CheckCollisions();
if(!controller.gamePaused){
//checkDirection();
MoveCharacter();
}
if(isGround){
jumped = false;
ApplyLinearDrag();
}else{
ApplyAirLinearDrag();
FallMultiplier();
}
}
private Vector2 GetInput()
{
return new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
}
private void MoveCharacter(){
if(horizontalDirection < 0 && facinRight || horizontalDirection > 0 && !facinRight){
checkDirection();
}
Vector3 v = _rb.velocity;
_rb.AddForce(new Vector2(horizontalDirection* _movementAcceleration, 0f) );
if(Mathf.Abs(_rb.velocity.x) > _maxMoveSpeed){
v.x = Mathf.Sign(_rb.velocity.x) * _maxMoveSpeed;
_rb.velocity = v;
//_rb.velocity = new Vector2(Mathf.Sign(_rb.velocity.x) * _maxMoveSpeed, _rb.velocity.y );
}
}
private void CheckCollisions(){
isGround = Physics2D.Raycast(transform.position * groundRayCastLenght, Vector2.down, groundRayCastLenght, groundLayer);
}
private void ApplyLinearDrag(){
if(Mathf.Abs(horizontalDirection) < 0.4f || changingDirection){
_rb.drag = _linearDrag;
}else{
_rb.drag = 0f;
}
}
private void ApplyDash(){
_rb.AddForce(new Vector2(horizontalDirection * dashPower, _rb.velocity.y));
}
void ApplyAirLinearDrag(){
_rb.drag = airLinearDrag;
}
void Jump(){
jumped = true;
if(horizontalDirection != 0){
_rb.velocity = new Vector2(_rb.velocity.x, 0f);
_rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}else{
_rb.velocity = new Vector2(_rb.velocity.x, 0f);
_rb.AddForce(Vector2.up * jumpForce * 2f, ForceMode2D.Impulse);
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, transform.position + Vector3.down * groundRayCastLenght);
}
void FallMultiplier(){
if(_rb.velocity.y < 0){
_rb.gravityScale = fallMultiplier;
}else if(_rb.velocity.y > 0 && !Input.GetButtonDown("Jump")){
_rb.gravityScale = lowJumpFallMultiplier;
}else{
_rb.gravityScale = 1f;
}
}
void setAnimations(){
animator.SetBool("Run", isRunning && isGround);
animator.SetBool("isGround", isGround);
animator.SetBool("Jump", jumped);
animator.SetBool("isFalling", isFalling);
animator.SetFloat("eixoY", Mathf.Abs(_rb.velocity.y));
}
void checkDirection(){
facinRight = !facinRight;
transform.localScale = new Vector3( - transform.localScale.x, transform.localScale.y, transform.localScale.z);
}
void OnCollisionEnter2D(Collision2D other)
{
if(LayerMask.LayerToName(other.gameObject.layer) == "Ground") //check layer is ground
{
if (gameObject.GetComponent<Rigidbody2D>().velocity.y <= 0) //check velocity.y is 0
{
Debug.Log("in ground"); //debug console
canPassThrough = false;
}else{
Debug.Log("Not in ground");
canPassThrough = true;
}
}
}
If we want to perform the debug operation when we touch it, we can perform the operation successfully by checking that the velocity.y is 0 at the moment it touches.
like this:
private void OnCollisionEnter2D(Collision2D collision)
{
if(LayerMask.LayerToName(collision.gameObject.layer) == "Ground") //check layer is ground
{
if (gameObject.GetComponent<Rigidbody2D>().velocity.y <= 0) //check velocity.y is 0
{
Debug.Log("in ground"); //debug console
}
}
}
Related
I have coded the unity movement for my character. I made it so they can wall run bit it seems that wall running is somehow making my character walk weird. After wall running (if I wall run with the wall on my right) it will apply a force 90 degrees when I'm walking on the ground. The unknown force changes when each button is pressed (is W then apply both the W force and a force pushing it to the right). And the same happens with running on the left wall but it is at a -90 degree angle. Please help I've been stuck on this for a whole week. Thanks
This is the wall running code
using System.Collections.Generic;
using UnityEngine;
public class MoveChar : MonoBehaviour
{
[Header("Movement")]
float moveSpeed;
[SerializeField] float walkSpeed;
[SerializeField] float sprintSpeed;
[SerializeField] float slideSpeed;
[SerializeField] float wallRunSpeed;
float desiredMoveSpeed;
float lastDesiredMoveSpeed;
[SerializeField] float groundDrag;
[Header("Jumping")]
[SerializeField] float jumpForce;
[SerializeField] float jumpCoolDown;
[SerializeField] float airMultiplier;
bool readyToJump;
[HideInInspector] public bool doubleJump;
[Header("Crouching")]
[SerializeField] float crouchSpeed;
[SerializeField] float crouchYScale;
float crouchYStart;
bool exitingJump;
[Header("Slope Check")]
[SerializeField] float maxSlope;
RaycastHit slopeHit;
[Header("Ground Check")]
[SerializeField] float playerHeight;
[SerializeField] LayerMask whatIsGround;
bool grounded;
[Header("Keybinds")]
KeyCode jumpKey = KeyCode.Space;
KeyCode walkKey = KeyCode.LeftShift;
KeyCode crouchKey = KeyCode.C;
[SerializeField] Transform orientation;
[SerializeField] Transform camRotate;
float horizontalInput;
float verticalInput;
Vector3 moveDirection;
Rigidbody rb;
MovementState state;
enum MovementState
{
walking,
sprinting,
crouching,
sliding,
wallRunning,
air
}
[HideInInspector] public bool sliding;
[HideInInspector] public bool wallRunning;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
ResetJump();
crouchYStart = transform.localScale.y;
}
// Update is called once per frame
void Update()
{
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);
MyInput();
SpeedControl();
StateHandler();
if (grounded)
{
rb.drag = groundDrag;
}
else
{
rb.drag = 0;
}
}
private void FixedUpdate()
{
MovePlayer();
}
void MyInput()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
if (Input.GetKeyDown(jumpKey) && readyToJump && (grounded || doubleJump))
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCoolDown);
}
if (grounded && !Input.GetKey(jumpKey))
{
doubleJump = false;
}
if (Input.GetKeyDown(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z);
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
}
if (Input.GetKeyUp(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, crouchYStart, transform.localScale.z);
}
}
void StateHandler()
{
if (wallRunning)
{
state = MovementState.wallRunning;
desiredMoveSpeed = wallRunSpeed;
doubleJump = false;
}
if (sliding)
{
state = MovementState.sliding;
if (OnSlope() && rb.velocity.y < 0.1f)
{
desiredMoveSpeed = slideSpeed;
}
else
{
desiredMoveSpeed = sprintSpeed;
}
}
else if (Input.GetKey(crouchKey))
{
state = MovementState.crouching;
desiredMoveSpeed = crouchSpeed;
}
else if (grounded && Input.GetKey(walkKey))
{
state = MovementState.walking;
desiredMoveSpeed = walkSpeed;
}
else if (grounded)
{
state = MovementState.sprinting;
desiredMoveSpeed = sprintSpeed;
}
else
{
state = MovementState.air;
}
if (Mathf.Abs(desiredMoveSpeed - lastDesiredMoveSpeed) > 4f && moveSpeed != 0)
{
StopAllCoroutines();
StartCoroutine(SmoothlyLerpMoveSpeed());
}
else
{
moveSpeed = desiredMoveSpeed;
}
lastDesiredMoveSpeed = desiredMoveSpeed;
}
IEnumerator SmoothlyLerpMoveSpeed()
{
float time = 0;
float difference = Mathf.Abs(desiredMoveSpeed - moveSpeed);
float startValue = moveSpeed;
while (time < difference)
{
moveSpeed = Mathf.Lerp(startValue, desiredMoveSpeed, time / difference);
time += Time.deltaTime;
yield return null;
}
moveSpeed = desiredMoveSpeed;
}
void MovePlayer()
{
moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
if (OnSlope() && !exitingJump)
{
rb.AddForce(GetSlopeMoveDirection(moveDirection) * moveSpeed * 20f, ForceMode.Force);
if (rb.velocity.y > 0)
{
rb.AddForce(Vector3.down * 80f, ForceMode.Force);
}
}
else if (grounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
}
else if (!grounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
}
if (!wallRunning)
{
rb.useGravity = !OnSlope();
}
}
void SpeedControl()
{
if (OnSlope() && !exitingJump)
{
if (rb.velocity.magnitude > moveSpeed)
{
rb.velocity = rb.velocity.normalized * moveSpeed;
}
}
else
{
Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
if (flatVel.magnitude > moveSpeed)
{
Vector3 limitVel = flatVel.normalized * moveSpeed;
rb.velocity = new Vector3(limitVel.x, rb.velocity.y, limitVel.z);
}
}
}
void Jump()
{
exitingJump = true;
rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
doubleJump = !doubleJump;
}
void ResetJump()
{
readyToJump = true;
exitingJump = false;
}
public bool OnSlope()
{
if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, playerHeight * 0.5f + 0.3f))
{
float angle = Vector3.Angle(Vector3.up, slopeHit.normal);
return angle < maxSlope && angle != 0;
}
return false;
}
public Vector3 GetSlopeMoveDirection(Vector3 direction)
{
return Vector3.ProjectOnPlane(direction, slopeHit.normal).normalized;
}
}
This is the wall running code
using System.Collections.Generic;
using UnityEngine;
public class WallRunning : MonoBehaviour
{
[Header("Wallrunning")]
[SerializeField] LayerMask whatIsRunAble;
[SerializeField] LayerMask whatIsGround;
[SerializeField] float wallRunForce;
[SerializeField] float wallRunUpForce;
[SerializeField] float wallRunSideForce;
[SerializeField] float wallClimbSpeed;
[Header("Input")]
KeyCode jumpKey = KeyCode.Space;
float horizontalInput;
float verticalInput;
[Header("Detection")]
[SerializeField] float wallCheckDistance;
[SerializeField] float minJumpHeight;
RaycastHit leftWallHit;
RaycastHit rightWallHit;
bool wallLeft;
bool wallRight;
[Header("Exiting")]
[SerializeField] float exitWallTime;
bool exitingWall;
float exitWallTimer;
[Header("Gravity")]
[SerializeField] bool useGravity;
[SerializeField] float gravityCounterForce;
[Header("References")]
[SerializeField] Transform orientation;
MoveChar mc;
Rigidbody rb;
[SerializeField] Transform cam;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
mc = GetComponent<MoveChar>();
}
// Update is called once per frame
void Update()
{
CheckForWall();
StateMachine();
}
private void FixedUpdate()
{
if (mc.wallRunning)
{
WallRunMove();
}
}
void CheckForWall()
{
wallRight = Physics.Raycast(transform.position, orientation.right, out rightWallHit, wallCheckDistance, whatIsRunAble);
wallLeft = Physics.Raycast(transform.position, -orientation.right, out leftWallHit, wallCheckDistance, whatIsRunAble);
}
bool AboveGround()
{
return !Physics.Raycast(transform.position, Vector3.down, minJumpHeight, whatIsGround);
}
void StateMachine()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
if ((wallLeft || wallRight) && verticalInput > 0 && AboveGround() && !exitingWall)
{
if (Input.GetKeyDown(jumpKey))
{
WallJump();
}
}
if ((wallLeft || wallRight) && verticalInput > 0 && AboveGround() && !exitingWall)
{
if (!mc.wallRunning)
{
StartWallRun();
}
}
else if (exitingWall)
{
if (mc.wallRunning)
{
StopWallRun();
}
if (exitWallTimer > 0)
{
exitWallTimer -= Time.deltaTime;
}
if (exitWallTimer <= 0)
{
exitingWall = false;
}
}
else
{
if (mc.wallRunning)
{
StopWallRun();
}
}
}
void StartWallRun()
{
mc.wallRunning = true;
rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
if (wallRight)
{
cam.localRotation = Quaternion.Euler(0, 0, 10f);
}
if (wallLeft)
{
cam.localRotation = Quaternion.Euler(0, 0, -10f);
}
}
void WallRunMove()
{
rb.useGravity = useGravity;
Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal;
Vector3 wallForward = Vector3.Cross(wallNormal, transform.up.normalized);
if ((orientation.forward - wallForward).magnitude > (orientation.forward - -wallForward).magnitude)
{
wallForward = -wallForward;
}
rb.AddForce(wallForward * wallRunForce, ForceMode.Force);
/*if (!(wallLeft && horizontalInput > 0) && !(wallRight && horizontalInput < 0))
{
rb.AddForce(-wallNormal * 100, ForceMode.Force);
}
if (useGravity)
{
rb.AddForce(transform.up * gravityCounterForce, ForceMode.Force);
}*/
}
void StopWallRun()
{
mc.wallRunning = false;
cam.localRotation = Quaternion.Euler(0, 0, 0);
}
void WallJump()
{
exitingWall = true;
exitWallTimer = exitWallTime;
Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal;
Vector3 forceToApply = transform.up * wallRunUpForce + wallNormal * wallRunSideForce;
rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
rb.AddForce(forceToApply, ForceMode.Impulse);
mc.doubleJump = !mc.doubleJump;
}
}
Thank you soooooooo much for any help
I've got my player sprite that has a blank "Front Check" object nested underneath it. The nested item is used to check if the front of the sprite is touching a wall. the problem I'm having is the Front Check object does not flip with the sprite when I move in the opposite direction. it was working fine earlier today and then out of the blue just quit. This is my first unity project and I'm just not quite sure what's missing. Any help is much appreciated. here is an image of the project and my movement script.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Rigidbody2D rb;
private BoxCollider2D coll;
private SpriteRenderer sprite;
private Animator anim;
[SerializeField] private LayerMask jumpableGround;
public float checkRadius;
bool isTouchingFront;
public Transform frontCheck;
public float wallSlidingSpeed;
bool wallSliding;
bool wallJumping;
public float xWallForce;
public float yWallForce;
public float wallJumpTime;
private float dirX = 0f;
[SerializeField] private float moveSpeed = 7f;
[SerializeField] private float jumpForce = 14f;
[SerializeField] private float airControl;
private enum MovementState { idle, running, jumping, falling }
[SerializeField] private AudioSource JumpSoundEffect;
// Start is called before the first frame update
private void Start()
{
rb = GetComponent<Rigidbody2D>();
coll = GetComponent<BoxCollider2D>();
sprite = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
private void Update()
{
dirX = Input.GetAxisRaw("Horizontal");
if (dirX < 0 && IsGrounded())
{
rb.velocity = new Vector2(moveSpeed * -1, rb.velocity.y);
}
else if (dirX > 0 && IsGrounded())
{
rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
}
else if (dirX == 0 && IsGrounded())
{
rb.velocity = new Vector2(0, rb.velocity.y);
}
if (Input.GetButtonDown("Jump") && IsGrounded())
{
JumpSoundEffect.Play();
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
UpdateAnimationState();
}
private void UpdateAnimationState()
{
MovementState state;
if (dirX > 0f && IsGrounded())
{
state = MovementState.running;
}
else if (dirX < 0f && IsGrounded())
{
state = MovementState.running;
}
else
{
state = MovementState.idle;
}
if (rb.velocity.y > .1f)
{
state = MovementState.jumping;
}
else if (rb.velocity.y < -.1f)
{
state = MovementState.falling;
}
//Wall Jump
isTouchingFront = Physics2D.OverlapCircle(frontCheck.position, checkRadius, jumpableGround);
if (isTouchingFront == true && IsGrounded() == false && dirX != 0)
{
wallSliding = true;
}
else
{
wallSliding = false;
}
if (wallSliding)
{
rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -wallSlidingSpeed, float.MaxValue));
}
if (Input.GetButtonDown("Jump") && wallSliding == true)
{
wallJumping = true;
Invoke("SetWallJumpingToFalse", wallJumpTime);
}
if (wallJumping == true)
{
rb.velocity = new Vector2(xWallForce * -Input.GetAxisRaw("Horizontal"), yWallForce);
}
anim.SetInteger("state", (int)state);
}
void SetWallJumpingToFalse()
{
wallJumping = false;
}
public bool IsGrounded()
{
return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, .1f, jumpableGround);
}
public void FixedUpdate()
{
if (dirX > 0f)
{
sprite.flipX = false;
}
else if (dirX < 0f)
{
sprite.flipX = true;
}
}
}
sprite.flipX only flips the rendering not the actual object scaling.
You rather want to use e.g.
var scale = transform.localScale;
scale.x = Mathf.Sign(dirX);
transform.localScale = scale;
Note that it needs to be UnityEngine.Mathf.Sign and not System.Math.Sign since the latter returns 0 for parameter 0 which would totally break your colliders etc. while Mathf.Sign returns only -1 or 1.
so i'm trying to achieve a player thats stops whenever the user lets go of the key, i don't want it to slide, i have a vertical variable and a horizontal variable that stores the axis, if these values are less or more than zero, than the bool isMoving is set to true, else it's set to false, this works wonderful on the vertical azis but not on the horizontal axis, i tried even making if statements checking when the keys are pressed and when they are not
like this
if(Input.GetKeyDown(KeyCode.A))
{
isMoving = true;
}
if(Input.GetKeyDown(KeyCode.D))
{
isMoving = true;
}
if(Input.GetKeyUp(KeyCode.A))
{
isMoving = false;
}
if(Input.GetKeyUp(KeyCode.D))
{
isMoving = false;
}
this also did not work,
this is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("Player Values")]
[SerializeField] private float playerSpeed = 50f;
[SerializeField] private float jumpHeight = 7f;
[Header("Ground Check")]
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask ground;
private float checkLenght = 0.1f;
private Rigidbody rb;
private float horizontal;
private float vertical;
// Crouch Scales
private Vector3 initialScale;
private Vector3 crouchScale;
// Counter Movement
private bool isMoving;
private bool isOnGround;
private float counterDrag = 10f;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
// Crouch Scales
initialScale = new Vector3(1f, 1f, 1f);
crouchScale = new Vector3(1f, 0.5f, 1f);
// Player Movement
MovePlayer();
// Counter Movement
ApplyCounterMovement();
// Check Ground
isOnGround = Physics.CheckSphere(groundCheck.position, checkLenght, ground);
}
private void Update()
{
CheckInput();
}
private void MovePlayer()
{
horizontal = Input.GetAxis("Horizontal") * playerSpeed;
vertical = Input.GetAxis("Vertical") * playerSpeed;
Vector3 movement = transform.forward * vertical + transform.right * horizontal;
rb.AddForce(movement, ForceMode.Acceleration);
}
private void CheckInput()
{
if(Input.GetKeyDown(KeyCode.LeftShift))
{
getDown();
}
if(Input.GetKeyUp(KeyCode.LeftShift))
{
getUp();
}
// Check Counter Movement
if (horizontal > 0f || horizontal < 0f)
{
isMoving = true;
}
else
{
isMoving = false;
}
if (vertical > 0f || vertical < 0f)
{
isMoving = true;
}
else
{
isMoving = false;
}
// Check Jump
if(Input.GetKeyDown(KeyCode.Space))
{
Jump();
}
}
// Crouch
private void getDown()
{
transform.localScale = crouchScale;
transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
}
// Get Up From Crouching
private void getUp()
{
transform.localScale = initialScale;
transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
}
// Apply Counter Movement
private void ApplyCounterMovement()
{
if(isMoving == true)
{
rb.drag = 0f;
return;
}
if(isMoving == false)
{
rb.drag = counterDrag;
}
}
private void Jump()
{
if (isOnGround == false)
{
return;
}
if(isOnGround == true)
{
rb.AddForce(Vector3.up * jumpHeight, ForceMode.VelocityChange);
}
}
}
Your if checks for the vertical into overrule the ones before for the horizontal since both of them set the same field isMoving.
Rather combine them into e.g.
isMoving = horizontal != 0f || vertical != 0f;
I created a script to make the character dash to the left or to the right but no matter what I do the character won't get pushed horizontally, when I switch it so that the character is pushed upwards the vector does work.
at the vectors there are two different ways of using methods because i tried both to see if either would work but they didn't.
here's the script.
public float speed;
public float jumpForce;
public float inputHorizontal;
public Rigidbody2D rb;
public float checkRadius;
bool isGrounded;
public Transform groundCheck;
public LayerMask whatIsGround;
public float dashSpeed;
public float dashTimeValue;
private float dashTime;
int extraJumps;
public int extraJumpsValue;
private bool facingRight = true;
void Start()
{
rb = GetComponent<Rigidbody2D>();
dashTime = dashTimeValue;
}
void Update()
{
if(isGrounded == true)
{
extraJumps = extraJumpsValue;
}
if(Input.GetKeyDown(KeyCode.Space) && extraJumps > 0)
{
rb.velocity = new Vector2(0f, jumpForce);
extraJumps = extraJumps - 1;
}
if(Input.GetKeyDown(KeyCode.F))
{
if(dashTime == dashTimeValue && facingRight == true)
{
rb.velocity = new Vector2(dashSpeed, 1f);
Debug.Log("eh");
dashTime -= Time.deltaTime;
}else if(dashTime == dashTimeValue && facingRight == false)
{
rb.velocity = Vector2.left * dashSpeed;
Debug.Log("eh");
dashTime -= Time.deltaTime;
}
dashTime = dashTimeValue;
}
}
void FixedUpdate()
{
inputHorizontal = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(inputHorizontal * speed, rb.velocity.y);
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
if(facingRight == false && inputHorizontal > 0){
Flip();
}else if(facingRight == true && inputHorizontal < 0){
Flip();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
I'm trying to find a way to rotate the enemy towards the player. Currently it follows/stops and shoots the player. Have not figured out how to make it rotate. Please help if you can. I've tried couple of different things on here but they dont seem to work.
I've tried creating a Flip function with isFacingRight.
private bool facingRight;
public float speed;
public float stoppingDistance;
public float retreatDistance;
private Animator enemyAnimation;
private bool isDead;
private float direction;
public static bool enemyShoot = false;
private float timeBtwShots;
public float startTimeBtwShots;
public GameObject projectile;
private Transform player;
[SerializeField]
private Stat health;
private void Awake()
{
health.Initialize();
}
// Start is called before the first frame update
void Start()
{
//Player tag
player = GameObject.FindGameObjectWithTag("Player").transform;
enemyAnimation = GetComponent<Animator>();
isDead = false;
}
// Update is called once per frame
void Update()
{
if (Vector2.Distance(transform.position, player.position) > stoppingDistance)
{
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
timeBtwShots = startTimeBtwShots;
if(player.position.x > transform.position.x && !facingRight) //if the target is to the right of enemy and the enemy is not facing right
Flip();
if(player.position.x < transform.position.x && facingRight)
Flip();
}
else if (Vector2.Distance(transform.position,player.position) <= stoppingDistance && Vector2.Distance(transform.position,player.position)>retreatDistance)
{
transform.position = this.transform.position;
}
else if (Vector2.Distance(transform.position, player.position) > retreatDistance)
{
transform.localScale = new Vector2(-1f, 1f);
transform.position = Vector2.MoveTowards(transform.position, player.position, -speed * Time.deltaTime);
timeBtwShots = 100;
enemyAnimation.SetTrigger("Attack");
}
if (enemyShoot == true)
{
//Stops animation Loop
enemyShoot = false;
enemyAnimation.SetTrigger("Shoot");
}
if (timeBtwShots <= 0)
{
Instantiate(projectile, transform.position, Quaternion.identity);
timeBtwShots = startTimeBtwShots;
}
else
{
timeBtwShots -= Time.deltaTime;
}
if (health.CurrentVal == 0)
{
timeBtwShots = 100;
FindObjectOfType<SoundsScript>().Play("SaibaDeath");
isDead = true;
enemyAnimation.SetBool("Dead", isDead);
Destroy(gameObject, 2f);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "ProjectileEnem")
{
health.CurrentVal -= 50;
enemyAnimation.SetTrigger("Hurt");
}
}
//Disables enemeies when off screen
private void OnBecameInvisible()
{
GetComponent <Enemy> ().enabled = false;
}
//Re enables enemies once they are visible
private void OnBecameVisible()
{
GetComponent<Enemy>().enabled = true;
}
void Flip(){
Vector3 scale = transform.localScale;
scale.x *= -1;
transform.localScale = scale;
facingRight = !facingRight;
}
}
Try this:
spriteRenderer.flipX = transform.position.x < player.position.x;
SpriteRenderer contains the flipX and flipY property, you do not need to create your own Flip() function.
You need a reference to the SpriteRenderer on your GameObject.
The above code is assuming that your sprite faces left on default. If your sprite faces right normally, change the < to >.