前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity2D游戏开发-坐标系与辅助线绘制

Unity2D游戏开发-坐标系与辅助线绘制

作者头像
码客说
发布2023-08-08 13:00:46
6940
发布2023-08-08 13:00:46
举报
文章被收录于专栏:码客

坐标系

概要

世界坐标

transform.position 游戏中获取的就是世界坐标。

局部/本地坐标

transform.localPosition

本地坐标系的特点是:

  • 原点位于游戏对象的position属性指定的位置。
  • 使用游戏对象自身的transform组件定义的Orientation(方向)。
  • 本地坐标系是相对于父对象坐标系的,如果没有父对象,则相对于世界坐标系。
  • 当对象位置或旋转时,本地坐标系也会跟着改变。
  • 对象的scale属性也会缩放本地坐标系。

本地坐标系经常用于:

  • 指定对象相对自身的偏移量,如使用LocalPosition。
  • 作为对象内部组件的相对坐标系,如相机、碰撞体等组件。
  • 用作计算对象本身的运算坐标系。
  • 表示对象空间下的点、矢量等。

总之,Unity中的本地坐标系是相对游戏对象自身的坐标系统,用于表示对象内部的相对关系,是一个非常重要的概念

屏幕坐标系

屏幕坐标就是相对于游戏的屏幕来说的,最大和游戏分辨率相等。

获取鼠标的位置是屏幕坐标

image-20230803003708334
image-20230803003708334

视口坐标系

视口坐标系和屏幕坐标系完全对等,不过范围是0-1。

image-20230803003553714
image-20230803003553714

GUI坐标系

和屏幕坐标系最大值一样,只不过y轴的方向相反,是从上到下。

image-20230803003408399
image-20230803003408399

别名

  • 世界坐标(全局坐标、左手坐标、绝对坐标)
  • 本地坐标(局部坐标、自身坐标、物体坐标、相对坐标)
  • 屏幕坐标(像素坐标)
  • 视口坐标(视窗坐标)
  • GUI坐标(UI坐标)

示例代码

代码语言:javascript
复制
private void OnGUI()
{
    Camera mainCamera = Camera.main;
    GUI.contentColor = Color.black;
    GUI.skin.label.fontSize = 20;
    GUI.Label
    (
        new Rect
        (
            10,
            10,
            400,
            30
        ),
        "世界坐标:" + transform.position
    );

    GUI.Label
    (
        new Rect
        (
            10,
            40,
            400,
            30
        ),
        "局部/本地坐标:" + transform.localPosition
    );

    GUI.Label
    (
        new Rect
        (
            10,
            70,
            400,
            30
        ),
        "屏幕宽高:" + Screen.width + "x" + Screen.height
    );

    GUI.Label
    (
        new Rect
        (
            10,
            100,
            400,
            30
        ),
        "屏幕坐标-鼠标位置:" + Input.mousePosition
    );

    GUI.Label
    (
        new Rect
        (
            10,
            130,
            400,
            30
        ),
        "视口坐标-鼠标位置:" + mainCamera.ScreenToViewportPoint(Input.mousePosition)
    );
}

坐标转换

屏幕坐标和视口坐标

Input.mousePosition鼠标的位置是屏幕坐标

屏幕坐标=>视口坐标

代码语言:javascript
复制
mainCamera.ScreenToViewportPoint(Input.mousePosition)

视口坐标=>屏幕坐标

代码语言:javascript
复制
Vector3 screenPoint = mainCamera.ViewportToScreenPoint
(
    new Vector3
    (
        0.5,
        0.5,
        0
    )
);

屏幕坐标和世界坐标

世界坐标=>屏幕坐标

代码语言:javascript
复制
Vector3 wPos = mCamera.WorldToScreenPoint(pPos);

屏幕坐标=>世界坐标

直接调用相机的屏幕转世界是不行的,因为我们获取到的屏幕坐标是没有z值的,所以计算的都是错的。

对于2D可以采用下面的方法,因为z是不变的。

代码语言:javascript
复制
/// <summary>
/// 屏幕转世界
/// </summary>
/// <param name="sPos">世界坐标</param>
/// <param name="mCamera">相机</param>
/// <param name="pPos">世界坐标下任意对象的位置,主要获取z值</param>
/// <returns></returns>
private Vector3 ScreenToWord
(
    Vector3 sPos,
    Camera mCamera,
    Vector3 pPos
)
{
    //因为屏幕坐标没有z值,所以我们线获取世界转屏幕时的z值
    Vector3 wsPos = mCamera.WorldToScreenPoint(pPos);
    sPos.z = wsPos.z;
    //设置z值后就能使用屏幕转世界了。
    return mCamera.ScreenToWorldPoint(sPos);
}

GUI/Gizmos/Handles绘制及对比

GUI绘制

GUI绘制使用的是GUI坐标。

示例

代码语言:javascript
复制
private void OnGUI()
{
    Camera mainCamera = Camera.main;
    GUI.contentColor = Color.black;
    GUI.skin.label.fontSize = 20;
    GUI.Label
    (
        new Rect
        (
            10,
            10,
            400,
            30
        ),
        "世界坐标:" + transform.position
    );
}

Gizmos绘制

OnDrawGizmosSelected和OnDrawGizmos使用其一即可。

  • OnDrawGizmosSelected 元素选中时才显示
  • OnDrawGizmos 都显示

但是无论哪种方式都要在开始调试后,让右上角的Gizmos处于激活状态才能显示。

并且只能放在这两个方法内,不能在OnGUI中。

代码语言:javascript
复制
private void OnDrawGizmosSelected()
{
}

private void OnDrawGizmos()
{
    Gizmos.color = Color.red;
    //绘制线
    Gizmos.DrawLine(transform.position, transform.position + Vector3.right);
    //绘制框
    Gizmos.DrawWireCube
    (
        transform.position,
        new Vector3
        (
            2,
            2,
            2
        )
    );
}

Handles绘制

Handles使用的世界坐标,但是注意绘制图形的时候需要设置相机,绘制Label的时候不需要设置相机。

绘制Label

比如在我们的人物上显示名称

代码语言:javascript
复制
private void OnGUI()
{
    Handles.Label(transform.position, "小明");
}

绘制圆

代码语言:javascript
复制
private void OnGUI()
{
    Camera mainCamera = Camera.main;
    Handles.color = Color.red;
    Handles.SetCamera(mainCamera);
    Handles.RadiusHandle
    (
        Quaternion.identity,
        transform.position,
        2
    );
}

绘制线

代码语言:javascript
复制
private void OnGUI()
{
    Camera mainCamera = Camera.main;
    Handles.color = Color.red;
    Handles.SetCamera(mainCamera);
    Handles.lighting = true;
    Vector3 startPoint = transform.position;
    Vector3 endPoint = startPoint + transform.right * 2;

    Handles.DrawLine
    (
        startPoint,
        endPoint
    );
}

使用场景

GUI、Gizmos 和 Handles 在 Unity 中的主要使用场景如下:

GUI - 用于在游戏界面中创建UI元素,如按钮、文本等。适用于显示游戏信息,提供交互。

使用GUI坐标系。 示例:

代码语言:javascript
复制
void OnGUI() { 
 GUI.Button(new Rect(100,100,200,50), "Start Game");
}

Gizmos - 用于在场景编辑器中可视化辅助信息,如球体、线条等。

使用世界坐标系。 示例:

代码语言:javascript
复制
void OnDrawGizmos() {
  Gizmos.DrawWireSphere(transform.position, 10);
}

Handles - 用于在场景编辑器中可视化交互编辑信息,如移动、旋转控制器。

使用世界坐标系。 示例:

代码语言:javascript
复制
void OnSceneGUI() {
  Handles.DoPositionHandle(transform.position, transform.rotation);
}

总结:

  • GUI用于游戏运行时界面
  • Gizmos用于场景编辑的可视化信息
  • Handles用于场景编辑的交互控制

明确三者的适用场景,可以更好地在Unity中使用它们实现各自的功能。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 坐标系
    • 概要
      • 别名
        • 示例代码
        • 坐标转换
          • 屏幕坐标和视口坐标
            • 屏幕坐标和世界坐标
            • GUI/Gizmos/Handles绘制及对比
              • GUI绘制
                • Gizmos绘制
                  • Handles绘制
                    • 使用场景
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档