- Home /
canMove bool never turn true after attack animation.
I have a simple problem which is while player is attacking i want move function to stop(that i accomplish); after that move function doesn't work. here is my code. if anyone can point me to right direction, it'd be so good for me. thank you.
public class Controller : MonoBehaviour {
public float moveSpeed, turnSpeed;
public float height = 0.5f, heightPadding = 0.05f, maxGroundAngle = 120;
float angle, moveAmount, actionDelay;
float groundAngle;
public LayerMask ground;
public bool debug;
bool grounded;
[HideInInspector]
public bool input_LM, input_RM, input_Space, input_LShift, input_E, input_Q, input_F;
public bool inCombat, equipped, lockedOn, canMove, inAction;
Vector3 forward;
RaycastHit hitInfo;
Vector2 input;
Quaternion targetRotation;
Transform cam;
Rigidbody rigid;
Animator anim;
void Start(){
canMove = true;
cam = Camera.main.transform;
rigid = GetComponent<Rigidbody>();
rigid.angularDrag = 999;
rigid.drag = 4;
anim = GetComponentInChildren<Animator>();
}
void Update(){
GetInput();
HandleAnimations();
if (inAction)
canMove = false;
else
canMove = true;
CalculateDirection();
CalculateForward();
CalculateGroundAngle();
CheckGround();
if (Mathf.Abs(input.x) < 1 && Mathf.Abs(input.y) < 1)
return;
Rotate();
if(canMove == true)
Move();
if (Input.GetButton("Interact"))
Interact();
}
void LateUpdate(){
}
void GetInput(){
input.x = Input.GetAxisRaw("Horizontal");
input.y = Input.GetAxisRaw("Vertical");
input_LM = Input.GetButtonUp("Left Mouse");
input_RM = Input.GetButtonUp("Right Mouse");
input_LShift = Input.GetButtonUp("Dash");
input_Space = Input.GetButtonUp("Roll");
input_Q = Input.GetButtonUp("Cast Left");
input_E = Input.GetButtonUp("Cast Right");
input_F = Input.GetButtonUp("Interact");
}
void CalculateDirection(){
angle = Mathf.Atan2(input.x, input.y);
angle = Mathf.Rad2Deg * angle;
angle += cam.eulerAngles.y;
}
void Rotate(){
targetRotation = Quaternion.Euler(0, angle, 0);
rigid.rotation = Quaternion.Slerp(transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
}
void Move(){
if (groundAngle >= maxGroundAngle)
return;
rigid.MovePosition(transform.position + forward * moveSpeed * Time.deltaTime);
}
void CalculateForward(){
if (!grounded){
forward = transform.forward;
return;
}
forward = Vector3.Cross(transform.right, hitInfo.normal);
}
void CalculateGroundAngle(){
if (!grounded){
groundAngle = 90;
return;
}
groundAngle = Vector3.Angle(hitInfo.normal, transform.forward);
}
void CheckGround(){
if (Physics.Raycast(transform.position, -Vector3.up, out hitInfo, height + heightPadding, ground)){
grounded = true;
}else{
grounded = false;
}
}
void DrawDebugLines(){
if (!debug)
return;
Debug.DrawLine(transform.position, transform.position + forward * height, Color.blue);
Debug.DrawLine(transform.position, transform.position - Vector3.up * height, Color.green);
}
void Interact(){
}
public void CheckForEquip(){
if (!inCombat){
equipped = false;
lockedOn = false;
}else{
equipped = true;
}
}
void HandleAnimations(){
CheckForEquip();
//movement
anim.SetFloat("Horizontal", Mathf.Abs(input.x));
anim.SetFloat("Vertical", Mathf.Abs(input.y));
//actions
if (input_LM == false && input_RM == false && input_E == false
&& input_Q == false && input_F == false && input_Space == false && input_LShift == false){
return;
}
string targetAnimation = null;
if (input_LM){
inAction = true;
targetAnimation = "Attack_05";
}
if (input_RM){
inAction = true;
targetAnimation = "Attack_01";
}
anim.CrossFade(targetAnimation, 0.2f);
rigid.velocity = Vector3.zero;
if (inAction){
anim.applyRootMotion = true;
Vector3 delta = anim.deltaPosition;
delta.y = 0;
Vector3 v = (delta * 1) / Time.deltaTime;
rigid.velocity = v;
rigid.drag = 0;
}
anim.applyRootMotion = false;
}
}
You didn't set inAction = false
in any part of your code.
Answer by niiicolai · Aug 08, 2018 at 01:45 PM
You will have to set inAction
back to false after your attack animations is finished. For this you could fetch the animation lengths and instead run your attack behaviour in a coroutine.
So for the example below you have to enter the correct clip names of the animations you use for animator states Attack_01
and Attack_05
Animator animator;
bool inAction;
bool canMove;
float fadeLength = .2f;
List<string> animationStateNames = new List<string>() {"Attack_01", "Attack_05"};
List<string> animationClipNames = new List<string>() {"Animation_clip_name_1", "Animation_clip_name_2"};
List<float> animationLengths = new List<float>();
void Start () {
animator = GetComponent<Animator>();
foreach(AnimationClip animationClip in animator.runtimeAnimatorController.animationClips) {
for (int i = 0; i < animationClipNames.Count; i++) {
if (animationClip.name == animationClipNames[i]) {
animationLengths.Add(animationClip.length);
}
}
}
}
void Update() {
// Only run the attack behaviour if we isn't attacking allready.
var leftClick = Input.GetMouseButtonDown(0);
var rightClick = Input.GetMouseButtonDown(1);
if (!inAction && leftClick) {
StartCoroutine(Attack(1));
} else if (!inAction && rightClick) {
StartCoroutine(Attack(0));
}
if (inAction) {
// run some behaviour every frame if we are in action.
}
}
// https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html
IEnumerator Attack(int animationIndex) {
inAction = true;
canMove = false;
animator.CrossFade(animationStateNames[animationIndex], fadeLength);
yield return new WaitForSeconds(animationLengths[animationIndex]);
inAction = false;
canMove = true;
}
Thank you for your time!
But now there is a "Argument out of range exception" error for "StartCoroutine(Attack(animations[1], animationLengths[1]));" and "StartCoroutine(Attack(animations[0], animationLengths[0]));".
Hmm. It doesn't find any animation lengths then. 2 sec.
it is same error again and also can$$anonymous$$ove is not returning true anymore. i don't get it; it seems fine to me. :/
Your answer
![](https://koobas.hobune.stream/wayback/20220612172433im_/https://answers.unity.com/themes/thub/images/avi.jpg)