【Unity】Transform座標をRectTransform座標に変換する方法


キャラクターの手前にHPゲージを表示したかったのだが、キャラクターがTransform、HPゲージは円ゲージを採用していたのでRectTransform。つまりワールド座標をスクリーン座標に変換してImageを表示する必要があった。

方法

テラシュールブログさんでやりかたが載っていたのでありがたく参考にさせていただいた。
ソールファイルはキャンバスオブジェクトにつける。

test.cpp

    [SerializeField] private Image bossHp = default;        // ボスHP画像
    [SerializeField] private Vector2 bossHpPos = default;   // ボスHP座標調整

    private RectTransform bossHpRectTrans;
    private RectTransform canvasRectTrans;

    private void Awake()
    {
        bossHpRectTrans = bossHp.GetComponent<RectTransform>();
        canvasRectTrans = GetComponent<RectTransform>();
    }

    /// <summary>
    /// ボスのHP座標を設定する
    /// </summary>
    /// <param name="target">ボス座標</param>
    public void SetBossHpPotision(Vector3 target)
    {
        var newPos = Vector2.zero;
        var camera = Camera.main;

        var screenPos = RectTransformUtility.WorldToScreenPoint(camera, target);
        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTrans, screenPos, camera, out newPos);
        bossHpRectTrans.localPosition = newPos + bossHpPos;
    }

解説としては
1つ目のRectTransformUtility.WorldToScreenPointでTransform(ワールド)座標をスクリーン座標に変換する。
2つ目のRectTransformUtility.ScreenPointToLocalPointInRectangleでスクリーン座標をRectTransform座標に変換する。

おそらく2つ目のほうはカメラ、キャンバスが複数あった場合、どのカメラに映っているキャンバス用RectTransformに変換するか?ということだと思う。キャンバスごとにカメラで映る解像度が変更できるし、Overlay設定とかもあるからそれのためなのかな?よくわからん…

今回もそうなんだけどSpineキャラクターは足元とかが中心座標になってたりするのでHP画像を表示する際には位置調整用に変数も追加。実行中に座標調整ができるという点に関してUnityは本当に便利。

まぁ、とりあえずこれでやりたいことはできたので一安心。

ワールド座標とスクリーン座標の違いすらよく分かってなかったし、いつもマウスの座標取得すら手当たり次第に関数ぶつけて確認してるくらいの未熟者だったから今回のはマジでよくわからなかった。調査&実装で3時間。+備忘録作成に1時間もかかってしまった…これがなかなか難しいねんな。