I'm new to programming and i had this problem coming up, whenever i use Input.GetKeyDown(KeyCode.Mouse0) to attack with my character, it fires maybe 3 out of 10 times, i tried changing many variables and trying to put the code in diferent places but i couldn't find the fix to it
here's the code :
private void Update()
{
dirX = Input.GetAxisRaw("Horizontal") ;
rb.velocity = new Vector2(moveSpeed * dirX , rb.velocity.y) ;
if(Input.GetButtonDown("Jump") && (IsGrounded()))
{
rb.velocity = new Vector3(rb.velocity.x,jumpForce,0);
}
UpdateAnimationState();
if(attackTime <= 0)
{
if(Input.GetKeyDown(KeyCode.Mouse0))
{
anim.SetBool("attacking", true);
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll( attackLocation.position, attackRange, enemies );
for (int i = 0; i < enemiesToDamage.Length; i )
{
enemiesToDamage[i].GetComponent<Enemy_health>().TakeDamage(damage);
}
}
attackTime = startTimeAttack;
}
else
{
attackTime -= Time.deltaTime;
anim.SetBool("attacking", false);
}
if(attackTime <= 0)
{
if( Input.GetKeyDown(KeyCode.Mouse0))
{
if(rb.velocity.y > .01f || rb.velocity.y < -.01f)
{
anim.SetBool("jumpattacking", true);
Collider2D[] damage = Physics2D.OverlapCircleAll( attackLocation.position, attackRange, enemies );
for (int i = 0; i < damage.Length; i )
{
Destroy( damage[i].gameObject );
}
}
}
attackTime = startTimeAttack;
}
else
{
attackTime -= Time.deltaTime;
anim.SetBool("jumpattacking", false);
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(attackLocation.position, attackRange);
}
CodePudding user response:
How should the jumpattacking
case be ever reached?
Either the
attackTime
is higher than0
or the firstattacking
case already kicks in and setsattackTime = startTimeAttack
immediately - regardless of the input!→ You rather want to start the cooldown only if you actually attacked!
And then still the
jumpattacking
could not be reached because theattacking
case already consumes your input first and sets the timer.Finally the way you are using the animator Bool parameters looks like you would be better using Tigger instead which is used for one time changing to a certain state and reset the trigger.
I don't know how your animator is configured but it might be that since you immediately reset the bool parameters in the next frame it immediately transitions back to the idle state.
What you should probably do is rather merging both cases together like e.g.
private void Update()
{
dirX = Input.GetAxisRaw("Horizontal") ;
rb.velocity = new Vector2(moveSpeed * dirX , rb.velocity.y) ;
if(Input.GetButtonDown("Jump") && IsGrounded())
{
rb.velocity = new Vector3(rb.velocity.x, jumpForce, 0);
}
UpdateAnimationState();
if(attackTime <= 0)
{
if(Input.GetKeyDown(KeyCode.Mouse0))
{
// simply store this in a variable instead of implementing the same code twice
// Use the absolute to simply check the magnitude regardless of the sign
var isJumping = Mathf.Abs(rb.velocity.y) > 0.01f;
// Use ternary for switching between the two bools according to the isJumping
anim.SetBool(isJumping ? "jumpattacking" : "attacking", true);
// disable the according other bool (?)
// As said rather using Trigger would already solve this
//anim.SetBool(isJumping ? "attacking" : "jumpattacking", false);
var enemiesToDamage = Physics2D.OverlapCircleAll(attackLocation.position, attackRange, enemies);
foreach (var enemy in enemiesToDamage)
{
// again decide for the resulting action according to isJumping
if(isJumping)
{
Destroy(enemy.gameObject);
}
else
{
enemy.GetComponent<Enemy_health>().TakeDamage(damage);
}
}
// You only want to do this once you actually consumed the User input
attackTime = startTimeAttack;
}
}
else
{
attackTime -= Time.deltaTime;
// rather using Trigger parameters wold make these unnecessary
anim.SetBool("attacking", false);
anim.SetBool("jumpattacking", false);
}
}