Unity2Dでアニメーションを作成
アニメーションを作成するには?
ゲームにアニメーションって必須ですよね。
今回は一枚の画像の中に複数書かれたモノを自動で切り取って、それをUnity上で動かす方法を説明します。
…意味が分かりませんよね(笑)
まずはOpenGameArt.orgに行ってみてください。
ここにはゲームの素材用画像がフリーでたくさん置いてあります。
(非常にありがたいです!)
この中に一枚の画像なのに同じものが複数動いているように書かれている画像がよくあります。
例えば↓のような画像です。
こんな画像がいっぱいあるんです。
最初見た時、これどうやって使うの?って思いました。
それと、最初から一枚ずつの画像にしてくれればいいのにとも思いました。
なんとこれ、Unity上で自動で一枚ずつに切り分けてくれるんです。
画像の切り取り方法
まずはアニメーションにしたい画像をUnity上に取り込みましょう。
これは以前説明した通りですが、一応記載します。
以下の通りにしてみましょう。
そして対象画像を開いてInspectorウィンドウのSprite ModeをMultipleへ変更します。
Applyを押して変更を保存した後、Sprite Editorをクリック。
別ウィンドウが開きます。ここのSliceをクリック→下のSliceをクリックする。
最後にApplyをクリックすると…勝手に画像を分割してくれました!
ちなみに上記画像の背景であるチェック柄は透明を意味しています。
多分透明でない部分のみを切り取るようになっているんでしょうね。すごい!
するとProjectウィンドウの対象画像の横に矢印が表示されます。
これをクリックすると切り取ったそれぞれの画像が表示されます。
本題:アニメーションを作成!
さぁ本題です。この切り取った画像の中からアニメーション化したい画像を時系列順に選んでいきます。
そして選んだ画像をクリックし、Sceneにドラッグ&ドロップしてみましょう。
するとアニメーションの保存先を聞かれるため、エクスプローラーが開きました。
任意の保存先を選んで保存しましょう。
Scene画面に完成したアニメーションが表示されていると思います。
そしてここからは以前第4歩でご紹介した通りPrefab化→LevelManagerで表示するということを行います。
これで指定の位置にアニメーションが表示されるようになりました!
C# Generic,Singletonってなに?
Genericsについて
Genericというのは私は初めて聞きました。
以下に公式の説明があります。
ジェネリック メソッド (C# プログラミング ガイド)
Genericは日本語でいうと「一般的」などという意味です。
ここで重要なのは何に対して一般化するかということですが、
これは【メソッドの引数】に対して一般化します。
どういうことか具体例を出してみていきましょう。
例えば2つの変数の値を交換するメソッドを作成するとしましょう。
このswap(交換)メソッドには2つ引数が必要です。
例えば整数値の交換であれば以下のように書けばよいですね。
private void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
もしも文字列の交換である場合、上記のSwapメソッドは引数の型が違うため使用できません。
Genericメソッドは型も引数に与えます。
つまり型毎に同じようなメソッドを書かなくてもよいようにしてくれているのです。便利ですね。
Genericメソッド的にswapメソッドを記述するには以下のようにすればよいです。
private void Swap<T>(ref T a, ref T b)
{
T temp;
temp = a;
a = b;
b = temp;
}
「T」が肝です。
呼び出し元でこのTの部分に型を指定してあげればいいんです。
例えばint型でSwapを呼び出したい場合は以下のようにします。
int a = 1;
int b = 2;
Swap<int>(ref a, ref b);
余談:refって何?
引数にrefって書くと呼び出し先で、引数に対し値が変更された場合、呼び出し元でも値が変更されます。
Singletonとは?
singletonを日本語にすると「1枚札の」らしいです。
1枚札という日本語がよく分からないので「どーゆーこと?」ってなりました。
Genericの説明の後なので、なんとなく分かるかもしれませんが、SingletonはGenericの応用版?みたいなイメージですかね。
Generic→メソッドの一般化でしたので
Singleton→クラスの一般化です。(多分…)
Genericを使うとメソッドを一回しか記述しなくてもよくなりました。
それに対しSingletonはクラスを一回しか呼び出さないでいいようにできるということみたいです。
なのでSingleton(1枚札)と呼ぶのか上記でなんとなく理解できたでしょうか。
具体的にどう実装すればよいか見ていきましょう。
まずSingletonの抽象クラスを作成します。
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance
{
get
{
if(instance == null)
{
instance = FindObjectOfType<T>();
}
return instance;
}
}
}
さきほど出てきた「T」で一般化されていますね。
そしてinstanceという変数とInstanceというプロパティが記述されています。
instance変数がnullの場合、instanceに値を詰めるようにして、instanceを返却しています。
これだけではちょっと何がしたいか分かりにくいと思いますが、とりあえず先にいってみましょう。そうすれば何となく分かってくると思います。
まず、このSingletonをLevelManagerが継承するようにします。
// 変更前
public class LevelManager : MonoBehaviour
// 変更後
public class LevelManager : Singleton<LevelManager>
そしてTileScriptでLevelManagerを呼び出してあげればいいです。
LevelManager.Instance.Tiles.Add(gridPos, this);
LevelManagerがSingletonを継承したので、TileScriptでLevelManager.InstanceとするとSingletonのInstanceプロパティが呼び出されます。
そして、もし実体化していなかった場合LevelManagerを実体化します。
つまり他のクラスでは、いちいちLevelManagerを実体化する記述をしなくてもよくなるんです。
どうでしょうか、なんとなくイメージ沸いたでしょうか。
なんだそれだけかよって思うかもしれないのですが、内容が複雑になっていけばいくほど、こういったコードをシンプルにすることが重要になってきます。
余談:whereってなに?
Singletonの継承のところにwhere T : MonoBehaviourとあります。
これはTの型に対し、MonoBehaviour型でないとダメだよっていう制限をつける、という意味だそうです。