I am trying to have an enemy attack the player and the enemy attacks through animation however the method I have to prevent the animation from starting when others are active are not working. The problem should be shown by this (might be low quality). As you can see the problem is that it is turning the bools on and off continuously. I don't know why this is happening because the way I have it should work. Is there a way to block them from doing this and run one at a time that works? Here is my code:
Edit: I forgot to say this but I am not getting any errors with my code
public void AttackPlayer(GameObject playerPos, Animator anim, NavMeshAgent agent, GameObject self, bool MultiAttack, float inRange, float inView, float AttackRange, bool isBlocking, bool HasSeenPLayer)
{
distDif = Vector3.Distance(self.transform.position, playerPos.transform.position);
if (distDif >= AttackRange)
{
agent.SetDestination(playerPos.transform.position);
anim.SetBool("walk", false);
}
else if (distDif <= AttackRange)
{
anim.SetBool("walk", false);
}
MultAttack(playerPos, anim, agent, self, MultiAttack, inRange, inView);
if (!MultiAttack)
{
anim.SetBool("Attack2", false);
anim.SetBool("Attack3", false);
StartCoroutine(PlayAnim(anim, "Attack"));
}
if (!PlayerPos.FindPlayerPos(AttackRange, playerPos.transform, inView, self, HasSeenPLayer))
{
anim.SetBool("Attack", false);
anim.SetBool("Attack2", false);
anim.SetBool("Attack3", false);
state = State.Chase;
}
}
private bool noloop = true;
public void MultAttack(GameObject playerPos, Animator anim, NavMeshAgent agent, GameObject self, bool MultiAttack, float inRange, float inView)
{
if (!MultiAttack) return;
if (random == 0) random = Random.Range(1, 5);
if (random == 1)
{
StartCoroutine(PlayAnim(anim, "Attack"));
random = 0;
return;
}
if (random == 2)
{
if (HasParameter("Attack2", anim))
{
StartCoroutine(PlayAnim(anim, "Attack2"));
random = 0;
return;
}
StartCoroutine(PlayAnim(anim, "Attack"));
random = 0;
return;
}
if (random == 3)
{
if (HasParameter("Attack3", anim))
{
StartCoroutine(PlayAnim(anim, "Attack3"));
random = 0;
return;
}
StartCoroutine(PlayAnim(anim, "Attack"));
random = 0;
return;
}
if (random == 4)
{
BlockPlayer(playerPos, anim, agent, inRange, inView, self);
random = 0;
return;
}
StartCoroutine(PlayAnim(anim, "Attack"));
random = 0;
return;
}
public static bool HasParameter(string paramName, Animator animator)
{
foreach (AnimatorControllerParameter param in animator.parameters)
{
if (param.name == paramName)
return true;
}
return false;
}
IEnumerator PlayAnim(Animator anim, string booleanName)
{
anim.SetBool(booleanName, true);
yield return new WaitForSeconds(anim.GetCurrentAnimatorStateInfo(0).length anim.GetCurrentAnimatorStateInfo(0).normalizedTime);
//^^^ this has a value I had debug.Log print the value and it has one value
anim.SetBool(booleanName, false);
}
Edit 2: This is how the attack function is called: (In its own script)
public void ChoseChasingWhatStateToAttackPlayer(NavMeshAgent agent, GameObject playerPos, GameObject Gself, Animator anim, bool MultiAttack, float inRange, float inView, float AttackRange, bool isBlocking, bool HasSeenPLayer)
{
switch (state)
{
case State.Chase:
ChasePlayer(playerPos, Gself, anim, agent, AttackRange, inRange, inView, HasSeenPLayer);
break;
case State.Attack:
AttackPlayer(playerPos, anim, agent, Gself, MultiAttack, inRange, inView, AttackRange, isBlocking, HasSeenPLayer);
break;
case State.Idle:
IdlePlayer(playerPos, anim, agent, Gself, inRange, inView, HasSeenPLayer);
break;
case State.Wander:
WanderPlayer(playerPos, anim, agent, Gself, HasSeenPLayer);
break;
}
}
Here it is in the main script:
TtF.ChoseChasingWhatStateToAttackPlayer(agent, Player_pos.player, self, anim, MultiAttack, inRange, inView, AttackRange, isBlocking, hasSeenPlayer);
// called in update
CodePudding user response:
I think your main problem may be that you are calling the AttackPlayer()
function repeatedly. If this was the case (Edit: you updated the code and it looks like this IS the case), then it would call MultAttack()
repeatedly which would cause it to choose a new random attack animation to play every time (possibly every frame).
I also see some minor problems that may be contributing but it's hard to tell:
From your code:
if (distDif >= AttackRange) { agent.SetDestination(playerPos.transform.position); anim.SetBool("walk", false); }
Do you really want to set the "walk" animation to false here?
Another:
Your code:
MultAttack(playerPos, anim, agent, self, MultiAttack, inRange, inView); if (!MultiAttack) { anim.SetBool("Attack2", false); anim.SetBool("Attack3", false); StartCoroutine(PlayAnim(anim, "Attack")); }
You are calling MultAttack()
even when the variable MultiAttack
is false. Instead of just "undoing" everything you do in MultAttack()
if MultiAttack
is false, maybe just don't call it unless MultiAttack
is true? Like so:
if(MultiAttack)
{
MultAttack(/*arguments here*/);
}
else
{
//trigger single attack animation
}
I would also HIGHLY suggest passing all of that data though those functions as a single object or struct or something. That looks like the kind of data that should be stored on an "Enemy" object. Having all those parameters makes it really hard to tell what's happening and is hard to organize.