KelvinWakaka

Hello, I have Player Controller Script that allows me to have the Player to have idle, walk and jump with animation. When I tried to add run, the Player runs but the animation is not working. I was following ThinkCitric's guides and I could not figure out what went wrong.
https://www.youtube.com/watch?v=In9K7wcpCto&ab_channel=ThinkCitric
https://www.youtube.com/watch?v=jNrCryU-Nv8&ab_channel=ThinkCitric
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity;

public class PlayerController : MonoBehaviour
{
public SkeletonAnimation skeletonAnimation;
public AnimationReferenceAsset idle, walking, jumping, running;
public string currentState;
public float speed;
public float movement;
private Rigidbody2D rigidbody;
public string currentAnimation;
public float jumpSpeed;
private Vector2 characterScale;
public string previousState;
public float runSpeed;

// Start is called before the first frame update
void Start()
{
rigidbody = GetComponent<Rigidbody2D>();
currentState = "Idle";
SetCharacterState(currentState);
characterScale = transform.localScale;

}

// Update is called once per frame
void Update()

{
Move();
}

//sets character animation
public void SetAnimation(AnimationReferenceAsset animation, bool loop, float timeScale)
{
if (animation.name.Equals(currentAnimation))
{
return;
}
Spine.TrackEntry animationEntry = skeletonAnimation.state.SetAnimation(0, animation, loop);
animationEntry.TimeScale = timeScale;
animationEntry.Complete += AnimationEntry_Complete;
currentAnimation = animation.name;
}

//Do something after animation completes
private void AnimationEntry_Complete(Spine.TrackEntry trackEntry)
{
if (currentState.Equals("Jumping"))
{
SetCharacterState(previousState);
}
}

//Checks character state and sets the animation accordingly
public void SetCharacterState(string state)
{

if (state.Equals("Walking"))
{
SetAnimation(walking, true, 1.5f);
}
else if (state.Equals("Jumping"))
{
SetAnimation(jumping, false, 1f);
}
else if (state.Equals("Running"))
{
SetAnimation(running, true, 1f);
}
else
{
SetAnimation(idle, true, 1f);
}

currentState = state;
}

public void Move()
{
movement = Input.GetAxis("Horizontal");
rigidbody.velocity = new Vector2(movement * speed, rigidbody.velocity.y);
if (movement != 0)
{
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Walking");
}



if (movement > 0)
{
transform.localScale = new Vector2(characterScale.x, characterScale.y);
}
else
{
transform.localScale = new Vector2(-characterScale.x, characterScale.y);
}
}
else
{
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Idle");
}


}

if (Input.GetButtonDown("Jump"))
{
Jump();
}

if (Input.GetKey(KeyCode.LeftShift))
{
Run();
}
}

public void Jump()
{
rigidbody.velocity = new Vector2(rigidbody.velocity.x, jumpSpeed);
if (!currentState.Equals("Jumping"))
{
previousState = currentState;
}
SetCharacterState("Jumping");
}

public void Run()
{
rigidbody.velocity = new Vector2(movement * runSpeed, rigidbody.velocity.y);
if (!currentState.Equals("Running"))
{
previousState = currentState;
}
SetCharacterState("Running");
}
}
KelvinWakaka
  • Postovi: 6

Mario

Is the running AnimationReferenceAsset set correctly?
Avatar
Mario

Mario
  • Postovi: 2965

KelvinWakaka

I think so. When I press Lshift it shows the state is Running. And I have also tested the animation without the Player Controller Script and the animation works.
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
KelvinWakaka
  • Postovi: 6

Harald

KelvinWakaka je napisao/la:And I have also tested the animation without the Player Controller Script and the animation works.
How did you test them? Are you sure that you have assigned the correct AnimationReferenceAssets from the skeleton asset you are controlling, and not from another skeleton that also has a Walking animation?

Please also describe in more detail what you mean by "the animation is not working". What are you expecting to see and what do you see instead. Does the animation play but show an undesired result, or is the skeleton not moving at all when playing the animation?
Avatar
Harald

Harri
  • Postovi: 3905

KelvinWakaka

Harald je napisao/la:
KelvinWakaka je napisao/la:And I have also tested the animation without the Player Controller Script and the animation works.
How did you test them? Are you sure that you have assigned the correct AnimationReferenceAssets from the skeleton asset you are controlling, and not from another skeleton that also has a Walking animation?

Please also describe in more detail what you mean by "the animation is not working". What are you expecting to see and what do you see instead. Does the animation play but show an undesired result, or is the skeleton not moving at all when playing the animation?
So I tried playing the scene while only looping the animation (i disabled the player controller script). Thats what I meant by tested the animation. I am sure I have assigned the correct AnimationReferenceAssets from the skeleton asset.



I was hoping to see the Player would run the "Running" animation and instead it only runs the first frame of the animation at the moment when I press LShift.



I apologise for not describing the issue in more detail previously.
KelvinWakaka
  • Postovi: 6

Harald

If you see only the first frame of an animation being played, you are most likely starting the same animation every frame instead of only once.
Avatar
Harald

Harri
  • Postovi: 3905

KelvinWakaka

Harald je napisao/la:If you see only the first frame of an animation being played, you are most likely starting the same animation every frame instead of only once.
I see. What am I missing? I followed the same principle the tutorial used for "Jump" in "Run".
KelvinWakaka
  • Postovi: 6

Jamez0r

I believe whats happening is that when your character is running, you are first setting it to "Walking" and then setting it to "Running" every frame. So the animation gets switched to Walking and then immediately switched to Running, which causes the run animation to start over.
public void Move()
{
movement = Input.GetAxis("Horizontal");
rigidbody.velocity = new Vector2(movement * speed, rigidbody.velocity.y);
if (movement != 0)
{
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Walking"); <---This is triggering each frame when you're running
}

....
You'll want to set up your code so that when you're supposed to be running, it doesn't set you to Walking
Avatar
Jamez0r
  • Postovi: 356

KelvinWakaka

Jamez0r je napisao/la:I believe whats happening is that when your character is running, you are first setting it to "Walking" and then setting it to "Running" every frame. So the animation gets switched to Walking and then immediately switched to Running, which causes the run animation to start over.
public void Move()
{
movement = Input.GetAxis("Horizontal");
rigidbody.velocity = new Vector2(movement * speed, rigidbody.velocity.y);
if (movement != 0)
{
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Walking"); <---This is triggering each frame when you're running
}

....
You'll want to set up your code so that when you're supposed to be running, it doesn't set you to Walking
So I tried hiding this part
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Walking"); <---This is triggering each frame when you're running
}
and you are right. Now when I press LShift the Player actually runs the "Running" animation. However when I press w or d to move, instead of "Walking" animation, it runs the "Idle" animation. I don't really know how to set up my code to achieve that.
KelvinWakaka
  • Postovi: 6

Jamez0r

Remove this part from below:
if (Input.GetKey(KeyCode.LeftShift))
{
Run();
}
And instead have it check if its running here, by replacing this:
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Walking");
}
with this:
if (!currentState.Equals("Jumping")){
if (Input.GetKey(KeyCode.LeftShift)) {
Run();
} else {
SetCharacterState("Walking");
}
}
That way it can only either set it to Run or to Walking but not both on the same frame.

I highly recommend spending some time focusing just on the basics of programming. I know its fun to jump right into making a game, but at some point you'll need to take a step back and get a good programming foundation or else you will struggle when you evolve from following along in a tutorial to actually creating your own stuff from scratch. It's tough but its worth it!
Avatar
Jamez0r
  • Postovi: 356

Harald

Thanks again Jamez0r for answering!
Jamez0r je napisao/la:I highly recommend spending some time focusing just on the basics of programming.
We definitely second that. Learning the foundational knowledge first is very important and will save a lot of trouble down the road. One thing for example would be to not use strings like "Walking" for saving and querying state, where you could use an enum instead. Also you should never repeat a string all over the place, instead declare a constant, this saves you from any typos and makes editing much easier. Additionally, learning design patterns helps carrying out what you intend to do in a way that's cleaner and easier to extend.
Avatar
Harald

Harri
  • Postovi: 3905

KelvinWakaka

Jamez0r je napisao/la:Remove this part from below:
if (Input.GetKey(KeyCode.LeftShift))
{
Run();
}
And instead have it check if its running here, by replacing this:
if (!currentState.Equals("Jumping"))
{
SetCharacterState("Walking");
}
with this:
if (!currentState.Equals("Jumping")){
if (Input.GetKey(KeyCode.LeftShift)) {
Run();
} else {
SetCharacterState("Walking");
}
}
That way it can only either set it to Run or to Walking but not both on the same frame.

I highly recommend spending some time focusing just on the basics of programming. I know its fun to jump right into making a game, but at some point you'll need to take a step back and get a good programming foundation or else you will struggle when you evolve from following along in a tutorial to actually creating your own stuff from scratch. It's tough but its worth it!
Yep, I don't usually work on the programming side of things and it shows. Thank you for the solution!
KelvinWakaka
  • Postovi: 6


Natrag na Unity