C# には「既存の型にメソッドを追加できる」**拡張メソッド(Extension Methods)**という仕組みがあります。
Unity の Vector3 など、自分では編集できない構造体にもメソッドを“生やせる”ため、コードの表現力を大きく高めてくれます。
この記事では、
拡張メソッドの基本
Vector3 に対して 任意の関数を成分ごとに適用する 拡張メソッドの作成
応用例(sin 波と掛け算処理による動的オフセット生成
を順番に解説します。
拡張メソッドは、static クラスに書かれた static メソッドで、
第一引数に this 型名 を付けることで、実際にはその型のメソッドのように呼び出せるものです。
例えば:
public static class StringExtensions
{
public static bool IsEmpty(this string str)
{
return string.IsNullOrEmpty(str);
}
}
// 使用例
bool b = "".IsEmpty();
"" は string のインスタンスですが、拡張メソッドを定義することで、 あたかも自分のメソッドのように IsEmpty() を呼び出せるようになります。
Unity の Vector3 は数値 3 つからなる構造体です。
これに対して 各成分へ任意の関数を適用したい 場面は多くあります。
sin, cos を各成分へ適用したい
他の Vector3 と「要素ごとの演算」をしたい
カスタムの変換処理を作りたい
そこで、以下の 2 種類の拡張メソッドを用意します。
public static class Vector3Extensions
{
/// <summary>
/// Vector3 の各要素に単項関数 (float → float) を適用します。
/// </summary>
public static Vector3 Apply(this Vector3 vector, Func<float, float> func)
{
return new Vector3(
func(vector.x),
func(vector.y),
func(vector.z)
);
}
Mathf.Sin, Mathf.Abs, x => x * x など、 「float を受け取り float を返す」関数を 3 つの成分へ一括で適用できます。
/// <summary>
/// 2 つの Vector3 の各要素に二項関数 (float, float → float) を適用します。
/// </summary>
public static Vector3 Apply(this Vector3 vector, Func<float, float, float> func, Vector3 other)
{
return new Vector3(
func(vector.x, other.x),
func(vector.y, other.y),
func(vector.z, other.z)
);
}
}
(a, b) => a * b を渡せば要素ごとの掛け算、 (a, b) => a + b を渡せば要素ごとの加算になります。
実際の使い方として、 「sin 波を生成し、それを元のベクトルに掛ける」という例を見てみましょう。
まずは分かりやすく、段階を分けて書いてみます。
// 周波数 f、時間 time
Vector3 baseAngleDeg = f * 360f * time;
// 位相オフセットを追加
Vector3 phaseDeg = baseAngleDeg + new Vector3(px, py, pz);
// ラジアンへ変換
Vector3 phaseRad = phaseDeg * Mathf.Deg2Rad;
// sin を成分ごとに適用
Vector3 wave = phaseRad.Apply(Mathf.Sin);
// 元のベクトル a と要素ごとの掛け算
Vector3 offset = a.Apply(
(value, w) => value * w,
wave
);
Apply(Mathf.Sin) により、Mathf.Sin を 3 成分すべてに一括適用できる
Apply((a, b) ⇒ a * b, wave) により、
a.x * wave.x, a.y * wave.y, a.z * wave.z がまとめて書ける
「関数を渡すだけで計算内容を差し替えられる」ため柔軟性が高い
上記は理解しやすさのために分けていましたが、
慣れると次のように一行で書くこともできます。
Vector3 offset =
a.Apply(
(v, w) => v * w,
((f * 360f * time + new Vector3(px, py, pz)) * Mathf.Deg2Rad)
.Apply(Mathf.Sin)
);
処理の流れとしてはまったく同じです。
拡張メソッドを使うと、既存の型に「自分だけのメソッド」を追加できる
Vector3.Apply を作ることで、
単項関数(Sin など)
二項関数(加算・乗算など)
を成分ごとに柔軟に適用できる
コードが圧倒的に読みやすく、変更へ強くなる
特に Unity では、ベクトル計算が頻繁に登場します。
Apply のようなユーティリティを持っておくと、 数学的な処理を 関数合成のように直感的に書ける ようになるため非常に便利です。