Jump to content

[RESOLVED] Unity animation.Play Problem


Recommended Posts

Unity's animation.Play() is not playing my clips. What am I missing?

this is the beginning of a part's plugin. Click the part, select "Red down", and the lever rotates down. right-click again, select "Red up", and the lever rotates up. Or, that's what is supposed to do.

Currently, it does change the command in the context menu. However, the lever does not move.

I verified in Unity's preview window that that entire scene does play. I cannot use ModuleAnimateGeneric, because I'll be using more than a single animation from the Scene animation. This is just a simple example to demonstrate my problem.


using UnityEngine;

namespace Animate
{
public class Animate : PartModule
{
private bool redUp = true;

public override void OnStart(PartModule.StartState state)
{
}

[KSPEvent(active = true, guiActive = true, guiActiveEditor = false, guiName = "Red down")]
public void LeverRed()
{
redUp = !redUp;
Events["LeverRed"].guiName = (redUp ? "Red down" : "Red up");
if (redUp)
animation.Play("redup");
else
animation.Play("reddown");
}


public override void OnUpdate()
{
base.OnUpdate();
}
}
}

EQNfvg5.jpg

Edited by Apollo13
Link to comment
Share on other sites

You need to tell Unity what animation it's supposed to be playing by creating an instance of the animation class.

Is that lowercase animation in your example supposed to be an instance of Animation? Because those methods aren't static, so it wouldn't work or compile otherwise.

A common way of initializing the Animation instance is something like this:


Animation anim;

private void Start()
{
anim = part.FindModelAnimators(Scene)[0];
}

[KSPEvent(...)]
public void play()
{
anim.Play(Scene);
}

Link to comment
Share on other sites

It compiles (without errors) and executes. The context menu is displayed. When I click the button, the giuName changes.

Here is the Unity reference page I used: Animation Play method

which contains this code example, not requiring instantiation of a class:


using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
void Example() {
animation.Play("walk");
}
}

Note that "walk" is not the entire Scene, but a clip from within.

I just now looked at Debug Log, and I saw this upon clicking the "Red down", "Red up" button:

[Exception]: NullReferenceException: Object reference not set to an instance of an object

Here is my project file. The File contains: project file

1) Blender project files, with .blend file, UV map textures, FBX export

2) Unity project files: Models, Texture

3) KSP GameData: with MU, MBMs, cfg

Edited by Apollo13
Link to comment
Share on other sites

I can't really contribute to the problem at hand, but I recommend you switch to .Blend, .Play doesn't play nice, only one .Play can be operating on an object at a time, this is why KSP partmodules don't play well together. .Blend is functionally the same as .Play but it's totally cool with multiple animations playing at once; it might not matter to what you're doing, but it'll make your stuff play well with other people's stuff, as long as they use .Blend too.

Link to comment
Share on other sites

Anybody got any idea what that NulllReferenceexception might be referring to? Or, any other ideas concerning my problem?

thanks

my best guess is:

you fall for the unity documentation scam!

you went there and naively thought "Hey example code" - but naaahhh..

it's just "dummy code" - or at least not copy paste code..

the example uses a object with the name "animation" - that is NOT there from it's own..

=> null ref

the documentation didn't mention the fact, that thi code will only work, IF there is an object "animation"..

The above code works for me only inside a foreach loop made on every animation in the model and additionally an if-statement to filter the right one by name..

To me, that doesn't seem logic that way - but it's the only way I got it to work..

hth

Link to comment
Share on other sites

It compiles (without errors) and executes. The context menu is displayed. When I click the button, the giuName changes.

Here is the Unity reference page I used: Animation Play method

which contains this code example, not requiring instantiation of a class:

[snip]

Note that "walk" is not the entire Scene, but a clip from within.

I just now looked at Debug Log, and I saw this upon clicking the "Red down", "Red up" button:

[Exception]: NullReferenceException: Object reference not set to an instance of an object

PartModules inherit from MonoBehaviour which comes with some conveniences, like the member variables animation, collider, renderer, etc. They're shortcuts for components attached to the same GameObject as the script. The example assumes the simplest case: a user will create a new GO with some kind of animation on it and then attach their script directly to it.

If we dump the contents of your Part ingame, you'll see this:

[LOG 20:43:11.152] DebugTools, Levers has components:
[B][LOG 20:43:11.152] DebugTools, ...c: UnityEngine.Transform
[LOG 20:43:11.153] DebugTools, ...c: Part
[LOG 20:43:11.154] DebugTools, ...c: Animate.Animate[/B] <------------
[LOG 20:43:11.154] DebugTools, --->model has components:
[LOG 20:43:11.155] DebugTools, ......c: UnityEngine.Transform
[LOG 20:43:11.155] DebugTools, ------>animate has components:
[LOG 20:43:11.156] DebugTools, .........c: UnityEngine.Transform
[LOG 20:43:11.156] DebugTools, .........c: [I][U]UnityEngine.Animation[/U][/I]
[LOG 20:43:11.157] DebugTools, --------->Cube has components:
[LOG 20:43:11.158] DebugTools, ............c: UnityEngine.Transform
[LOG 20:43:11.158] DebugTools, ............c: UnityEngine.MeshFilter
[LOG 20:43:11.159] DebugTools, ............c: UnityEngine.MeshRenderer
[LOG 20:43:11.159] DebugTools, --------->Cube.001 has components:
[LOG 20:43:11.160] DebugTools, ............c: UnityEngine.Transform
[LOG 20:43:11.160] DebugTools, ............c: UnityEngine.MeshFilter
[LOG 20:43:11.161] DebugTools, ............c: UnityEngine.MeshRenderer
[LOG 20:43:11.162] DebugTools, --------->Plane has components:
[LOG 20:43:11.162] DebugTools, ............c: UnityEngine.Transform
[LOG 20:43:11.163] DebugTools, ............c: UnityEngine.MeshCollider
[LOG 20:43:11.163] DebugTools, ............c: UnityEngine.MeshFilter
[LOG 20:43:11.164] DebugTools, ............c: UnityEngine.MeshRenderer

You can see that PartTools has taken the entire Unity hierarchy and moved it under a GO called "model". Your script, marked with the arrow, tries to access animation which returns null because the GameObject called "Levers" has no Animation component in it. This is where you need to follow DMagic's advice: when your PartModule starts you need to go find and store a reference to the animation; use that stored reference to play your clips

Link to comment
Share on other sites

this is actually what I ment - but as allways, if xEvil explains it, it sounds like a valid doc..

amazing..

Einstein said "If you can't explain it to a child within 2 minutes, you didn't understand it your selfe"..

guilty as charged..

back on topic, here's the code that works for me..

this is called if the radar altitude get's below 100 and it toggles the landing gears automatically

I'm sure someone could write this with 20 lines less - but well..


void runLegAnimations()
{
if (legState == 0)
{
if (legAction=="down")
{
legState = 1;
foreach (Animation animation in this.vessel.rootPart.FindModelAnimators("LandingLegsLower"))
{
animation.Rewind();
animation.PlayQueued("LandingLegsLower");
}
}
}
else
{
if (legState == 1)
{
if (legAction == "up")
{
legState = 2;
foreach (Animation animation in this.vessel.rootPart.FindModelAnimators("LandingLegsRaise"))
{
animation.Rewind();
animation.PlayQueued("LandingLegsRaise");
}
}
}
else
{
legState = 0;
}
}
}

hint: if your part is not the root part in any case, modify the code accordingly..

hth

Link to comment
Share on other sites

Folks,

Thanks for those very detailed explanations. I appreciate that you took the time (and with editing, a long time), to draft your responses. Also, every time the game enters a scene, it calls OnStart(). Does that not rewind the animation?

@xEvilReeperx: how did you get that debug dump?

Edited by Apollo13
Link to comment
Share on other sites

It's just a little extension I wrote to GameObject, part of a set of handy snippets I share between all projects. It's not very clean but it does the job

public delegate void GameObjectVisitor(GameObject go, int indent);

public static class DebugExtensions
{
private static void internal_PrintComponents(GameObject go, int indent)
{
Log.Debug("{0}{1} has components:", indent > 0 ? new string('-', indent) + ">" : "", go.name);

var components = go.GetComponents<Component>();
foreach (var c in components)
Log.Debug("{0}: {1}", new string('.', indent + 3) + "c", c.GetType().FullName);
}

public static void PrintComponents(this UnityEngine.GameObject go)
{
go.TraverseHierarchy(internal_PrintComponents);
}

public static void TraverseHierarchy(this UnityEngine.GameObject go, GameObjectVisitor visitor, int indent = 0)
{
visitor(go, indent);

for (int i = 0; i < go.transform.childCount; ++i)
go.transform.GetChild(i).gameObject.TraverseHierarchy(visitor, indent + 3);
}
}

It comes in handy in all sorts of situations

Link to comment
Share on other sites

Thank you all, again, for your help. I used DMagic's magic code snippet, and everything works like a bloody charmer. With the code provided by Philotical and the debug dump from xEvilreeper, I'm well on my way.

my best guess is:

you fall for the unity documentation scam!

you went there and naively thought "Hey example code" - but naaahhh..

Yep, I fell for that internet scam. Kinda like the time that Nigerian banker promised to send me 5.4 million dollars if i sent him $5,000 to to bribe the Nigerian bank. I'm still waiting.

@xEvilReeperx: thanks for sharing that code. that's now a part of all my projects.

Edited by Apollo13
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...