In my PlayerInput file, I have the following in the Update function
if(Input.GetButtonDown("Attack"))
{
SendMessage("MeleeAttack");
}
This kicks off the process ok and calls MeleeAttack, which is turn calls PlayAttackSequence. But, I am having an issue, when I click more than once, it kind of starts the first animation and then restarts it and the plays the sequence. My desired behavior is if I 1. press the mouse once, play animation one
2. press the mouse twice, play animation one, then animation two
3. press the mouse three times, play animation one, then animation two, then animation three
The mouse clicks need to happen consecutively. If the user user clicks once and then waits five seconds and then clicks twice, the loop should start over. Hopefully this is clear and someone can help. I would certainly appreciate it!
/// <summary>
/// AdvancedMovement.cs
/// Dec 27, 2010
/// Peter Laliberte
///
/// This script is responsible for getting the players movement inputs and adjusting the characters animations accordindly.
///
/// This script will be automatically attached to your player or mob with the use of the PlayerInput.cs and AI.cs scripts.
///
/// This script assumes that you have these animation with the following names:
/// Player:
/// swim - the swim forward animation (only needed if you want to swim in game)
/// walk - a walk animation
/// run - a run animations
/// side - for strafing
/// jump - a jump animation
/// fall - a falling animation
/// idle - an idle animation
///
/// Mob:
/// run - a run animations
/// jump - a jump animation
/// fall - a falling animation
/// idle - an idle animation
///
/// </summary>
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(CharacterController))]
public class AdvancedMovement : MonoBehaviour {
public enum State {
Idle,
Init,
Setup,
Run
}
public enum Turn {
left = -1,
none = 0,
right = 1
}
public enum Forward {
back = -1,
none = 0,
forward = 1
}
public enum Flight {
down = -1,
none = 0,
up = 1
}
//10.3.12
public enum MeleAttack
{
sword_swing_high_right,
sword_swing_high_left,
sword_swing_high_straight_down
}
//S.Murley 10.3.12 - using temp animation
public string walkAnimName = "sword_walk";
public string runAnimName;
public string jumpAnimName;
public string idleAnimName;
public string swimForwardAnimName;
public string strafeLeftAnimName;
public string strafeRightAnimName;
public string fallAnimName;
//S.Murley 10.2.12
public string[] arrMeleAttacks = new string[]{"sword_swing_high_right", "sword_swing_high_left", "sword_swing_high_straight_down"};
public float mouseClicks = 0;
public int attackSequence;
private float mouseTimer = 0f;
private float mouseTimerLimit = 1.25f;
private float lastMouseClick = 0;
private float timer;
//public AnimationClip meleeAttack1;
//public AnimationClip meleeAttack2;
//public AnimationClip meleeAttack3;
public GameObject characterObject;
//private int attackSequence = 0;
public AnimationClip idleIncombat1h;
public float walkSpeed = 2; //the speed our character walks at
public float runMultiplier = 2; //how fast the player runs compared to the walk speed
public float strafeSpeed = 2.5f; //the speed our character strafes at
public float rotateSpeed = 250; //the speed our character turns at
public float gravity = 20; //the setting for gravity
public float airTime = 0; //how long have we been in the air since the last time we touched the ground
public float fallTime = .5f; //the length of time we have to be falling before the system knows its a fall
public float jumpHeight = 8; //the height we move when we are jumping
public float jumpTime = 1.5f;
public float attackWeight= 1.5f;
private CollisionFlags _collisionFlags; //the collisionFlags we have from the last frame.
private Vector3 _moveDirection; //This is the direction our character is moving
private Transform _myTransform; //our cached transform
private CharacterController _controller; //our cached CharacterController
private Turn _turn;
private Forward _forward;
private Turn _strafe;
private Flight _flight;
private bool _run;
private bool _jump;
private bool _isSwimming;
public bool _isFlying;
private State _state;
private BaseCharacter _bc;
//Called before the script starts
public void Awake() {
_myTransform = transform; //cache our transform
_controller = GetComponent<CharacterController>(); //cache our charactercontroller
_state = AdvancedMovement.State.Init;
_bc = gameObject.GetComponent<BaseCharacter>();
}
// Use this for initialization
IEnumerator Start () {
while(true) {
switch(_state) {
case State.Init:
Init();
break;
case State.Setup:
SetUp();
break;
case State.Run:
ActionPicker();
break;
}
yield return null;
}
}
void Update()
{
//reset clicks after 1 second if mouse clicks > 0
if (Time.time - lastMouseClick > 1.0F mouseClicks > 0)
{
resetClicks();
}
}
private void Init() {
if(!GetComponent<CharacterController>()) return;
if(!GetComponent<Animation>()) return;
_state = AdvancedMovement.State.Setup;
}
private void SetUp() {
_moveDirection = Vector3.zero; //zero our the vector3 we will use for moving our player
animation.Stop(); //stop any animations that might be set to play automatically
animation.wrapMode = WrapMode.Loop; //set all animations to loop by default
// if(jumpAnimName != "") {
// animation[jumpAnimName].layer = -1; //move jump to a higher layer
// animation[jumpAnimName].wrapMode = WrapMode.Once; //set jump to only play once
// }
animation.Play(idleAnimName); //start the idle animation when the script starts
_turn = AdvancedMovement.Turn.none;
_forward = AdvancedMovement.Forward.none;
_strafe = Turn.none;
_flight = Flight.none;
_run = true;
_jump = false;
_isSwimming = false;
_isFlying = false;
_state = AdvancedMovement.State.Run;
}
private void ActionPicker() {
//allow the player to turn left and right
_myTransform.Rotate(0, (int)_turn * Time.deltaTime * rotateSpeed, 0);
//if we are on the ground, let us move
if(_isFlying){
_moveDirection = new Vector3((int)_strafe, (int)_flight, (int)_forward);
_moveDirection = _myTransform.TransformDirection(_moveDirection).normalized;
_moveDirection *= walkSpeed;
// FlyingUpdate();
}
else if(_controller.isGrounded || _isSwimming) {
//if(_controller.isGrounded || _isSwimming) {
//reset the air timer if we are on the ground
airTime = 0;
//get the user input if we should be moving forward or sideways
//we will calculate a new vector3 for where the player needs to be
_moveDirection = new Vector3((int)_strafe, 0, (int)_forward);
_moveDirection = _myTransform.TransformDirection(_moveDirection).normalized;
_moveDirection *= walkSpeed;
if(_forward != Forward.none) { //if user is pressing forward
if(_isSwimming) {
Swim();
}
else {
if(_run) { //and pressing the run key
_moveDirection *= runMultiplier; //move user at run speed
Run(); //play run animation
}
else {
Walk(); //play walk animation
}
}
}
else if(_strafe != AdvancedMovement.Turn.none) { //if user is pressing strafe
if(_strafe == Turn.left)
StrafeLeft(); //play strafe animation
else
StrafeRight(); //play strafe animation
}
else {
if(_isSwimming) {
}
else {
Idle(); //play idle animation
}
}
if(_jump) { //if the user presses the jump key
if(airTime < jumpTime) { //if we have not already been in the air to long
_moveDirection.y += jumpHeight; //move them upwards
Jump(); //play jump animation
_jump = false;
}
}
}
else {
//if we have a collisionFlag and it is CollideBelow
if((_collisionFlags CollisionFlags.CollidedBelow) == 0) {
airTime += Time.deltaTime; //increase the airTime
if(airTime > fallTime) { //if we have been in the air to long
Fall(); //play the fall animation
}
}
}
if(!_isSwimming || !_isFlying)
_moveDirection.y -= gravity * Time.deltaTime; //apply gravity
//move the character and store any new CollisionFlags we get
_collisionFlags = _controller.Move(_moveDirection * Time.deltaTime);
}
private float moveSpeed;
//public float rotateSpeed = 100.0f;
public float speedSmoothing = 10.0f;
public float flyingSpeed = 15.0f;
public float flyingBackSpeed = -5.0f;
public float runFlyMultiplier = 3.1f;
public float elevateMultipler = 4.0f;
private bool isFlying = false;
private bool isFlyingBackward = false;
void FlyingUpdate()
{
// ----------------Movement Controls ---------------------//
//sets target direction by making a vector with the keys that you have pressed.
// the 1.0f is the vertical value. If you try to turn with only h being pressed, it will act funny
Vector3 targetDirection = /*Input.GetAxis("Horizontal") * transform.right + */ 0.3f * _myTransform.forward;
targetDirection = targetDirection.normalized;
//creates a vector that will smoothly rotate toward destination. Normalized for good measure
_moveDirection = Vector3.Lerp(_moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime);
//moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
_moveDirection = _moveDirection.normalized;
//Does the final rotation along as there is being input pressed (targetDirection)
/*
if (targetDirection != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(moveDirection);
}
* */
//--Find out the movement
float v = Input.GetAxisRaw("Vertical");
float h = Input.GetAxisRaw("Horizontal");
//Vector3 targetDirection2 = v * transform.forward;
//Vector3 targetDirection2 = h * transform.right + v * transform.forward;
// Choose target speed
//* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
//float targetDirection3 = Mathf.Min(targetDirection2.magnitude, 1.0f);;
float targetSpeed = 20f;
// if (Mathf.Abs(v) < 0.1f Mathf.Abs(h) < 0.1f )
// {
// targetSpeed = 0;
// isFlyingBackward = false;
// }
// else if (v < -0.1f)
// {
// targetSpeed = flyingBackSpeed;
// isFlyingBackward = true;
// }
// else
// {
targetSpeed = flyingSpeed;
// isFlyingBackward = false;
// }
//sets the current smooth speed
// Smooth the speed based on the current target direction
float curSmooth = speedSmoothing * Time.deltaTime;
//sets the movement after all the scenarios have been calculated
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
//playerManager.MoveSpeed(moveSpeed);
//Debug.Log("Move Speed:" + moveSpeed + " Target Speed:" + targetSpeed + " CurSmoth:" + curSmooth );
// Calculate actual motion
Vector3 movement = _moveDirection * moveSpeed;
movement *= Time.deltaTime;
//collisionFlags = controller.Move(movement);
// ----------------FLying rotation Controls ---------------------//
//for mouse movement
float yawMouse = Input.GetAxis("Mouse X");
float pitchMouse = _moveDirection.y;//Input.GetAxis("Mouse Y");
Vector3 targetFlyRotation = Vector3.zero;
Screen.lockCursor = true;
if (Mathf.Abs(yawMouse) > 0.1f || Mathf.Abs(pitchMouse) > 0.1f)
{
targetFlyRotation = yawMouse * _myTransform.right + pitchMouse * _myTransform.up;
targetFlyRotation.Normalize();
targetFlyRotation *= Time.deltaTime * 3.0f;
//limit x rotation if looking too much up or down
//Log out the limitX value for this to make sense
float limitX = Quaternion.LookRotation(_moveDirection + targetFlyRotation).eulerAngles.x;
//70 sets the rotation limit in the down direction
//290 sets limit for up direction
if (limitX < 90 limitX > 70 || limitX > 270 limitX < 290)
{
//Debug.Log("restrict motion");
}
else
{
_moveDirection += targetFlyRotation;
//does the actual rotation on the object if no limits are breached
_myTransform.rotation = Quaternion.LookRotation(_moveDirection);
}
//just tells the playerManager where to Look for the aim target.
// Vector3 newLookDirection = lookObject.transform.position - transform.position;
// newLookDirection.Normalize();
//
// playerManager.LookDirection(newLookDirection);
}
}
//S.Murley 10.2.12
public void resetClicks()
{
mouseClicks = 0;
mouseTimer = 0;
lastMouseClick = 0;
}
//S.Murley 10.2.12
void OnGUI()
{
Event e = Event.current;
if (e.isMouse)
Debug.Log("Mouse clicks: " + mouseClicks++);
}
public void MeleeAttack()
{
//attackSequence = 0;
//if mouse click equal 0, and first click, increment to 1
if (mouseClicks == 0)
{
mouseClicks += 1;
}
else if (Time.time - lastMouseClick < mouseTimerLimit)
{
mouseClicks += 1;
}
//loop through current click number and set sequence
if (mouseClicks >= 1 mouseClicks < 4)
{
mouseTimer += Time.fixedDeltaTime;
if (mouseClicks == 3)
{
if (mouseTimer - mouseTimerLimit < 0)
{
attackSequence = 3;
//Debug.Log("Mouse Triple Click");
}
else
{
attackSequence = 2;
//Debug.Log("Timer expired on Triple, do Double");
resetClicks();
}
}
else if (mouseClicks == 2)
{
if (mouseTimer - mouseTimerLimit < 0)
{
attackSequence = 2;
//Debug.Log("Mouse Double Click");
}
else
{
attackSequence = 1;
//Debug.Log("Timer expired on Double, do Single");
resetClicks();
}
}
else if (mouseClicks == 1)
{
if (mouseTimer - mouseTimerLimit < 0)
{
attackSequence = 1;
//Debug.Log("Mouse Single Click");
}
else
{
//Debug.Log("Timer expired on Single, reset clicks");
resetClicks();
}
}
else if (mouseTimer > mouseTimerLimit)
{
//Debug.Log("Timer expired");
resetClicks();
}
}
else
{
resetClicks();
}
lastMouseClick = Time.time;
PlayAttackSequence(attackSequence);
}
public void MoveMeForward(Forward z) {
_forward = z;
}
public void ToggleRun() {
_run = !_run;
}
public void RotateMe(Turn y) {
_turn = y;
}
public void Strafe(Turn x) {
_strafe = x;
}
public void JumpUp() {
_jump = true;
}
public void IsSwimming(bool swim) {
_isSwimming = swim;
}
public void SetFlyHeight(Flight x) {
_flight = x;
}
public void ToggleFly() {
_isFlying = !_isFlying;
}
/**
* Below is a list of all of the animations that every character in the game can perform along with any parameters needed for them to work right
**/
//Idle animation
public void Idle() {
if(idleAnimName == "")
return;
if( !_bc.InCombat )
animation.CrossFade(idleAnimName);
//else
// Debug.LogWarning( "Attack Idle" );
}
//walk animation
public void Walk() {
if(walkAnimName == "")
return;
//animation.CrossFade(walkAnimName);
//Debug.Log(walkAnimName);
animation[arrMeleAttacks[0]].wrapMode = WrapMode.Once;
animation[walkAnimName].wrapMode = WrapMode.Loop;
animation[walkAnimName].weight = .5f;
animation.CrossFade(walkAnimName);
animation[arrMeleAttacks[0]].layer = 1;
animation.CrossFade(arrMeleAttacks[0]);
animation[arrMeleAttacks[0]].weight = .5f;
}
//run animation
public void Run() {
if(runAnimName == "")
return;
animation[runAnimName].speed = 1.5f;
animation.CrossFade(runAnimName);
}
//strafe left animation
public void StrafeLeft() {
if(strafeLeftAnimName == "")
return;
animation.CrossFade(strafeLeftAnimName);
}
//strafe right animation
public void StrafeRight() {
if(strafeRightAnimName == "")
return;
animation.CrossFade(strafeRightAnimName);
}
//jump animation
public void Jump() {
if(jumpAnimName == "")
return;
animation.CrossFade(jumpAnimName);
}
//fall animation
public void Fall() {
if(fallAnimName == "")
return;
animation.CrossFade(fallAnimName);
}
public void Swim() {
if(swimForwardAnimName == "")
return;
animation.CrossFade(swimForwardAnimName);
}
//S.Murley 10.2.12
public void PlayAttackSequence(int attackLevel)
{
//Debug.Log(attackLevel);
_bc.InCombat = true;
////S.Murley 10.2.12
characterObject = GameObject.Find("Thor");
for (int attackCntr = 0; attackCntr < attackLevel; attackCntr++)
{
characterObject.animation[arrMeleAttacks[attackCntr]].wrapMode = WrapMode.Once;
if (attackCntr == 0)
{
characterObject.animation.PlayQueued(arrMeleAttacks[attackCntr], QueueMode.PlayNow);
}
else if (attackCntr <= attackLevel - 1)
{
characterObject.animation.PlayQueued(arrMeleAttacks[attackCntr], QueueMode.CompleteOthers);
}
}
//yield return new WaitForSeconds(attackLevel);
//yield return new WaitForSeconds(characterObject.animation.clip.length);
}
}