• Unity
  • Character movement - animation setting

Related Discussions
...

Hello,
would like to move a spine character under 2D and change the animation.
Unfortunately I get the following error:

NullReferenceException: Object reference not set to an instance of an object
PlayerMovement.SetAnima (System.String name, System.Boolean loop) (at Assets/Scripte/PlayerMovement.cs:80)
PlayerMovement.Update () (at Assets/Scripte/PlayerMovement.cs:54)

Here my Update C#:

void FixedUpdate()
    {
        Debug.Log("Fix");
        horizontal = Input.GetAxis("Horizontal");
        rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
        //rigidbody2D.velocity = new Vector2(x, Rigidbody2D.velocity.y);
        playerAnimator.SetFloat("Speed", Mathf.Abs(horizontal));

    if (horizontal < 0)
    {
        transform.localScale = new Vector3((float)0.3, (float)0.3, 1);
        SetAnima("1_Walk", true);
    }
    else if (horizontal > 0)
    {
        
        transform.localScale = new Vector3((float)-0.3, (float)0.3, 1);
        SetAnima("1_Walk", true);
    }
    else
    {
        Debug.Log("stehen");
        SetAnima("_Idle", true);
    }
 }

void SetAnima(string name, bool loop)
        {
        Debug.Log("Current: " + currentAnimation + " - " + name);
            if (name == currentAnimation)
                return;
        loop = false;
        Debug.Log("Current 2: " + currentAnimation + " - " + name + loop);
        
//skeletonAnimation.state.SetAnimation(0, name, loop); //skeletonAnimation.AnimationState.SetAnimation(0, name, loop); [b] skeletonAnimation.AnimationName = name;[/b] Debug.Log("Current 3: " + currentAnimation + " - " + name); currentAnimation = name; }

You will see further attempts to solve the problem in the script. Can someone help me ? Are there any instructions?
What informations are still needed?

Thanks Wolfgang

Sorry , my english is from Google ....

If the line skeletonAnimation.AnimationName = name; fails then you haven't assigned skeletonAnimation yet. So most likely you are missing a line like skeletonAnimation = this.GetComponent<SkeletonAnimation>(); if the component is part of the same GameObject.

In general, please learn Unity basics first.
Then read the spine-unity documentation pages, also the following section covering basic scripting:
spine-unity Runtime Documentation: Life cycle
Then also have a look at the example scenes and scripts in the Spine Examples directory.

Thanks Harald,
this missing line was helpfull "private static SkeletonData skeletonData;", in Void Start is: "skeletonAnimation = GetComponent<SkeletonAnimation>();" .

Believe me, I looked at the documentation and the runtime API.
But most programmers work with learning by doing!

Thanks Wolfgang

superkerni wrote

Believe me, I looked at the documentation and the runtime API.

Then you have looked without seeing (understanding).

superkerni wrote

Believe me, I looked at the documentation and the runtime API.
But most programmers work with learning by doing!

This is wrong, programmers learn by reading, thinking and then doing. And they learn from analysing and fixing their own mistakes.
And the reading and understanding part includes:
1) example code
2) documentation
3) what an error message tells them.
In order to be promoted to the rank of a programmer, you have to master all three of these reading and understanding skills.

Furthermore, the fundamental basics always have to be learned first, then more specialized topics can build upon it.
Thus the order is learning how to write code in your programming language, then how to use this language to write basic scripts for Unity, then how to use specialized Unity frameworks like spine-unity. Skipping parts is like running before you can walk, you will fall and hurt yourself.

5日 後

Hello and thank you for the "Learning" lesson.

I have been programming for 50 years and have taught programming for 20 years (IBM assembler, Cobol, Pascal). My experiences are only basically the same. There are enough references, methods and functions that cannot always be understood by reading. Here is the problem of understanding the Unity and Spine methods.
When I look at the included spine examples and compare them with many video tutorials, I see two or more worlds.

Ok, but of course I've read more and a new question:

My character actually makes all the movements. When I move horizontally, the animation “walk” is set, but the legs run or do not move. It is not the idle state either. I think an update is too fast.
Hopefully the script is a little better now.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine;
using Spine.Unity;
using Spine.Unity.AttachmentTools;

public class CharacterController : MonoBehaviour
{
    Skeleton skeleton;
    public AnimationReferenceAsset idle, walk,jump;
    public SkeletonAnimation skeletonAnimation;
    public float speed;
    public string currentState;
    Spine.AnimationState animationState;
    public string currentAnimation;
    //public string animationName;
    public float movement;
    private Rigidbody2D rb;
    public float jumpSpeed;
    public string previousState;

private void Awake()
{
    skeletonAnimation = GetComponent<SkeletonAnimation>();
    skeleton = skeletonAnimation.Skeleton;
    animationState = skeletonAnimation.AnimationState;
}

void Start()
{
    rb = GetComponent<Rigidbody2D>();
    currentState = "idle";
    SetCharacterState(currentState);
}

public void SetAnimation(AnimationReferenceAsset animation, bool loop, float timescale)
{
    if (animation.Equals(currentAnimation))
    {
        return;
    }
    Spine.TrackEntry animationEntry = skeletonAnimation.state.SetAnimation(0, animation, loop);
    //skeletonAnimation.state.SetAnimation(0, animation, loop).TimeScale = timescale;
    animationEntry.TimeScale = timescale;
    animationEntry.Complete += AnimationEntry_Complete;
    currentAnimation = animation.name;
}
private void AnimationEntry_Complete(Spine.TrackEntry trackEntry)
{
   // throw new System.NotImplementedException();
   if (currentState.Equals("jump"))
    {
        SetCharacterState(previousState);
    }
}
public void SetCharacterState(string state)
{
    if (state.Equals("walk"))
    {
        SetAnimation(walk, true, 2f);
    }
    else if (state.Equals("jump"))
    {
        SetAnimation(jump, false, 1f);
    }
    else
    {
        SetAnimation(idle, true, 1f);
    }
    currentState = state;

}
public void FixedUpdate()
{
    movement = Input.GetAxis("Horizontal");
    rb.velocity = new Vector2(movement * speed, rb.velocity.y);
    if (movement != 0)
    {
        if (!currentState.Equals(jump))
        {
            SetCharacterState("walk");
        }
        if (movement < 0)
        {
            // Skalierung mit 0.3 ist notwendig, da der Charakter sonst zu groß
            transform.localScale = new Vector2(0.3f, 0.3f);
        }
        else
        {
            transform.localScale = new Vector2(-0.3f, 0.3f);
        }
    }
    else
         // keine Bewegung horizontal
    {
        if (currentState.Equals(jump))
        {
           SetCharacterState("walk");
        }
        else
        {
            SetCharacterState("idle");
        }
    }
    if (Input.GetButtonDown("Jump"))
    {
        Jump();
    }
}
public void Jump()
{
    rb.velocity = new Vector2(rb.velocity.x, jumpSpeed);
    if (currentState.Equals(jump))
    {
        previousState = currentState;
    }
    SetCharacterState("jump");
}
}

superkerni wrote

I have been programming for 50 years and have taught programming for 20 years (IBM assembler, Cobol, Pascal). My experiences are only basically the same. There are enough references, methods and functions that cannot always be understood by reading. Here is the problem of understanding the Unity and Spine methods.

I sincerely did not expect that, your postings looked like young motivated people skipping over fundamentals and getting to the "fun part". You have my respect for still being interested in programming and learning new frameworks like Unity.
It puzzles me however that as a programmer you are looking at videos and not at executable example code. We have both solved programming problems long before we had internet access 🙂.

Please note that we do not have any official example videos on using the spine-unity runtime on youtube, those that you might have found can always be outdated or incomplete. So if any 3rd party videos are contradicting the officially provided resources by us, we can just recommend to use and trust our resources as a reference.

superkerni wrote

My character actually makes all the movements. When I move horizontally, the animation “walk” is set, but the legs run or do not move. It is not the idle state either. I think an update is too fast.

Updates are never too fast. What do you mean by " the legs run or do not move"? Is the walk animation visible, or visible only too shortly? You can also ask in German as I am from Mozart's home country 🙂.

Hallo Harald ich grüße Salzburg,
auf deutsch geht es evnetuell besser, da mein Englisch nicht gut genug ist und Googl nicht immer das übersetzt was ich meine.
Natürlich habe ich mir alas erstes die Spine Beispiele durchgesehen und getestet und gesehen es führen viele Wege nach Rom. Dabei versucht, alles zu kombinieren. Begonnen habe ich mit den Beginner Tutorials von Unity.
Nur von den Dokus (Spine Unity und die API) ist es nich ganz so einfach eigene Ideen umzusetzten; zumal fast immer auch entsprechende Inspector-Einträge notwendig sind. Deswegen auch meine Äußerungen "leraning by doing". Man kann logischer Weise die Spine-Demos nicht einfach mal so übernehmen, man muss viel testen.

Das was ich jetzt im CharacterControler geschfrieben habe kommt eventuell den Spine-Anforderungen etwas näher.
Die Beine starten bei "walk" ganz kurz, Füße gehen zusammen und bleiben dann so, aber nicht wie bei "Idle", breitbeinig.
Beim "Stehen" wieder "idle". Der Seiten-Switch klappt, Jump ist auch OK , noch ohne Mix.
Wenn ich die Move-Tasten (A und D) kurz antippe bewegt sich ein Bein, aber wenn ich festhalte gibt es kein "Laufen" ??
Habe das auch mit dem "Spineboy" getestet, bei "Walk" und Taste festhalten läuft er auch nicht, nur gleiten !!
:grinfake

zur Zeit versuche ich ein "Movement" mit den beiden Demoskripten BasicPlatformCotroller und SkeletonAnimationHandleExample aus Spline-Examples hin zu bekommen. Hier läuft der Player auch nicht, bewegt sich steif nach links oder rechts. !!
Aber auch hier werden die Zusammenhänge mangelhaft erläutert, also wieder "Learning by doing" !

superkerni wrote

Hallo Harald ich grüße Salzburg,

Hallo Wolfgang,
Zwar ist es Graz statt Salzburg (es war nur das Heimatland gemeint, die Stadt ist eine andere), aber ebenso Grüße zurück!

superkerni wrote

Man kann logischer Weise die Spine-Demos nicht einfach mal so übernehmen, man muss viel testen.

Zugegebenermaßen sind die Szenen 4 Object Oriented Sample und 5 Basic Platformer viel zu fortgeschritten als 4. und 5. Szene, bzw. hier auch over-engineered. Wir planen die Szenen in Spine Examples in den 4.0 beta spine-unity runtimes komplett zu restrukturieren, auch einiges zu ersetzen, um hier nicht z.B. durch das Model View Controller Pattern mehr zu verwirren als in der Strukturierung zu helfen.

superkerni wrote

Die Beine starten bei "walk" ganz kurz, Füße gehen zusammen und bleiben dann so, aber nicht wie bei "Idle", breitbeinig.

Das Problem wird höchstwahrscheinlich bei deiner Game Logik liegen, es klingt so als ob skeletonAnimation.state.SetAnimation zu oft (dauernd) aufgerufen wird, obwohl du das nur einmal intendiert hattest. Das sollte sich einfach debuggen lassen per quasi printf-debugging, per Unity Äquivalent Debug.Log("...");. Fern-Debugging durch Code-lesen ist hier schwierig. Bei deiner Erfahrung ist das für dich sicherlich ein Kinderspiel.

Oder einfach einmal deine Eingabe-Logik umgehen und nur ohne dieser einfach die Animationen starten, wenn das nichts tut, dann ist vielleicht etwas an den AnimationReferenceAssets nicht in Ordnung (diese müssen vom selben SkeletonDataAsset abstammen, nicht z.B. ein "run" AnimationReferenceAsset von Spineboy bei Raptor verwenden).

superkerni wrote

zur Zeit versuche ich ein "Movement" mit den beiden Demoskripten BasicPlatformCotroller und SkeletonAnimationHandleExample aus Spline-Examples hin zu bekommen. Hier läuft der Player auch nicht, bewegt sich steif nach links oder rechts. !!

Die Skripte in Spine Examples sind hier im Kontext der Szenen sinnvoll, in Isolation ohne die anderen Skripte der selben Szene eventuell nicht.

superkerni wrote

Aber auch hier werden die Zusammenhänge mangelhaft erläutert, also wieder "Learning by doing" !

Ich denke hier herrscht ein generelles Mißverständnis. Die Skripte und Szenen in Spine Examples sind (wie der Name schon sagt) Beispiele, wie man die spine-unity runtime verwenden kann. Sie dienen dazu, dass man sieht, wie man Lösungen bauen könnte und wofür man die einzelnen Bausteine verwenden kann. Die Skripte sind strikt getrennt von denen im Top-level Verzeichnis Spine. spine-unity ist ein Animations-Framework, keine Gameplay Bibliothek. Wenn die Beispiel-Skripte für dich beim Lesen keinen Sinn machen, dann bitte diese einfach ignorieren (die Skripte in Object Oriented Sample machen z.B. wenig Sinn wenn man kein Fan des MVP Patterns ist oder es hier für over-engineered hält). Wie gesagt sind die beiden Szenen zu kompliziert, bitte dann an die anderen Beispiele halten.

Man kann mit dem Code aus 2 Controlling Animation oder 3 Controlling Animation Continued sehr weit kommen, für deinen Fall würde ich diese einfacheren Beispiele empfehlen. Die Beispiele haben hier niemals den Anspruch, Spieleentwicklung in Unity im Generellen zu erklären, sie sollen nur zeigen, wie man 2D Spine Animationen darin einbinden kann.

Hallo Harald,
danke für die ausführliche Antwort. Die Example-Scripte machen schon Sinn, aber in der Summe sieht man nicht gleich, welches Skript für die eigene Anwendung sinnvoll umzugestalten geht.
Habe in der Zwischenzeit eine Lösung gefunden, die erst einmal funktioniert. Man kann diese ja weiter ausbauen, denke ich jedenfalls. Euer Charakter läuft jetzt ordentlich. Nochmals danke für Deinen Aufwand mit mir.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine;
using Spine.Unity;
using Spine.Unity.AttachmentTools;

public class PlayerMoving : MonoBehaviour
{

public float speed;
public float jumpspeed;
public Transform graphics;
float x;
float y;
string currentAnimation = "1_Idle";
public SkeletonAnimation skAnim;
Rigidbody2D rb;
bool isJumping;
   
void SetAnimation(string name, bool loop)
{
    if (name == currentAnimation)
        return;

    skAnim.state.SetAnimation(0, name, loop);
    currentAnimation = name;
}
private void Awake()
{
    rb = GetComponent<Rigidbody2D>();
    isJumping = false;
  
}
void FixedUpdate()
{
    x = Input.GetAxis("Horizontal");
    rb.velocity = new Vector2(x * speed, rb.velocity.y);
    if (x>0)
    {
        graphics.localRotation = Quaternion.Euler(0, 0, 0);
        SetAnimation("1_Walk", true);
    }
    else if (x<0)
    {
        graphics.localRotation = Quaternion.Euler(0, 180, 0);
        SetAnimation("1_Walk", true);
    }
    else
    {
        SetAnimation("1_Idle", true);
    }
    if (Input.GetButtonDown("Jump"))
    {
        Jump();
    }
}
void Jump()
{
   
    rb.velocity = new Vector2(rb.velocity.x, jumpspeed);
    
    if (y > -1.32f)   
    {
        isJumping = true;
        SetAnimation("1_Jump", false);
    }
}

}

Hallo Wolfgang,
Freut mich sehr, dass Dein Skript nun funktioniert, danke für die Rückmeldung! Wir werden auch versuchen Dein Feedback beim Umgestalten der Beispielszenen zu berücksichtigen.