Edit: Converting into a general Unity Q&A thread, cos it is *needed*
Hi guys :)
So I started venturing into Unity and already I've hit a bit of a stumping point...
How do I do 2D sprite animation? I've googled around but nothing seemed... Understandable. I found one piece of code that gave me the ability to run a spritesheet as a material and animate it, but it wasn't positioned correctly on the plane, it was interploated to mushy hell and not clean pixels, and there was no transparency...
I know many people have done this sprite animation thing before me sooooo...
Oh brothers (and sisters) in arms, lend me your pixelly spritey animation sword and please point me to something I can use to do animated sprites...
Thanks :D
Hi guys :)
So I started venturing into Unity and already I've hit a bit of a stumping point...
How do I do 2D sprite animation? I've googled around but nothing seemed... Understandable. I found one piece of code that gave me the ability to run a spritesheet as a material and animate it, but it wasn't positioned correctly on the plane, it was interploated to mushy hell and not clean pixels, and there was no transparency...
I know many people have done this sprite animation thing before me sooooo...
Oh brothers (and sisters) in arms, lend me your pixelly spritey animation sword and please point me to something I can use to do animated sprites...
Thanks :D
Comments
Many people seem to recommend 2D Toolkit or SpriteManager.
I don't know of free libraries that do it well unfortunately.
On the sprite sheet itself make sure it is not being compressed, and is set to true colour. should fix your texture looking bad. also have a look at the "Texture type"
on the material you will find "Tiling" and "Offset", make sure those are set up right for your sprite sheet.
but ideally you would not change the material to animate...unity has some funny stuff happening, each time you change the material it creates a new one apparently, so after a while that could add up. best to animate by changing the UV coordinates on your plane. @tbulford wrote one for his A-Maze workshop (most of the stuff I said here is stuff he found out). For my D competition entry I also wrote my own if I remember correctly, but I'm sure there must be plenty floating around on the interwebs :) hope this helped
Edit: well seems I was a bit slow :P
At this stage I'm only going to venture into the free stuff for now, $400 for GMS later I'm going to stick to my own advice and not go into paid for stuff until I *need* it XD
This bit of code will set the UVs of an object correctly assuming the spritesheet contains 8x8 tiles. Action represents the row and state represents the column. direction can be 1 or 0. I initially tried achieving this by setting the UVs manually but that turned out to be all kinds of terrible.
If you add the script to your gameobject/player you should be able to upload each frame into the Inspector under the script's tabs.
Just shout if something doesn't make sense. It's not really easy to explain like this :|
Batching can only happen if objects share a material. Any change to any material means its a new instance even if its exactly the same as all the other instances. If you change a material u/v for a sprite each sprite will be a separate draw call and potentially ruin your performance. This is ofc hardly a big deal on smaller games esp if you don't care about mobile. Its however good to try keep good practices always.
@RickyGC I really don't think having a texture per animation frame is a good approach. You loosing so much performance opportunity. The common method is to change the texture coords in the mesh. I just dropped the Unity 2D workshop project in another thread the code to do the UV swap is there. Its how we manage Toxic Bunny HD sprites in Unity and works on many platforms already.
Has anyone worked with the 4.3 beta yet, specifically working with sprite animation?
But I jest, I can see the use for the nuance. Thanks, it's been enlightening.
Check your material counts in the profiler and use Resources.UnloadUnusedAssets() to check if you've got resources floating around with no references to them. Chances are you probably do if you're modifying materials via script - every time you call renderer.material, you're creating a clone. If you do it twice, you're leaking the first clone.
This means that enemies are free to share the same material as long as they don't need anything unique done to them graphically, but as soon as we start fading an individual object (for instance), it'll spawn its own material and then get dumped out of the drawing batch. It sounds complicated, but all I'm doing is letting Unity manage the draw calls for me and buffering material creation/loading as needed.
Using .sharedMaterial can help when it comes to batching, but be super careful with it because it will modify the *actual* material data in your project, meaning that you could end up saving those changes permanently once your app has stopped. Sometimes this doesn't matter (ie. dynamic variables stored in the material for a shader), but it could cause big headaches too.
We made use of both methods extensively in Bladeslinger, depending on the circumstances.
I haven't had a chance to try the info out (life getting in the way of game making, what IS that?! :P), but really thanks everyone for the input! :D
For example transform.Translate(-0.1,0,0) gives me an Error...
Is there no way of tweaking movement to a slower speed (I'm doing this per step) unless using rigidbody and velocity/addForce? :s
The f stands for floating point which is the value type the function is accepting. I believe without the f the number is implicitly cast as a double?
So that you move in units per second instead of units per frame (assuming this code is in Update() )
Also then, I've been reading about getComponent but can't get it to bloody work.
I have a controller with a public variable
the script is called RunningController and the variable is called RunningSpeed...
I want to call that variable from another script,
So this is far as I got, but it doesn't work...
globalRunningSpeed = GetComponent<RunningController>().runningSpeed;
This script lets the game start, but it throws errors during runtime...
NullReferenceException: Object reference not set to an instance of an object
BuildingBehaviour.Update () (at Assets/BuildingBehaviour.cs:17)
Help?
As far as the getComponent goes, you need to specify the object that you want to get the component from. So it should be specificObject.GetComponent<RunningController>().runningSpeed;
An easier way to do it (although slightly messy) is to just declare a public reference. So in the script that you need the speed do something like :
you can then access the speed with :
You can then just drag and drop the game object that has the RunningController script on it into the reference to link it.
You have to be getting the component from an object :). So you have to tell it where to took before you can tell it what to look for :).
It's like Gamemaker's syntax kinda: gameobject.variableName
So in this case nameOfObjectWhereVariableIs.GetComponent<RunningController>().runningSpeed;
But, since the script is on the same object as the script that's calling get component, just use gameObject (which refers to the game object the script/component is on).
So the code would be: gameObject.GetComponent<RunningController>().runningSpeed; :)
I don't get it... I've been trying that and it hasn't been working...
I have a gameObject. It's named controllerRun. It says so in the hierarchy.
I have these instantiated prefabs, Building01, Building02, Building03.
In them are a script component BuildingBehaviour.
In that script are these lines:
The last bits regarding globalRunningSpeed are what matters, I think...
What am I doing wrong here @_@
an easier way that might make more sense as well would be to do something like this:
Then you just have to drag and drop the object with the RunningController script on it into the public variable and it will link it.
THAAAAAANKS :D
Cross-engine syntax and stuff is so hard to wrap head around @_@
public RunningController runController;
Can be read as:
public nameOfExternalObject objectNameInThisScript;
Is that right?
Omg unity syntax XD
Edit: So I'm trying to use @rigormortis's second method, but in the component of my prefab I have this line that I can't drag objects into - neither the script object nor the object in the hierarchy that contains the runningController script... I've tried many combination of the three things, trying different combinations... It doesn't let me put anything into that field. What' the logic of this syntax... I'm not getting it XD
Also, to use prefabs they have to be instantiated first. Either in game hierarchy, or as a gameobject property linked via editor. If you need to instantiate prefabs in run time the best method is to have a script that can hold cached references to prefabs in design time, and then just clone them in run time.
@dislekcia your code is theoretically *that* simple. I get that it should be that simple.
But where the heck do I stick that first bit of Class Global, etc? I tried putting it in something like this:
And stuck that onto my empty gameObject called gameController, which is in the scene, in the hierarchy. I've tried renaming this to "Global". no success.
And then tried to access Global.runningSpeed from other scripts, and it tells me "Global does not exist in the current context".
Where do I stick a class?