今回はRenderTexturerを使用しつつ、クリックした位置にRayを飛ばし移動させるアプローチについて色々と見てみます。
低解像度なRenderTextureでゲームを描画する
ゲーム画面を低解像度に設定する為にRenderTextureを使うのは良いアイディアの一つです。このアプローチを使えばUIは高解像度のままハイクォリティで描画不可の高いシェーダーやポストエフェクトを割りと安く使用できます。
個人的な考えで言えば、モバイルのような小さな画面で軽いシェーダーをFHD(1920×1080)で描画するより、リッチなシェーダーをHD(1280×720+MSAA)で描画するほうがハイクォリティと見られるんじゃないかって気がしてます。*1
ただ、画面全体を低解像度化するとUIが低解像度になります。低解像度なUIはエッジ部分が目立ってしまうので余りやりたくない事の一つです。特に文字が目立ちます。
ので、描画負荷の上がりやすいゲーム画面は少し低解像度で、エッジの見えやすいUIは高解像度で描画するアプローチを使います。
Camera.main.ScreenPointToRayがおかしくなる
さて、このアプローチを行った場合Camera.Main.ScreenPointToRayの値がおかしな値を返して来ます。
例えば下のようなコードです。640x480の画面に対して320x240のRenderTextureを使用して描画していると、クリックの位置に向かうはずが、違う位置で動いてしまっています。
var ray = Camera.main.ScreenPointToRay ( Input.mousePosition);
if (Physics.Raycast (ray, out hit)) {
agent.SetDestination (hit.point);
}
理由はシンプルで、Input.MousePositionはフル解像度の位置を示していますがRenderTextureで画面は縮小されているので、位置がズレています。
Input.MousePositionの位置を補正してやる
思いつく解決方法は二つ。Input.MousePositionの位置を補正してやるか、ViewPort座標を使用するかです。
今回は手っ取り早い解決法でViewport座標を使用してみます。
Input.MousePositionで取得した位置をScreenのサイズで割り、位置を0~1の値に正規化します。後は、正規化したInput.MousePositionの座標を使用してViewportPointToRayでRayを生成、Raycastに与えます。
下のコードでは、cursorに動かしたいオブジェクト、rtCameraにRenderTextureをセットしたカメラを指定すると、低解像度化したRenderTextureを使用してもマウスの位置までCursorを動かしてくれます。