Unity-2D游戏中的相机控制

摄像机是游戏的基础。通过对摄像机的控制,我们可以实现很多常见的的特效,如角色跟随、锁定到特殊物品、缩放、屏幕抖动等等。在2D游戏中,因为只需要处理二维坐标,摄像机的控制相对3D游戏应该会简单一点。本文介绍了2D游戏中常用的摄像机控制和特效,但它们也是很容易扩展到3D游戏的。

跟随目标角色

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
// 跟随的目标
Transform trackTarget;
// 摄像机相对于角色的偏移
public float xOffset;
public float yOffset;
protected float followSpeed;
// 方向锁定
protected bool isXLocked = false;
protected bool isYLocked = false;
void Update ()
{
float xNew = transform.position.x;
if (!isXLocked)
{
float xTarget = trackTarget.position.x + xOffset;
// 使相机可以平滑移动
xNew = Mathf.Lerp(transform.position.x, xTarget, Time.deltaTime * followSpeed);
}
float yNew = transform.position.y;
if (!isYLocked)
{
float yTarget = trackTarget.position.y + yOffset;
yNew = Mathf.Lerp(transform.position.y, yTarget, Time.deltaTime * followSpeed);
}
transform.position = new Vector3(xNew, yNew, transform.position.z);
}

锁定节点

有时我们需要让相机锁定在场景中的某个物体上面,即游戏场景中的“兴趣点”(POI)。
我们可以在场景中配置一个这样的POI对象,并在上面添加触发器碰撞体(Trigger Collider)来达到这一目的。不管什么时候,只要玩家角色进入了触发体区域,我们就把相机的焦点放在POI上。当角色离开碰撞体区域后,我们再恢复相机的正常行为。
相机追踪目标的切换通常有两种方法可以实现,一种是简单地进行切换,而另一种是使用栈系统,即将追踪模式push到栈中,再pop恢复。
这里只是简单的进行切换,相关代码:

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
[SerializeField]
Camera camera;
[SerializeField]
string tag;
private Transform previousTarget;
private TrackBehaviour trackBehaviour;
private bool isLocked = false;
void Start () {
trackBehaviour = camera.GetComponent<TrackBehaviour>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == tag && !isLocked)
{
isLocked = true;
PushTarget(collision.transform);
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == tag && isLocked)
{
isLocked = false;
PopTarget();
}
}
private void PushTarget(Transform target)
{
previousTarget = trackBehaviour.TrackTarget;
trackBehaviour.TrackTarget = target;
}
private void PopTarget()
{
trackBehaviour.TrackTarget = previousTarget;
}

相机缩放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
float zoomFactor = 1.0f;
float zoomSpeed = 5.0f;
private float originalSize = 0f;
private Camera camera;
void Start ()
{
camera = GetComponent<Camera> ();
originalSize = camera.orthographicSize;
}
void Update ()
{
float targetSize = originalSize * zoomFactor;
if (targetSize != camera.orthographicSize)
{
camera.orthographicSize = Mathf.Lerp(camera.orthographicSize, targetSize, Time.deltaTime * zoomSpeed);
}
}
void setZoomFactor(float zoomFactor)
{
this.zoomFactor = zoomFactor;
}

屏幕抖动

当游戏中遇到战斗、爆炸等场景时,屏幕抖动能够增强游戏的表现力,使玩家更能身临其境。

1
2
3
4
5
6
7
8
9
private Vector3 shakePos = Vector3.zero;
void Update () {
if (Input.GetKey (KeyCode.Space))
{
transform.localPosition -= shakePos;
shakePos = Random.insideUnitSphere / 5.0f;
transform.localPosition += shakePos;
}
}

淡入淡出

游戏关卡开始或结束时,有时会需要淡入淡出效果。要实现这种效果,我们可以添加一个不可交互的UI纹理并让其覆盖整个屏幕。最开始时将纹理设为透明,然后填入任意颜色或改为任意透明度,使用动画来达到这种效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[SerializeField]
Image overlay;
[SerializeField]
float fadeSpeed = 5f;
[SerializeField]
Color targetColor;
void Update()
{
if (overlay.color != targetColor)
{
overlay.color = Color.Lerp(overlay.color, targetColor, Time.deltaTime * fadeSpeed);
}
}
public void SetOverlayColor(Color color)
{
targetColor = color;
}