正交相机(Orthographic Camera)
Unity3D中的正交相机(Orthographic Camera)是一种投影方式,它不同于透视相机(Perspective Camera)的投影方式。在正交相机中,物体在视野中的大小与其与相机的距离无关,也就是说,所有物体在相机视野中呈现的大小是相同的。
Unity3D的正交相机可以看作是一个在固定位置的照相机,它将三维空间中的物体投影到一个二维图像平面上,而不考虑物体到相机的距离。因此,在正交投影中,无论物体离相机多远,它们在二维图像平面上的大小都不会改变。
正交相机的投影方式是通过一个虚拟的长方体来取景,并将场景投影到这个长方体的前面。在Unity中,可以通过更改相机参数来调整这个长方体的尺寸,进而影响相机视野中物体的显示大小。
主要特点和应用场景
物体大小不变
由于正交相机不考虑物体到相机的距离,所以物体在相机视野中的大小是固定的,这使得在2D游戏或者UI设计中非常方便。
无透视收缩效果
在正交投影中,远处的物体和近处的物体在图像平面上的大小是相同的,不会有透视收缩效果,这使得场景中的物体之间的相对距离
保持不变。
适用于2D游戏和UI设计
正交相机由于其特殊的投影方式,非常适合用于2D游戏和UI设计,可以很容易地实现平铺纹理或者背景等效果。
易于实现像素化效果
正交相机由于物体大小固定,所以可以很容易地实现像素化效果,这在一些复古风格的2D游戏中非常常见。
总的来说,Unity3D的正交相机通过忽略物体到相机的距离,实现了一种特殊的投影方式,这种方式在2D游戏和UI设计中有广泛的应用。
正交相机的主要属性
- 投影模式(Projection Type)
这是设置相机投影方式的属性,Unity中提供了多种投影模式,但对于正交相机来说,通常只会选择“正交(Orthographic)”这一项。
选择正交投影后,相机的视野不会因物体距离的增加而产生大小变化。
- 视野大小(Field of View)
在正交投影中,视野大小实际上定义了相机的视锥体的大小,它决定了相机的可视范围。Unity中是以角度来定义的,数值越大,
视野范围越宽。
- 近平面(Near Plane)和远平面(Far Plane)
这两个属性定义了相机视锥体的近边界和远边界。在正交相机中,这两个平面是固定垂直于相机前后的,不会因为相机的移动而改变。
近平面和远平面的距离决定了相机的深度范围。
- 正交尺寸(Orthographic Size)
这个属性定义了相机的虚拟长方体视野的尺寸。相机将场景投影到一个虚拟的长方体上,这个长方体的长、宽、高分别由正交尺寸的
X、Y、Z分量决定。物体在相机视野中的大小实际上是由这个长方体的尺寸决定的。例如,如果正交尺寸的X为10,Y为5,那么相机视野
的宽高比就是2:1。
- 平移(Position)
这是相机在三维空间中的位置,可以自由设置。
- 旋转(Rotation)
这是相机在三维空间中的旋转,同样可以自由设置。旋转会影响相机的朝向,从而改变拍摄的视角。
- 缩放(Scale)
在Unity中,相机也有缩放属性,但这通常指的是相机视锥体的缩放,而不是像物体一样改变大小。这个属性在正交相机中不太常用。
实例应用
Lua实现Unity3D正交相机镜头缩放及视野范围控制。
实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
---@class AmusementParkCameraCtrl
local m = {
camera = nil,
---@type Vector3 相机最左侧视野位置
limitLeftPos = 0,
---@type Vector3 相机最右边视野位置
limitRightPos = 0,
---@type Vector3 相机最上边视野位置
limitUpPos = 0,
---@type Vector3 相机最下边视野位置
limitDownPos = 0,
---@type number 目标镜头大小
targetSize = 0,
---@type Vector3 目标位置
targetPos = Vector3.New(0,0,0),
---@type number 相机移动速度
moveSpeed = 5,
---@type number 相机放大速度
zoomSpeed = 2,
---相机最小的视野大小
minSize = 3.75,
---相机最大的视野大小
maxSize = 1.5,
}
function m.New(camera)
local obj = Clone(m)
obj:Init(camera)
return obj
end
function m:Init(camera)
self.camera = camera
self:AddListeners()
end
function m:Refresh(limitLeftPos,limitRightPos,limitUpPos,limitDownPos)
self.limitUpPos = limitUpPos
self.limitLeftPos = limitLeftPos
self.limitRightPos = limitRightPos
self.limitDownPos = limitDownPos
self.targetSize = self.minSize
self.camera.orthographicSize = self.targetSize
self.targetPos = self.camera.transform.position
end
function m:OnUpdate()
if self.camera.orthographicSize ~= self.targetSize then
if self.camera.orthographicSize > self.targetSize then
self.camera.orthographicSize = self.camera.orthographicSize - self.zoomSpeed *
UnityEngine.Time.deltaTime
else
self.camera.orthographicSize = self.camera.orthographicSize + self.zoomSpeed *
UnityEngine.Time.deltaTime
end
self.camera.orthographicSize = Mathf.Clamp(self.camera.orthographicSize,self.maxSize,self.minSize)
self.targetPos = self:CheckCameraLimitPos(self.targetPos)
end
local direction = self.targetPos - self.camera.transform.position
if direction.magnitude > 0.2 then
self.camera.transform:Translate(direction.normalized * self.moveSpeed * UnityEngine.Time.deltaTime)
else
self.camera.transform.position = self.targetPos
end
end
function m:AddListeners()
end
function m:RemoveListeners()
end
---放大/缩小镜头
---@param type number type 1 放大; 2 缩小
function m:ChangeCameraSize(type)
if type == 1 then
self.targetSize = self.maxSize
else
self.targetSize = self.minSize
end
end
---移动相机位置
---@param dx number
---@param dy number
function m:MoveCamera(dx,dy)
if self.camera == nil or LuaCodeInterface.GameObjIsDestroy(self.camera) then
return
end
local pos = self.camera.transform.position
self.targetPos = self:CheckCameraLimitPos(pos + Vector3.New(dx,dy,0))
end
---检测相机移动范围
---@param pos Vector3
function m:CheckCameraLimitPos(pos)
---边界判断
local cameraWidth = self.camera.orthographicSize * self.camera.aspect * 2
local cameraHeight = self.camera.orthographicSize * 2
local tempPos = pos:Clone()
tempPos.x = Mathf.Clamp(tempPos.x,self.limitLeftPos.x + cameraWidth / 2,
self.limitRightPos.x - cameraWidth / 2)
tempPos.y = Mathf.Clamp(tempPos.y,self.limitDownPos.y + cameraHeight / 2,
self.limitUpPos.y - cameraHeight / 2)
return tempPos
end
function m:Dispose()
AssetUtil.UnloadAsset(self)
self:RemoveListeners()
self.camera = nil
end
return m