第1回目はスクラッチブロックの「動き」偏です。
〇歩動かす
スクラッチではキャラクターを動かすのに、座標を使用します。
Unityでも座標を使って動かすこともできるのですが、もう一つ物理エンジンというものを使って、物体に直接速度を与えて動かすことが出来ます。
1、Transform(座標情報)を使ったオブジェクトの移動方法
スクラッチの場合、座標はx座標とy座標で構成されています。
一方、Unityではx座標、y座標の他に、z座標という奥行きを表す軸があります。 座標は Transformコンポーネント の Positionプロパティ が管理しています。
右方向に進む場合 右方向は transform.right と表記します。 移動には transform の positionプロパティを直接書き換える方法と、transform.positionプロパティを変化させるメソッド:Translate()メソッド を使用する方法があります。
transform.positon += transform.right;
//または
transform.Translate(transform.right);
左方向に進む場合 transformプロパティには right という値はありますが、left はありません。左方向は -transform.right と表記します。
transform.positon += -transform.right;
//または
transform.Translate(-transform.right);
上方向に進む場合 キャラクターの上下方向は transformプロパティの up という値を使用します。
transform.positon += ransform.up;
//または
transform.Translate(transform.up);
下方向に進む場合
transform.positon += -ransform.up;
//または
transform.Translate(-transform.up);
スクラッチは上下左右の2Dの構造ですが、Unityでは3Dの構造を持つことが出来ます。キャラクターを前後に移動させることが出来、その時の transformプロパティは Forward という値を使用します。
前方向に進む場合
transform.positon += ransform.forward;
//または
transform.Translate(transform.forward);
後ろ方向に進む場合
transform.positon += -ransform.forward;
//または
transform.Translate(-transform.forward);
2、Rigidbody(物理エンジン) を使ったオブジェクトの移動方法
物理エンジンを使うと、オブジェクトに速度を与えて移動させることが出来ます。transformを使った移動は座標情報の置き換え、いわゆる連続した瞬間移動であるのに対し、rigidbodyを使った移動は現実世界に近い物理移動になります。
Rigidbody コンポーネントを使用するためには、オブジェクトにRigidbodyを追加する必要があります。
AddComponent でRigidbodyコンポーネントを追加します。検証の為、追加されたRigidbodyコンポーネントの UseGravity のチェックを外し、重力を無効化にします。
Rigidbodyコンポーネントを使用するには、Rigidbody型の変数を作り、Start関数で初期値を取得すると良いでしょう。下の記述を行います。
Rigidbody rb; //Rigidbodyを使用するため、変数の宣言
void Start()
{
rb = GetComponent<Rigidbody>(); //Rigidbodyに初期値を代入
}
方向の指示は、transformコンポーネントを使用した移動と同じです。またプロパティ値を置き換える方法も、transformコンポーネント同様直接変更する方法と、AddForceメソッドを使って置き換える方法があります。ただし、AddForceを使った場合、力が加わり続けますので、第二引数(ForceMode)などで適切な値を指定する必要があります。
右方向に進む場合
rb.velocity = transform.right;
//または
rb.AddForce(transform.right);
左方向に進む場合
rb.velocity = -transform.right;
//または
rb.AddForce(-transform.right);
上方向に進む場合
rb.velocity = transform.up;
//または
rb.AddForce(transform.up);
下方向に進む場合
rb.velocity = -transform.up;
//または
rb.AddForce(-transform.up);
前方向に進む場合
rb.velocity = transform.forward;
//または
rb.AddForce(transform.forward);
後ろ方向に進む場合
rb.velocity = -transform.forward;
//または
rb.AddForce(-transform.forward);
〇度まわす
Unityで向きを管理しているのはtransformコンポーネント の Rotation プロパティです。
このプロパティの値を変更する場合も、移動同様 transformコンポーネントを直接操作する方法と、Rigidbodyコンポーネントを使って値を操作する方法があります。
1、Transform(座標情報)を使ったオブジェクトの回転 Unityの場合、3軸のうちどの軸を回転させるかを指定する必要があります。スクラッチ同様2次元でとらえた場合、オブジェクトを時計回りに回すにはZ軸を中心に回転させます。
回転も移動と同様、transformコンポーネントの rotationプロパティを直接変化させる方法と、transform.rotationプロパティを変化させるメソッド:Rotate()メソッド を使用する方法があります。
Untiyでは角度をQuaternionという4軸で管理しています。プロパティを直接変化するには4軸を3軸に置き換える Quaternion.Euler() を使用します。一方、Rotate()メソッドの場合はVector3で指定することが出来ます。
右回りに回転
transform.rotation *= Quaternion.Euler(0, 0, -1);
//または
transform.Rotate(0,0,-1);
Unityは角度の正負がスクラッチの逆になるので注意が必要です。
左回りに回転
transform.rotation *= Quaternion.Euler(0, 0, 1);
//または
transform.Rotate(0,0,1);
同様に、y軸、z軸、またはそれぞれを組み合わせた回転をするときは、3軸の値をそれぞれ変化させます。
2、Rigidbody(物理エンジン) を使ったオブジェクトの回転方法
他のオブジェクトの影響を受けるような回転をさせる場合、Rigidbodyコンポーネントを使用した回転を使用します。Rigidbodyコンポーネントの回転を管理するプロパティは angularVelocity です。移動を管理するvelocityプロパティ同様、この angularVelocity を直接変更する方法と、AddTorqueメソッドを使用して変更する方法があります。
右回りに回転
rb.angularVelocity = new Vector3(0, 0, -1);
//または
rb.AddTorque(0, 0, -1);
左回りに回転
rb.angularVelocity = new Vector3(0, 0, 1);
//または
rb.AddTorque(0, 0, 1);
「どこかの場所」へ行く
このブロックは初期状態で「どこかの場所」が指定されています。この場合、スクラッチでは押すたびにランダムな場所が再設定されます。Unityでは Randam.range() を使って、3軸に乱数を指定します。
transform.position = new Vector3(Random.Range(-10.0f, 10.0f),
Random.Range(-10.0f, 10.0f),
Random.Range(-10.0f, 10.0f));
「マウスポインター」へ行く
マウスをクリックしたときに取得される座標は「スクリーン座標」、一方オブジェクトが持つ座標は「ワールド座標」です。 Cameraクラスが持つScreenToWorldPoint メソッドを使ってスクリーン座標をワールド座標に変換しオブジェクトの座標を指定します。
Vector3 mousePos;
mousePos = Input.mousePosition; //マウスの座標を取得
mousePos.z = 10f; //Z座標調整
//スクリーン座標をワールド座標に変換
transform.position = Camera.main.ScreenToWorldPoint(mousePos);
「他のオブジェクト」へ行く
ターゲットを指定する方法は様々です。サンプルでは事前に GameObject.Find メソッド でオブジェクトの名前を指定して探し出し、変数:target に代入しています。
GameObject target = GameObject.Find("TargetName");
transform.position = target.transform.position;
x座標を 0、y座標を 0 にする
transformコンポーネントのpositionプロパティにVector3の値を指定します。Vector3のカッコ内の引数は順に、x,y,z の座標の値です。
transform.position = new Vector3(0, 0, 0);
〇秒でどこかの場所に行く
Unityで時間を管理するには、Coroutine(コルーチン)や DeltaTime(デルタタイム)を使うと良いでしょう。今回の事例では特定のキーを押したとき、またはマウスをクリックしたときにそれぞれの処理を発動したいと思います。
まずスタート位置、ゴール位置を変数宣言します。 コルーチンのメソッドの中では、引数で受け取った秒数でゴール位置に移動するコードを作っています。
今回はスペースキーを押したときに3秒かけてx、y、zそれぞれ -10 から 10 の間のランダムな座標に移動する内容にしました。
Vector3 startPos; //初めの場所
Vector3 endPos; //向かう場所
IEnumerator GotoTargetR(float t) //引数:t秒で指定した場所へ移動する関数
{
float duration = t; //移動にかける時間(引数:t)
float currentTime = 0; //経過時間を初期化
startPos = transform.position; //移動開始位置
//endPosを乱数で取得(対象が他Objectの場合、下の※を置換)
※endPos = new Vector3(Random.Range(-10.0f, 10.0f),
Random.Range(-10.0f, 10.0f),
Random.Range(-10.0f, 10.0f));
//指定した時間を越えない間、以下の処理を繰り返す
while (currentTime < duration)
{
currentTime += Time.deltaTime; // 経過時間を更新
float p = currentTime / duration; //経過時間の割合を算出
transform.position = Vector3.Lerp(startPos, endPos, p); //座標更新
yield return null; //1フレームスキップ
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) //スペースキーが押されたら
{
//引数 3(秒)を入れて移動のコルーチン発動
StartCoroutine(GotoTargetR(3));
}
}
どこかの場所が指定するオブジェクトの場合、endPos に該当のオブジェクトのtransfomPositon を指定します。
//シーン上のオブジェクトからターゲットの名前で検索、その座標を endPos に指定
※endPos = GameObject.Find("TargetName").transform.position;
〇秒で「マウスポインター」へ行く
マウスをクリックしたときに取得される座標は「スクリーン座標」、一方オブジェクトが持つ座標は「ワールド座標」です。マウスを左クリックをしたタイミングで、クリックしたスクリーン座標を Cameraクラスが持つScreenToWorldPoint メソッドを使ってワールド座標に変換し、ゴールの座標を指定します。引数には同じように3秒を指定したので、3秒かけてクリックした座標に移動します。
Vector3 startPos; //初めの場所
Vector3 endPos; //向かう場所
IEnumerator GotoTargetM(float t) //引数:t秒でクリックした座標に移動する関数
{
float duration = t; //移動にかける時間
float currentTime = 0; //経過時間を初期化
startPos = transform.position; //移動開始位置
//指定した時間を越えない間、以下の処理を繰り返す
while (currentTime < duration)
{
currentTime += Time.deltaTime; // 経過時間を更新
float p = currentTime / duration; //経過時間の割合を算出
transform.position = Vector3.Lerp(startPos, endPos, p); //座標更新
yield return null; //1フレームスキップ
}
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Vector3 mousePos;
mousePos = Input.mousePosition; //マウスの座標を取得
mousePos.z = 10f; //Z座標調整
//スクリーン座標をワールド座標に変換
endPos = Camera.main.ScreenToWorldPoint(mousePos);
//引数 3(秒)を入れて移動のコルーチン発動
StartCoroutine(GotoTargetM(3));
}
}
〇秒でx座標を0、y座標を0に変える
Unityで時間を管理するには、Coroutine(コルーチン)や DeltaTime(デルタタイム)を使うと良いでしょう。今回の事例では特定のキーを押したときに指定した座標に移動する処理を作ります。
「〇秒でどこかの場所に行く」の内容とほぼ同じです。ターゲットとなる場所をVector3の座標で指定しました。
Vector3 startPos; //初めの場所
Vector3 endPos; //向かう場所
IEnumerator GotoTargetR(float t) //引数:t秒で指定した場所へ移動する関数
{
float duration = t; //移動にかける時間(引数:t)
float currentTime = 0; //経過時間を初期化
vector3 startPos = transform.position; //移動開始位置
vector3 endPos = new Vector3(5,-5,5); //向かう場所を指定
//指定した時間を越えない間、以下の処理を繰り返す
while (currentTime < duration)
{
currentTime += Time.deltaTime; // 経過時間を更新
float p = currentTime / duration; //経過時間の割合を算出
transform.position = Vector3.Lerp(startPos, endPos, p); //座標更新
yield return null; //1フレームスキップ
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) //スペースキーが押されたら
{
//引数 3(秒)を入れて移動のコルーチン発動
StartCoroutine(GotoTargetR(3));
}
}
90度に向ける
スクラッチ同様2Dの視点でとらえた場合、オブジェクトを90度に向ける(初期状態の角度)にはZ軸の値を変更します。
transform.rotation = Quaternion.Euler(0, 0, 90);
但し、スクラッチはオブジェクトの向きが初期状態で90度であるのに対し、Unityではすべての軸が0度となります。
マウスのポインターに向ける
この動きは作品が2Dなのか3Dなのかでプログラムを分ける必要があります。3Dの場合 transform.LookAtメソッド を使って対象のオブジェクトをターゲットに向けることが出来ます。この時オブジェクト自体の正面がターゲットを向くので3軸にそれぞれ向きが与えられます。これを2Dで使って場合、画像が傾いてしまい元の形が崩れてしまいます。
3Dの場合
Vector3 mousePos = Input.mousePosition; //マウスの座標を取得
mousePos.z = 10f; //Z座標調整
//スクリーン座標をワールド座標に変換
Vector3 targetPos = Camera.main.ScreenToWorldPoint(mousePos);
transform.LookAt(targetPos);
2Dの場合
Vector3 mousePos = Input.mousePosition; //マウスの座標を取得
mousePos.z = 10f; //Z座標調整
//スクリーン座標をワールド座標に変換し、自分の座標からの向きを取得
Vector3 dir = Camera.main.ScreenToWorldPoint(mousePos) -
transform.position;
// ベクトルの方向を回転角度に変換
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
// オブジェクトを指定した角度に回転
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
他のオブジェクトへ向ける
3Dの場合
Vector3 targetPos = GameObject.Find("TargetName").transform.position;
transform.LookAt(targetPos);
2Dの場合
Vector3 targetPos = GameObject.Find("TargetName").transform.position;
Vector3 dir = targetPos - transform.position;
// ベクトルの方向を回転角度に変換します
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
// オブジェクトを指定した角度に回転させます
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
X座標を10ずつ変える
座標情報は、transformコンポーネントの Position プロパティが管理しています。10ずつ変える場合は、加算演算子を使って次のように記述します。
ただし、スクラッチと移動量や画面内の座標の範囲が大きく違っていますので、指定する値には注意が必要です。
transform.position += new Vector3(10, 0, 0);
X座標を〇 にする
transformコンポーネントの Position プロパティを指定した値にするのですが、スクラッチと違って Positionプロパティに1つの軸の値だけ入れることが出きません。x以外の値は元の値を保持させたいので、次のように y 及び z の値には現在の値を指定します。
transform.position = new Vector3(10, transform.position.y,
transform.position.z);
Y座標を10ずつ変える
座標情報は、transformコンポーネントの Position プロパティが管理しています。10ずつ変える場合は、加算演算子を使って次のように記述します。
ただし、スクラッチと移動量や画面内の座標の範囲が大きく違っていますので、指定する値には注意が必要です。
transform.position += new Vector3(0, 10, 0);
y座標を〇 にする
transformコンポーネントの Position プロパティを指定した値にするのですが、スクラッチと違って Positionプロパティに1つの軸の値だけ入れることが出きません。y以外の値は元の値を保持させたいので、次のように x 及び z の値には現在の値を指定します。
transform.position = new Vector3(transform.position.x, 10,
transform.position.z);
もし端に着いたら跳ね返る
Unityでオブジェクト同士の当たり判定を行うには、Colliderというコンポーネントが必要になります。前提条件としてステージ上に下のような2つのオブジェクトを配置します。
Sphere(球体)はRigidbodyコンポーネントを使って移動します。Use Gravity(重力)のチェックを外しておきます。また Sphere Collider コンポーネントが付いているのを確認しておきます。
Wall(壁)はSphereが衝突する対象です。跳ね返りの条件として「Wall」という名前を使用します。Box Collider コンポーネントが付いていることを確認しておきます。
Rigidbody rb; //Rigidbody 型の変数
Vector3 force = new Vector3(-10, 1, 1); //Sphereの移動方向(ベクトル)
void Start()
{
rb= GetComponent<Rigidbody>(); //変数に初期値を代入
}
void Update()
{
rb.velocity = force; //常にforceの力で物理移動
}
void OnCollisionEnter(Collision collision) //当たり判定
{
//当たった相手の名前が「Wall」なら
if (collision.gameObject.name == "Wall")
{
force *= -1; //移動方向 に -1 をかけ、正反対にする
}
}
回転方法を左右のみにする
RigidbodyコンポーネントのConstrains、Freeze Rotationプロパティ、回転を止めたい軸にチェックを入れるとその軸が固定されます。
回転方法を左右のみにしたい場合は、y軸のみ回転を有効にすればいいので、xとzにチェックを入れます。
これをスクリプトファイルから指定すると以下のようになります。
回転方法を「左右のみ」にする
Rigidbody rb = GetComponent<Rigidbody>()
rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
回転方法を「自由に回転」にする
Rigidbody rb = GetComponent<Rigidbody>()
rb.freezeRotation = false;
回転方法を「回転しない」にする
Rigidbody rb = GetComponent<Rigidbody>()
rb.freezeRotation = true;
X座標
x座標は transform コンポーネントの Postion プロパティが管理しています。
transform.positon.x
使用例
もしx座標が 0 より大きいなら、x座用を 0 にする
( y座標とz座標も0 にする )
if (transform.position.x > 0)
{
transform.position = new Vector3(0, 0, 0);
}
Y座標
y座標は transform コンポーネントの Postion プロパティが管理しています。
transform.positon.y
使用例
もしy座標が 0 より大きいなら、y座用を 0 にする
( x座標とz座標も0 にする )
if (transform.position.y > 0)
{
transform.position = new Vector3(0, 0, 0);
}
向き
向きは transform コンポーネントの Rotation プロパティが管理しています。
但しUnityでは、Quaternion(クォータにオン)という4軸で角度を見ているため、3軸で角度を測るときは注意が必要です。
Quaternionの場合
transform.rotate
Vector3の場合
transform.rotation.eulerAngles
使用例
もしy座標が 0 より大きいなら、y座用を 0 にする
( x座標とz座標も0 にする )
Vector3 currentRotation = transform.rotation.eulerAngles; //角度を変数化
if (currentRotation.z > 0f) //z軸の角度が0度より大きい場合
{
currentRotation.z = 0f; //z軸の角度を0
transform.rotation = Quaternion.Euler(currentRotation);//角度を更新
}
ファイブボックスでは、スクラッチはもう卒業、という方向けにUnityの個別指導のオンラインレッスンを行っています。
ご興味のある方は当サイト、オンラインレッスンから、無料体験授業へお問い合わせ下さい。
Comments