Search Unity

Adding animation clips from a loaded resource

Discussion in 'iOS and tvOS' started by Sam at FPS, Aug 25, 2010.

  1. Sam at FPS

    Sam at FPS

    Joined:
    Sep 1, 2009
    Posts:
    80
    I have several character models and several sets of animations in my Resources folder.

    What I'm wanting to be able to do is Instantiate character model X and add to it Animation group Y.

    For example: Below, this script is attached to a character prefab I have instantiated. During the Awake() method, I want to load up the animation 'package' I require (in this case 'animationY') and extract out the animation clips I require (Idle and RunLoop).

    Code (csharp):
    1. private AnimationState IdleAnimation;
    2. private AnimationState RunLoopAnimation;
    3.  
    4.  
    5.     void Awake()
    6.     {
    7.         GameObject testAnim = Resources.Load("Characters/Anims/animationY", typeof(GameObject)) as GameObject;  
    8.  
    9.     this.IdleAnimation = this.AddAnimationClip(testAnim,"idle");
    10.     this.RunLoopAnimation = this.AddAnimationClip(testAnim,"run_loop");
    11.  
    12.     }
    13.  
    14.     private AnimationState AddAnimationClip(GameObject testAnim, string animationString)
    15.     {
    16.         AnimationClip theAnimation = testAnim.animation.GetClip(animationString);
    17.         this.animation.AddClip(theAnimation, animationString);
    18.         return this.animation[animationString];
    19.     }
    The problem is that this code works ok once, but then if I reload the scene (via going back to my main menu scene then back to this scene) I get null reference exceptions when extracting the animations. This only happens on the iPhone. When running on Standalone Unity I don't get any problems.

    The animations appear to be there, but when I grab the Animation Clips out of the animation states they come out as null. So my code is failing on the AddClip() method above... but only the second time the scene is loaded.

    So my questions are:

    Is there any way that what I am doing above can actually modify the resource that I am loading? I didn't think that was possible, but it seems like I am reassigning the animation clips somehow so that the second time I go to extract the clips from the resource they are missing (null).

    Also, is the code above correct in that I'm not Instantiating the animation GameObject, but rather just loading it and extracting the clips? Should I actually have to Instantiate the GameObject, extract the clips then Destroy it?

    Is there something special about how Unity loads resources on the iPhone? Does it cache the results or something?
     
  2. goodhustle

    goodhustle

    Joined:
    Jun 4, 2009
    Posts:
    310
    I do something similar but have never run into that exact issue. Is the object whose component calls Resources.Load part of the scene, or do you instantiate that dynamically as well? In my scene, I have a controller script which instantiates a model with an animation component, then it loads animations from the Resources folder and then attaches them similarly to what you've posted.

    However, I HAVE had issues where AnimationEvents on AnimationStates are NOT cleared when re-loading a scene through the editor. This leads me to believe that there is some caching of animationclip resources behind the scenes, or at least of animationevents attached thereto.
     
  3. Sam at FPS

    Sam at FPS

    Joined:
    Sep 1, 2009
    Posts:
    80
    Thanks for the reply getluky.

    The object that is calling Resources.Load() is also instantiated dynamically. I'll try moving the adding of animations out into a scene object and see if that makes a difference.

    I do actually have something I call CharacterFactory that creates the models in the first place, but since my animations were scene specific I was loading the animations differently to the models. I'll try putting them all together.

    It's good to hear that someone else is doing what I'm trying. :)
     
  4. Sam at FPS

    Sam at FPS

    Joined:
    Sep 1, 2009
    Posts:
    80
    If anyone is interested, I think I've found a working solution to this problem.

    Now I have a scene object with a CharacterFactory script on it, which does...

    • Loads the model from a Resource.
    • Instantiates the model.
    • Loads the animations from a Resource.
    • Instantiates the animations object.
    • Extracts the required animations and adds then to the model.
    • Destroys the instantiated animations object.
    • Returns the new model with its animations.

    I don't think that simply loading the animations from a scene object as opposed to a dynamically created object fixed it. But it may have.

    I'm also not certain that it is required to instantiate the animations object as I'm doing. It could well be a combination of things plus me refactoring the code that has changed something to make it work.

    But I'm not complaining now because it works. :)

    And here is representative code of what that looks like if anyone has suggestions of improvements or redundancies.

    Code (csharp):
    1.     public GameObject GetCharacter()
    2.     {
    3.         Object newCharacter = Resources.Load("Characters/CharcterA", typeof(GameObject));
    4.         GameObject newCharacterGameObject = Instantiate(newCharacter) as GameObject;
    5.  
    6.         Object testAnimObject = Resources.Load("Characters/Anims/animationsY", typeof(GameObject));
    7.         GameObject testAnim = Instantiate(testAnimObject) as GameObject;
    8.  
    9.         this.AddAnimationClip(newCharacterGameObject, testAnim, "idle");
    10.         this.AddAnimationClip(newCharacterGameObject, testAnim, "run");
    11.  
    12.         Destroy(testAnim);
    13.  
    14.         return newCharacterGameObject;
    15.     }
    16.  
    17.     private void AddAnimationClip(GameObject toAddTo, GameObject testAnim, string animationString)
    18.     {
    19.         AnimationClip theAnimation = testAnim.animation.GetClip(animationString);
    20.         toAddTo.animation.AddClip(theAnimation, animationString);
    21.     }
     
  5. Sam at FPS

    Sam at FPS

    Joined:
    Sep 1, 2009
    Posts:
    80
    One more thing FYI...

    I require that the animations update while offscreen, BUT, setting the updateWhenOffscreen property in code will cause all your animations to stop playing.

    ie, in the code above..

    Code (csharp):
    1. (newCharacterGameObject.GetComponent(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer).updateWhenOffscreen = true;
    Will make nothing work. Not the same null reference exception like I described in the OP, but another trick to learn if you're loading things dynamically like I am. You have to set it in your prefab if you want it to work.
     
  6. nonehill

    nonehill

    Joined:
    Oct 29, 2014
    Posts:
    7