UGUI世界坐标转换为UI本地坐标(游戏Hud的实现)

https://blog.csdn.net/qq_34937637/article/details/90375697

 

实现世界坐标的原理是: 世界坐标和UGUI的坐标分属两个坐标系,他们之间是无法进行转换的,需要通过屏幕坐标系来进行转换(因为屏幕坐标是固定的),即先将游戏场景中的世界坐标通过游戏场景Camera转化为屏幕坐标(Camera.main.WorldToScreenPoint(point)),再通过UICamera将该屏幕坐标转换为UI本地坐标(RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, screenPoint, uiCamera, out localPoint))

疑问?
那么初学的小白们(博主也是小白)可能会疑惑UGUI为什么会有UICamera,因为UGUI的Canvas的RenderMode有三种模式,一般默认为Overlay(全覆盖),另一种为Camera。

    当RenderMode为Overlay时,UI坐标系和屏幕坐标系是一样的,则不需要通过UICamera来转换,直接将第一步得到的屏幕坐标赋值给Hud的localPosition就可以了。
    一般游戏中要实现3D物体在在UI之上时,就不能用画布全覆盖模式,而是要再创建一个Camera来单独渲染UI,Clear Flags为Depth Only。当RenderMode为Camera时,则需要以上两步来得到本地坐标。

注意:最后赋值给Hud的本地坐标是localPosition而不是position

拓展:世界坐标、本地坐标、视口坐标,各种坐标系要理解清楚,在学习shader时也是有用的

以下是实现hud跟随3D物体的脚本,只是测试用,不是开发中的代码,脚本挂在任意游戏物体上 demo下载
---------------------
作者:WalkerChen(种菜的码农)
来源:CSDN
原文:https://blog.csdn.net/qq_34937637/article/details/90375697
 

版权声明:本文为博主原创文章,转载请附上博文链接!

using UnityEngine;

public class SceneFollowUI : MonoBehaviour
{
    public RectTransform hud;            //Hud
    public RectTransform canvas;//UI的父节点
    public Transform parent;    //跟随的3D物体
    public Camera uiCamera;     //UICamera 

    Vector3 offset;      //hud偏移量
    Vector3 cachePoint;
    float originalDistance;
    float factor = 1;
    bool visiable = true;

    void Start()
    {
        offset = hud.localPosition - WorldPointToUILocalPoint(parent.position);
        cachePoint = parent.position;
        originalDistance = GetCameraHudRootDistance();
        UpdateVisible();
    }

    void LateUpdate()
    {
        if (cachePoint != parent.position)
        {
            float curDistance = GetCameraHudRootDistance();
            factor = originalDistance / curDistance;
            UpdatePosition(); //更新Hud位置
            UpdateScale();    //更新Hud的大小
            UpdateVisible();  //更新Hud是否可见,根据需求设置:factor或者根据和相机距离设置,一定范围内可见,相机视野范围内可见 等等
        }
    }


    private void UpdateVisible()
    {
        
    }

    private void UpdatePosition()
    {
        hud.localPosition = WorldPointToUILocalPoint(parent.position) + offset * factor;
        cachePoint = parent.position;
    }

    private void UpdateScale()
    {
        hud.localScale = Vector3.one * factor;
    }

    private float GetCameraHudRootDistance()
    {
        return Vector3.Distance(Camera.main.transform.position, parent.position);
    }

    private Vector3 WorldPointToUILocalPoint(Vector3 point)
    {
        Vector3 screenPoint = Camera.main.WorldToScreenPoint(point);
        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, screenPoint, uiCamera, out localPoint);
        return localPoint;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值