Cap_146

 

もはやお馴染みのFPSのダメージエフェクト、受けたダメージの方角を示すアレを作った。
最初は5分で作れるだろうと甘く見ていたが、Unityの罠にはまり手こずった。
というのも、Vector3.Angle()関数は負の値を返さないので単純計算には使えないのだ。
使うためには、Xが左なら-1を乗算するなどの対応が必要。

言っても難しいと思うので、実際のコードを見てみよう。

using UnityEngine;
using System.Collections;

public abstract class BaseHuman :MonoBehaviour
{
	// ダメージエフェクト用テクスチャー(面倒なのでインスペクターから設定).
	[SerializeField] protected Texture tex;

	private Vector3 attacker;// 攻撃者の座標.
	private float timer; // エフェクト表示タイマー.

	// ダメージを受ける関数.
	public void OnDamage(int damage,Vector3 sender)
	{
		// 攻撃者の座標を受け取る.
		attacker = sender;

		// タイマーをオンにする.
		timer = 4f;
	}

	void OnGUI()
	{
		// Screenの真ん中を取得.
		Vector2 center = new Vector2(Screen.width/2,Screen.height/2);
		
		// GUI領域を開始.
		GUILayout.BeginArea(new Rect(0,0,Screen.width,Screen.height));

		// タイマーが動作中は処理.
		if(timer>0)
		{
			// 色を設定.
			GUI.color = new Color(1,0,0,timer/4f);

			// 回転計算.
			Vector3 target = attacker-transform.position; // 差分座標を取得.
			target.y = 0; // 水平方向のみ判定するのでY軸は無視.
			target.Normalize(); // 正規化(必要ないかも).
			float angle = Vector3.Angle(Vector3.forward,target); // 角度を取得.
			if(target.x<0)
				angle*=-1; // 座標がマイナスの時、角度を反転.

			// テクスチャを回転.
			GUIUtility.RotateAroundPivot(angle-transform.rotation.eulerAngles.y, center);

			// ダメージエフェクトを表示.
			GUI.DrawTexture(new Rect(0,0,Screen.width,Screen.height),tex);

			// タイマーを減算.
			timer -= Time.deltaTime;
		}

		// GUI領域を終了.
		GUILayout.EndArea();
	}
}

こんな感じで、あとはテクスチャーとして半透過アーチ状の画像を用意すれば完成です。