- Home /
Unity 2D : Can you change a 2D animation clip's sprites at runtime?
Hi there,
I'm working in Unity's 2D mode and using the Unity UI I've created a GameObject with an Animation Controller (Animator) linked up with six different Animation Clips. While running the game this GameObject properly transitions between all of the animation clips.
I'd like to use this object as a prefab. At runtime I want to clone it and swap out the sprites being used for the animation clip key frames.
In other words I have object A that uses a Sprite_Sheet_A. Now I want to clone Object A and start using Sprite_Sheet_B.
Once I clone object A how can I access its Animation Controller, view the Animation Clips being controlled and swap out their sprites?
EDIT: When I say Animation Clip... I might mean Animation. The difference between these classes in 2D is not super clear for me.
If you want to clone an object and change it's sprites at runtime, you'll need to do it with scripting. The relevant references can be found here, but it's likely that it won't be easy:
http://docs.unity3d.com/Documentation/ScriptReference/index.html
It's a better idea to make another prefab for the object with different sprites.
Thanks for the reply but I think you misunderstand my question. I am trying to clone a GameObject that has an Animator, Animator Controller and several Animation Clips attached to it.
Each Animation Clip is a series of sprites that add up to a frame-by-frame animation. I want to clone that and then replace each frame with sprites from a new sheet.
For example, lets say I have 2D game with a character that walks from left to right. I have animated the walking motion. Now I want to add a new character that reuses all of the animation logic. I don't want to remake ALL of the animations using a new set of sprites. I just want to copy the animation I made for the first character and apply the new sprites.
http://forum.unity3d.com/threads/213431-Changing-Animation-Sprites Unity says there's no easy way to do what you want in this thread, but supposedly Sprite$$anonymous$$anager can help:
http://wiki.unity3d.com/index.php?title=Sprite$$anonymous$$anager
Answer by soulburner · Nov 05, 2014 at 02:56 PM
You CAN do this.
All you need to do is to change sprite in the LateUpdate() method.
PS: Late 2018 update. The solution is still very useful. I shipped 2 games using it and will use it in future. The performance drawback is not noticeable at all. But you may consider the following optimizations: 1. You can cache the sprite. And if it was not changed from the previous frame, you don't need to replace it again. 2. You can consider creating a hash of name-sprite pairs. So, you will get a "sprite by name" faster later (considering that your animation probably will need to make the same operation over and over again on the same object).
soulburner is correct... see Unity's video about this at 20:00 in: https://www.youtube.com/watch?v=r$$anonymous$$CLWt1DuqI
That is A$$anonymous$$AZING. Need do check this out. Sadly, OP is probably not interested into this anymore
OP here. I've dropped the project that originally spawned this question but the answer is still good to know :D
Perfect answer! Thanks a lot!
Applies to sprite animations AND bone animations.
Nice guideline for implementation: the link in bererton´s comment.
I spent hours trying to get this done. I really wonder why there arent´t some clearer instructions concerning this problem in the unity scripting reference. This is a must have for every single game sporting different looking characters (races / classes etc) with same animation patterns...
Answer by retry_entry · Oct 18, 2017 at 10:29 AM
There is a better solution. Use this script - https://github.com/RetryEntry/UnityAnimatorChangeSprite Please give thumbs up, cause I have spent two days searching through useless solutions like one that soulburner suggected. If you have 15 gameobjects with 15 sprites in animation chain you will spend up to 225 loops every frame searching for sprites to swap to... With such approach you CAN'T create for instance charactes with different clothes animated by one animator, cause you will spend 12000 loops every second on useless things like searching. With this script you will not spend time... It uses shaders. You can change it as you'l like, Just star please. I have spent two days... :/
Yes, It works like a charm. If your character color is different its because with the current shader it requires light. Add directional light to the scene adjust the intensity & it will work perfectly. Thanks mate.
No, your solution is not better.
It doesn't support sprite animation. If the animation changes sprites, your script doesn't work.
It has no sense. If you are not using the sprite animation, why do you need a special shader for that? You can just change the sprite once when object is initialized and if there are no texture-changing keyframes in the animation, it wouldn't be changed.
I have shipped 2 games with this technique. And it works fine. There is no performance drawback even when I have 30 skinned characters with 6 sprites in each. I made a lot of profiling of my games and my solution never even visible in the profiler. Of course, I added some caching so I don't replace the sprite again if it was not changed from the previous frame.
Soulburner.... idk what are you talking about - thius solution DOES support sprite animation. Thats the whole point. Get brains pls somewhere. Your solution sucks and its not even yours. It was presented at some conference like in 2012 or smth like that, I saw that video on youtube.
@retry_entry, Did you write the Custom/SwapTwo shader? It does work beautifully as you said when using the built-in render pipeline but I noticed that when I try to use URP, it stops working (i.e., all my sprites turn pink). Any ideas what could be going wrong?
@retry_entry, did you write the SwapTwo shader? Does this work with URP? I love how your script works and you're right the solution seems very simple I can't believe Unity doesn't have a solution like this for such a simple problem. I do not understand shader code however and when I try to use URP, the solution stops working. Any ideas?
Thank you, man, you saved my project. I just swap sprite in Awake, and it works perfect, no need to swap every frame.
public Texture2D head;
public Texture2D body;
void Awake () {
Shader _swapShader = Shader.Find("Custom/SwapTwo");
Material _newMat1 = new Material(_swapShader);
headSR.material = _newMat1;
headSR.material.SetTexture("_MainTex2", head);
Material _newMat2 = new Material(_swapShader);
bodySR.material = _newMat2;
bodySR.material.SetTexture("_MainTex2", body);
}
Answer by Mike-Geig · Mar 31, 2014 at 04:54 PM
Edit: See the accepted answer for a better solution
Animations are stored in .anim asset files. As such, there is no easy way to modify them at run time. My recommendation would be to create multiple .anim files with the variations you desire and then swap them out on the fly at runtime.
Thanks... I get that this is the intended use but if you're doing random/procedural content or you just have too many permutations to animate by hand then this solution is just too tedious.
How would I actually do this? I have multiple .anim files, but how would I swap them out on the animator controller?
See soulburners answer and the video posted in the comment to that.
There is absolutely no need to create multiple anim files if you have the same animations for different sprites.
So would you swap out the animation controllers at runtime then? And have a seperate controller for each piece of equipment? Or is there a way to switch out the animation files in the controller? Im also confused by this
Depends on what you want to do.
OPs question was about switching sprites at runtime, not animations/animation controllers. $$anonymous$$g.: Regardless of whether your character wears a chainmail or a smoking - everything moves the same way. If that´s what you have in $$anonymous$$d: no need to swap animation controllers, see here (about $$anonymous$$ute 20): https://www.youtube.com/watch?v=r$$anonymous$$CLWt1DuqI
The way I am animating the separate parts of the body uses an animator and an animator controller for each piece of armour. This seems a little bit unrealistic, but it makes sense to me because the only way to display the armor moving on the character is to have it as an animation. If there was a way to switch out which sprites the animation was looking at, that would be amazing and I could just use one animation controller but I have not been successful.. Any ideas? @mos3456
Answer by Lachee1 · Jun 12, 2016 at 05:12 AM
I use a script like this to swap sprites out
using UnityEngine;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public class SkinController : MonoBehaviour {
private new SpriteRenderer renderer;
public List<SpriteCollection> skins = new List<SpriteCollection>();
public int skin = 0;
void Start()
{
renderer = GetComponent<SpriteRenderer>();
//First thing we must do is load all the sprites for the character
foreach (SpriteCollection coll in skins)
coll.sprites = Resources.LoadAll<Sprite>(coll.sheet.name);
}
void LateUpdate()
{
//Select the correct sprite
SpriteCollection coll = skins[this.skin];
//Get the name
string spriteName = renderer.sprite.name;
//Search for the correct name
if (coll == null || coll.sprites == null) return;
Sprite newSprite = coll.sprites.Where(item => item.name == spriteName).ToArray()[0];
//Set the sprite
if (newSprite)
renderer.sprite = newSprite;
}
}
[System.Serializable]
public class SpriteCollection
{
public string name;
public Texture sheet;
[System.NonSerialized]
public Sprite[] sprites;
}
Could you possibly explain this a bit? This may be useful to me and I am having a little trouble understanding exactly what its supposed to do.
Answer by Loius · Mar 31, 2014 at 04:58 PM
No, you can't. I have an asset on the asset store specifically for this problem:
You're answering wrong just to advertise your own asset?
Reported.