ゾンビとUnity

ゾンビネタとUnityでのゲーム制作について綴るブログです。

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Unity 指定フレームの指定距離内でオブジェクトを加速、減速させる

よくあるのがGUIパーツなんかの移動アニメーション。

1. 画面が切り替わったらアイテムパネルを画面の右端から左端に向かって10フレームで400ピクセル水平移動させる。
2. その後、10フレームで40ピクセルを水平移動させるが、徐々に減速して止める。必ず40ピクセル以内で止めること。

こんな処理をデザイナーがFlashを使ったりして作ってくれるのではなく、プログラムやスクリプトのコードでやらなきゃいけない場合、1.は簡単だが、問題なのは 2. 。
大昔にプランナーから似たような仕様書をもらったことがある。
手動で位置を計算して、1フレーム目はこの位置、2フレームはこの位置…とやって行くのは面倒なだけで簡単だけど

「10フレームって書いたけど、やっぱり8フレームにするわー、めんごめんご」

というのは当たり前にありすぎて想定しておかない方が悪いくらいの良くあること。
実際に動く画面を見て、感覚的に細かい調整をするのがゲームなので、何でも決めうちすると後で自分が損をすることになってしまう。
そうなると、指定したフレーム数で、指定した距離を減速させる処理が必要になる。
フレーム数、距離はいつでも変えられるように作らないといけない。

サイン波の0~90度のグラフを見ると、徐々に減速する速度に見える。
こちらのページに分かりやすいグラフがあります。

http://our-house.jp/ACbook/index.htm

使えそうだ。
逆に加速させる場合は90~180度を使えばいい。
ただ、0~90度は0から1に向かって変化するが、90~180度は0から1に向けて変化するので、取得できる値を 1 - sin(r) にする。

using System;

public class MoveAnime {
private const float _RADIAN = 3.1415f / 180;
public static float[] GetBrake(uint frame, float distance) {
float a = 90.0f / frame;
float[] p = new float[frame];
for (uint i = 0; i < frame; i++) p[i] = Math.Sin (i * a * MoveAnime._RADIAN) * distance;
return p;
}
public static float[] GetAccel(uint frame, float distance) {
float a = 90.0f / frame;
float[] p = new float[frame];
for (uint i = 0; i < frame; i++) p[i] = (1 - Math.Sin ((i * a + 90) * MoveAnime._RADIAN)) * distance;
return p;
}
}

このコードは Unity のライブラリを使ってないので、.Net 環境さえあれば何にでも組み込める。

Unity での動作チェックは、移動させたいオブジェクトにスクリプト(とりあえずNewBehaviourScript)を追加して

using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour {

private int _index = 0;
private float[] _pos;
private Vector3 _base_pos;

// Use this for initialization
void Start () {
// _pos = MoveAnime.GetAccel(60, 10f); //加速
_pos = MoveAnime.GetBrake(60, 10f); //減速
_base_pos = transform.position;
}

// Update is called once per frame
void Update () {
if (_index < _pos.Length) {
transform.position = (new Vector3(0, _pos[_index++], 0)) + _base_pos;
}
}
}

こんな風にやればOK

C#コンパイラだけ使って標準出力に GetBrake(), GetAccel() の戻り値を出力するだけで良いなら

using System;
class test {
static void Main() {
float[] p = MoveAnime.GetBrake(60, 10f);
for (int i = 0; i < p.Length; i++) Console.WriteLine("[{0}]={1}", i, p[i]);
}
}
とかやればいい

※追記
名前を思い出せなかったため、記事に書くことができなかったが、ついさっきやっと思い出すことができた。
この処理はイージング(Easing)と呼ばれている。
イージングと言っても色んな処理の仕方があり、.Net 4.5 には複数のイージング関数が用意されている。

MSDN - イージング関数
http://msdn.microsoft.com/ja-jp/library/ee308751(v=vs.110).aspx

ただし、Unity の C# は独自にチューニングされたものなので、.これらのイージング関数に対応しているかは不明。

関連記事


 
スポンサーサイト

- 0 Comments

Add your comment

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。