Ok sounds great i'll send the files right over.
My spine runtime verstion.txt contains this
This Spine-Unity runtime works with data exported from Spine Editor version: 3.5.xx
The script that handles the animations contains the following code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity;
using Spine;
using StudioName.Utility;
public class CharacterAnimatorController : MonoBehaviour {
public enum AnimationType { Spine, Mecanim }
[TooltipAttribute("The type of animator we want to animate the character with")]
public AnimationType animType;
public Animator animator;
[HeaderAttribute("Spine Animation Properties")]
public SkeletonAnimation skeletonAnimation;
[SpineAnimation(dataField: "skeletonAnimation")]
public string idleName = "";
[SpineAnimation(dataField: "skeletonAnimation")]
public string runName = "";
[SpineAnimation(dataField: "skeletonAnimation")]
public string jumpName = "";
[SpineAnimation(dataField: "skeletonAnimation")]
public string quickJumpName = "";
[SpineAnimation(dataField: "skeletonAnimation")]
public string tauntJumpName = "";
[SpineAnimation(dataField: "skeletonAnimation")]
public string landName = "";
[SpineAnimation(dataField: "skeletonAnimation")]
public string fallingName = "";
[Range(1,2)]
public float runAnimationScale = 1.2f;
[RangeAttribute(0,1.5f)]
public float stdJumpThreshold = 0;
private JumpController jumpController;
private PlayerController playerController;
private new Rigidbody2D rigidbody2D;
private SkeletonData skeletonData;
private Spine.Animation landAnimation;
private Vector2 lastVelocity;
private bool facingRight = true;
private bool lastGrounded = true;
private bool landing = false;
private float quickJumpTimer = 0;
void Start(){
jumpController = GetComponent<JumpController>();
playerController = GetComponent<PlayerController>();
rigidbody2D = GetComponent<Rigidbody2D>();
skeletonData = skeletonAnimation.skeletonDataAsset.GetSkeletonData(false);
landAnimation = skeletonData.FindAnimation(landName);
skeletonAnimation.state.Start += SpineStartHandler;
skeletonAnimation.state.End += SpineEndHandler;
}
void OnDisable(){
skeletonAnimation.state.Start -= SpineStartHandler;
skeletonAnimation.state.End -= SpineEndHandler;
}
// Update is called once per frame
void Update () {
switch(animType){
case AnimationType.Mecanim:
//flips animations when facing left or right
if (playerController.MovingDirection > 0 && !facingRight){
Flip();
}else if (playerController.MovingDirection < 0 && facingRight){
Flip();
}
//computes a random jump when the player is grounded
if(jumpController.IsGrounded){
animator.SetInteger("Random Jump", Random.Range(0,4));
}
SetMecanimMovementVariables();
break;
case AnimationType.Spine:
//flips animations when facing left or right
if (playerController.MovingDirection > 0 && !facingRight){
facingRight = !facingRight;
skeletonAnimation.skeleton.flipX = false;
}else if (playerController.MovingDirection < 0 && facingRight){
facingRight = !facingRight;
skeletonAnimation.skeleton.flipX = true;
}
//if we are grounded and moving change to run animation otherwise idle
if(jumpController.IsGrounded){
skeletonAnimation.loop = true;
//add to our quickJumpTimer
quickJumpTimer += Time.deltaTime;
//if we just hit the ground play our land animation until it finishes
if(!lastGrounded){
skeletonAnimation.loop = false;
skeletonAnimation.AnimationName = landName;
landing = true;
quickJumpTimer = 0;
StartCoroutine(GenUtil.Wait(Land, landAnimation.Duration));
}
//ensure that we let our land animation finish before we play another animation
if(!landing){
//if we aren't moving idle otherwise run animation
if(Mathf.Abs(playerController.MovingDirection) > 0.01f){
skeletonAnimation.AnimationName = runName;
}else{
skeletonAnimation.AnimationName = idleName;
}
}
//if we are not grounded and we have a up velocity jump otherwise fall
}else{
skeletonAnimation.loop = false;
if(rigidbody2D.velocity.y > 0){
switch(jumpController.FingerCountOnJump){
//One finger
case 1:
//quick jump
if(quickJumpTimer <= stdJumpThreshold ){
Debug.Log("Time!" + quickJumpTimer + "stdJumpThreshold" + stdJumpThreshold);
skeletonAnimation.AnimationName = quickJumpName;
//normal jump
}else{
skeletonAnimation.AnimationName = jumpName;
}
break;
//Two fingers
case 2:
skeletonAnimation.AnimationName = tauntJumpName;
break;
default:
goto case 1;
}
}else{
skeletonAnimation.AnimationName = fallingName;
//===This is the bit that doesn't seem to work. I also tried just state, rather then AnimationState
//skeleteonAnimation.AnimationState.setAnimation(0,fallingName,false);
}
}
break;
}
lastGrounded = jumpController.IsGrounded;
lastVelocity = rigidbody2D.velocity;
}
//flips animations when the player is facing other direction
private void Flip() {
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
private void SetMecanimMovementVariables(){
animator.SetFloat("vSpeed", rigidbody2D.velocity.y);
animator.SetFloat("Speed", Mathf.Abs(playerController.MovingDirection));
animator.SetBool("Ground", jumpController.IsGrounded);
}
/// <summary>
/// Resets the landing variable and looping of the spine animator so that other aniamtions can play
/// when the landing animation is finished
/// </summary>
private void Land(){
landing = false;
skeletonAnimation.loop = true;
}
/// <summary>
/// Executes code when a spine animation starts
/// </summary>
/// <param name="trackEntry">the track entry that is currently playing (set of animations)</param>
private void SpineStartHandler(TrackEntry trackEntry){
string animation = trackEntry.animation.name;
if(animation == runName){
skeletonAnimation.timeScale = runAnimationScale;
}
}
/// <summary>
/// Executes code when a spine animation ends
/// </summary>
/// <param name="trackEntry">the track entry that is currently playing (set of animations)</param>
private void SpineEndHandler(TrackEntry trackEntry){
string animation = trackEntry.animation.name;
if(animation == runName){
skeletonAnimation.timeScale = 1f;
}
}
public bool FacingRight {
get { return facingRight; }
}
}