Unity相机、坐标和射线

相机

Camera 至少有一个相机,也可以有多个

ClearFlags 清除标识

  • Skyblock 天空盒
  • SolidColor 背景色,常用在2D开发
  • DepthOnly 相机深度,深度越大,越先被渲染
  • DontClear 不清除 颜色 和 缓存,每帧渲染的结果都会叠加在下一帧之上,一般与自定义的Shader配合使用

Projection:

  • Perspective 透视相机,3D;远小近大,有距离之分,可以用于3D游戏开发与FiledofView 可用于 简单的狙击枪镜头,倍镜的扩大 缩小 等
  • Orthraphic 正交相机,2D;没有远小近大,没有距离之分,通过Size搭配,调节相机的视口大小

Clipping Planes

  • 裁剪平面 摄像机渲染的范围,Near为最近的点,Far为最远的点

Viewport Rect

  • 视图矩形 用四个数值开控制摄像机的视图在屏幕中的位置和大小,使用屏幕坐标系,数值在0~1之间
  • X 水平位置的起点 Y 垂直位置的起点 W 宽度 H 高度

Target Texture

  • 目标纹理 包含相机视图输出

Occusion Culling

  • 遮挡剔除
  • HDR优化 高动态光照渲染,高动态范围渲染让场景变得更为真实,光照的变化不会显得太突兀
  • MSAA 优化 抗锯齿
  • AllowDynamicResolution 允许动态分辨率渲染

坐标

World Space(世界坐标)

Cube : transform.position

Screen Space (屏幕坐标)

以像素来定义,以屏幕的左下角(0,0),右上角为(Screen.width, Screen.height)

z 的位置 以相机的世界单位来进行衡量的

Viewport Space(视口坐标)

  • 视口坐标是标准的,相对于相机的
  • 以Game视图的左下方角(0, 0),右上角为(1, 1),z 的位置 以相机的世界单位来进行衡量的

OnGUI坐标系

  • 与屏幕坐标比较相似,但是Y轴是相反的

四种坐标系转换

世界坐标系和本地坐标系的相互转换函数如下。

  • Transform.TransformPoint(Vector3 position):将一个坐标点从本地坐标系转换到世界坐
  • Transform.InverseTransformPoint(Vector3 position):将一个坐标点从世界坐标系转换到本地坐标系
  • Transform.TransformDirection(Vector3 direction):将一个方向从本地坐标系转换到世界坐标系
  • Transform.InverseTransformDirection(Vector3 direction):将一个方向从世界坐标系转换到本地坐标系
  • Transform.TransformVector(Vector3 vector):将一个向量从本地坐标系转换到世界坐标系
  • Transform.InverseTransformVector(Vector3 vector):将一个向量从世界坐标系转换到本地坐标系

屏幕坐标系与世界坐标系的相互转换函数如下。

  • Camera.ScreenToWorldPoint(Vector3 position):将屏幕坐标系转换为世界坐标系。
  • Camera.WorldToScreenPoint(Vector3position):将世界坐标系转换为屏幕坐标系。

屏幕坐标系与视口坐标系的相互转换函数如下

  • Camera.ScreenToViewportPoint(Vector3 position):将屏幕坐标系转换为视口坐标系。
  • Camera.ViewportToScreenPoint(Vector3 position):将视口坐标系转换为屏幕坐标系。

世界坐标系与视口坐标系的相互转换函数如下

  • Camera.WorldToViewportPoint(Vector3 position):将世界坐标系转换为视口坐标系
  • Camera.ViewportToWorldPoint(Vector3 position):将视口坐标系转换为世界坐标系

Ray 射线

在三维世界中从一个点沿着一个方向,发射的一条无限长的线

如果射线在投射的过程中,遇到了带有碰撞器的模型,停止投射

Ray ray = new Ray(); 射线的构建

Physics.Raycast(); 进行射线的投射

案例1

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RayTest : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                print(hit.transform.name);
                print("投射到物体上");
            }
            else
            {
                print("没有投射到物体上");
            }
        }
    }
}

案例2 点击地面实现人物的移动

using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    public LayerMask layer;
    private bool _isDown;
    private RaycastHit _hit;

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out _hit, 9999, 1<<layer))
            {
                _isDown = true;
            }
        }

        if (_isDown)
        {
            transform.LookAt(_hit.point);
            if (Vector3.Distance(_hit.point, transform.position) > .1f)
            {
                transform.Translate(Vector3.forward * Time.deltaTime * 5);
            }
        }
    }
}

线渲染器 LineRender

using UnityEngine;

public class LineManager : MonoBehaviour
{
    private GameObject _linePrefab;

    private void Awake()
    {
        _linePrefab = Resources.Load<GameObject>("Line");
    }

    private GameObject _mLine;
    private bool _isDown;
    private CreateLine _lp;
    private Color _color = Color.white;
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            _mLine = Instantiate(_linePrefab);
            _isDown = true;
            _lp = _mLine.GetComponent<CreateLine>();
            _lp.SetColor(_color);
        }

        if (Input.GetMouseButtonUp(0))
        {
            _isDown = false;
        }

        if (_isDown)
        {
            _lp.AddPosToPoints(Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 5)));
            _lp.Draw();
        }
    }

    private void OnGUI()
    {
        if (GUILayout.Button("黄色"))
        {
            _color = Color.yellow;
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CreateLine : MonoBehaviour
{
    public List<Vector3> points = new List<Vector3>();

    private LineRenderer _line;

    private void Awake()
    {
        _line = GetComponent<LineRenderer>();
    }

    public void AddPosToPoints(Vector3 pos)
    {
        points.Add(pos);
    }

    public void Draw()
    {
        _line.positionCount = points.Count;
        for (int i = 0; i < points.Count; i++)
        {
            _line.SetPosition(i, points[i]);
        }
    }

    public void SetColor(Color color)
    {
        _line.startColor = color;
        _line.endColor = color;
    }
}
上一篇
下一篇