オブジェクトの移動や時間で増減する要素についての考え方

画面上でオブジェクトは、動的に動いている様に考えていましたが、プログラムを書く上では、フレームという静的な写真をパラパラと見せていると考えた方が間違いありません。つまり、秒速10mで進めと命令して移動するわけではなく、秒速10mだったら、次のフレームではこの座標にオブジェクトがある。次のフレームではこの座標、次のフレームでは……という様に、オブジェクトの座標を移動して設置し、フレームを作ってる様なイメージです。

弓から矢を射出した時の計算方法

例として、弓から矢を発射したときに、矢をどのようにして移動させるかを見てみましょう。
このスクリプトはタワーディフェンスゲーム制作時に、実際に使用しているスクリプトです。なので、これだけでは動かないのですが、重要な部分がいくつかありますので、それぞれメモを記します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Arrow : MonoBehaviour
{
    public Enemy targetEnemy;   // 弓が捉えたターゲット
    private float speed = 10;   // 矢の速度

    void Update()
    {
        if (targetEnemy == null)
        {
            // ターゲットがいない場合は矢を消去
            Destroy(gameObject);
            return;
        }

        // ターゲットへのベクトルを計算
        var v = targetEnemy.transform.position - transform.position;
        // 矢を移動させる
        transform.position += v.normalized * speed * Time.deltaTime;
        // 特定の距離に近付いたらHPを減らす
        if (v.magnitude < 0.7f)
        {
            targetEnemy.hp -= 1;
            if (targetEnemy.hp <= 0)
            {
                Destroy(targetEnemy.gameObject);
            }
            Destroy(gameObject);
        }
    }
}

どの方向に移動するのか

var v = targetEnemy.transform.position - transform.position;

まず、移動する方向を決める必要があります。そのためにはベクトルを求める必要があります。
ベクトルは簡単に言うと、向きと大きさを持つ数値です。
ベクトルの計算方法は「目標とする場所 - 現在の場所」で求める事ができます。

今回はターゲットが存在するため、ベクトルを求めて方向を決めていますが、単純に右に移動させる場合は Vector3.right と記述します。

どれだけ移動するか

transform.position += v.normalized * speed * Time.deltaTime;

ベクトルを求めたら、実際にオブジェクトの座標を移動します。
v.normalized はベクトルから方向だけを取り出す書き方と考えてください。正確には、ベクトルの正規化と呼ばれていて、ベクトルの長さを 1.0 にした物が生成されます。正規化を行わないと、距離が近いとベクトルが小さくなり、遠いとベクトルが大きくなってしまい、距離によって速度が変化してしまいます。

Time.deltaTime とありますが、とても重要なプロパティで、直前のフレームと今のフレーム間で経過した時間[秒]を返すプロパティです。こうすることで、距離を求める際に必要な時間を求める事ができます。後は小学校の算数と同じで、時間×速さ×方向で移動距離を算出して、現在の座標に足し算するだけです。

ターゲットに当たった判定

if (v.magnitude < 0.7f)

今回は矢を敵に発射するスクリプト処理なので、敵に当たった時にどうするのかも書かれています。ターゲットに当たった判定ですが、距離が 0.7 以下の場合には当たったと判定しています。つまり、実際には当たっていません。
実際に当たったと判定したい場合は、コライダーを設定する必要がありますし、衝突したコライダーが本当にターゲットなのかを判定する必要もあります。今回の場合はそこまで複雑な処理を必要としないため、このように距離で判定を行っています。

v.magnitude はベクトルの長さを数値で返してくれるプロパティです。つまり、直線距離でどれだけ離れているかがこれで分かります。