【unity】ファミコン風アニメーションと移動の実装
ドット絵の表示は取り込みは分かったので上下左右の移動とアニメーションを実装します。
移動はまぁ簡単にできたのですが、アニメーションがまぁ厄介でして、かなり調べましたが未だに正解はわかってません。
①本に則ったやり方
本はシンプルにするため、script上で直接アニメーションを指定するものでした。
これはこれでいいのですが、キー入力がないときに動きを止めたいのと、今後より複雑なアニメーションを設定することを考えると勉強も兼ねて他の方法を調べることにしました。
②サイトのやり方
コチラのサイトを参考にしました。
https://qiita.com/_tybt/items/bc9c3be75c04ab547c35
アニメーターコンポーネントやらアニメーションステートを用いるやり方です。
かなり理想の動きに近いのですが、キー入力からアニメが切り替わるまでラグがあって、所謂ファミコン風ではないのでまた模索することに。
③手詰まり
ここからは色々調べてもこれといった方法は見つかりませんでした。
トップビュー2Dゲームの作り方が載ってあるとの情報からコチラの本を買ってみたりしましたが
たのしい2Dゲームの作り方 Unityではじめるゲーム開発入門 https://www.amazon.co.jp/dp/4798164119/ref=cm_sw_r_other_apa_glt_i_3Z39827RP9FR2EZCT0SD
結局これも直接アニメーションを指定するもので得られるものはありませんでした。
④手作り
最早調べてもそれらしい方法は見つからないので自作してみることにしました。
どうやら待機モーションを4方向つけるのは難しいっぽい?のでそれはまぁ後回しとして、4方向の移動モーションとついでに4方向の構えモーション、そして4方向の攻撃モーションをつけることにしました。
アニメーションステート上でx,yに対応したブレンドツリーを3つ作成し、fireボタンを一回押したら構えに、構え中にfireで攻撃モーションに移行するようにしました。
攻撃モーションへの遷移はトリガーにしてhas exit timeを1とし、戻りは何も設定しないことでアニメが終わったら戻るようにしています。
以下スクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MotionAnimeController : MonoBehaviour
{
Animator animator;
Rigidbody2D rbody;
private Vector2 axisRaw; //移動用
private Vector2 nowDir; //アニメ用
bool kamae;
private float time; //連打防止用
public float speed = 2f;
public float kamaeSpeed = 1f;
// Start is called before the first frame update
void Start()
{
rbody = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
time = 0.5f;
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime; //時間を数える
//キー入力が0以外の時アニメ用変数に代入
axisRaw.x = Input.GetAxisRaw("Horizontal");
if(axisRaw.x != 0)
{
nowDir.x = axisRaw.x;
nowDir.y = 0; //x軸入力がある時はy軸を0に
}
axisRaw.y = Input.GetAxisRaw("Vertical");
if (axisRaw.y != 0)
{
nowDir.y = axisRaw.y;
nowDir.x = 0;
}
//1秒後にかまえ
if(Input.GetButton("Fire1"))
{
Invoke("Kamae", 1);
}
//0.5秒経ってたら攻撃可能
if (time >= 0.5f)
{
if (Input.GetButton("Fire1") && kamae == true)
{
Fire();
time = 0f;
}
}
//かまえ中にjumpでキャンセル
if (Input.GetButton("Jump") && kamae == true)
{
kamae = false;
}
//攻撃時以外キー入力がないときはアニメストップ
if(axisRaw == Vector2.zero && !(time <= 0.6f))
{
this.animator.speed = 0f;
}
else
{
this.animator.speed = 1.0f;
}
animator.SetFloat("x", nowDir.x);
animator.SetFloat("y", nowDir.y);
animator.SetBool("kamae", kamae);
}
void FixedUpdate()
{
//攻撃時はストップ、かまえ時と移動時でスピード変化
if(time >= 0f && time <= 0.5f)
{
rbody.velocity = axisRaw.normalized * speed * 0;
}
else if (kamae == true)
{
rbody.velocity = axisRaw.normalized * kamaeSpeed;
}
else
{
rbody.velocity = axisRaw.normalized * speed;
}
}
public void Kamae()
{
kamae = true;
}
public void Fire()
{
animator.SetTrigger("fire");
}
}
axisRawとnowDirで移動用とアニメーション用で変数を分けているのは、axisRawだけでやろうとしたらキー入力がない時に右向きに固定されてしまったからです。
x方向の入力があるときはnowDir.yを0に、y方向があるときはnowDir.xを0にすることで、キー入力がない時の向きも正しくなりました。
time変数はfireキーを一回押しただけで2回攻撃してしまうので、連打防止用に0.5秒経つまでは振れないよう作りました。
ついでに攻撃モーション中は移動を制限したくなったので0.5秒間は止まるようにしています。
初めてちゃんと自分でプログラミングしてみた訳ですが、思い通り動いてくれた喜びはひとしおですね。初心者なのでやってる人から見ると冗長だったり面倒なことをしてるのかもしれないのですが、とりあえず望んだ動きができて満足です。
そして待機モーション代わりにキー入力がないときはアニメを止めてみましたが、これ移動時用のbool値を用意して待機時のブレンドツリーを作れば多分理想の動きもできますね?とりあえずこれはテストなのでやりませんが。
むしろ今のやり方だと攻撃以外の要素を追加する度にアニメの調整をしないといけないから手間です。
今回初めてのプログラミングをやってみる過程で度々思ったのが「こういう機能があればできるな」という憶測が立つのですが、その調べ方がわからないですね…。とりあえず現状は適当にググってそれっぽいメソッドやらを使ってるのですが、果たしてこれは正攻法なのか…。公式のリファレンスとやらを見てもイマイチ分からんし、便利な関数一覧とかあるのでしょうか。
とりあえず上記の新たに買った本に則ってカメラ追従やら当たり判定やらマップ作成やらをしてしまったので、このままトップビューアクションを試作していこうと思います。
この記事が気に入ったらサポートをしてみませんか?