OK,之前的章节我们实现了玩家通过虚拟摇杆移动,但是玩家会很容易超出屏幕,我们想要的结果应该是玩家始终在画面中心。那么我们就需要设置摄像机。
当然,直接把摄像机绑定为玩家的子对象就能解决,但是一旦移动到地图边缘就会出现问题( 当然,无限地图无需考虑这个)。
首先,把摄像机的Size调整到一个适宜的程度,差不多是9,然后背景颜色调整为白色。
接下来新建脚本CameraController作为摄像机的控制脚本。
补充知识:
Update
-
作用:每帧调用一次,用于处理与帧率相关的逻辑,比如处理玩家的实时输入、控制游戏对象的常规移动、更新动画状态等。由于其调用频率与帧率相关,所以不同性能的设备上调用间隔可能不同。
-
案例:根据玩家的键盘输入来控制角色的移动。
using UnityEngine; public class PlayerMovement : MonoBehaviour { public float speed = 5f; void Update() { float horizontalInput = Input.GetAxis("Horizontal"); float verticalInput = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(horizontalInput, 0f, verticalInput) * speed * Time.deltaTime; transform.Translate(movement); } }
FixedUpdate
-
作用:以固定的时间间隔调用,默认是 0.02 秒(可在
Edit
->Project Settings
->Time
中的Fixed Timestep
进行修改)。它主要用于处理与物理模拟相关的操作,如对刚体施加力、进行碰撞检测等,因为固定的时间间隔能保证物理模拟的稳定性和准确性,不受帧率波动的影响。 -
案例:通过对刚体施加力来实现物体的移动。
using UnityEngine; public class RigidbodyMovement : MonoBehaviour { public float force = 10f; private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void FixedUpdate() { float horizontalInput = Input.GetAxis("Horizontal"); float verticalInput = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(horizontalInput, 0f, verticalInput) * force; rb.AddForce(movement); } }
LateUpdate
-
作用:在所有
Update
方法调用完毕后调用,每帧执行一次。常用于处理那些需要依赖于Update
中逻辑执行结果的操作,比如相机跟随角色,确保相机能在角色完成移动后再进行位置更新,避免出现相机抖动或位置不一致的问题。 -
案例:实现相机跟随玩家角色。
using UnityEngine; public class CameraFollow : MonoBehaviour { public Transform target; public Vector3 offset; void LateUpdate() { if (target != null) { transform.position = target.position + offset; } } }
OK,所以我们需要用Lateupdate写摄像机的脚本,同时修改Player Controller里面的update改为fixedupdate。
摄像机脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
[Header("组件")]
[SerializeField]private Transform target;//跟随目标
[Header("变量")]
[SerializeField] private Vector2 minMaxXY;
private void LateUpdate()
{
//空引用检测
if (target == null)
{
Debug.LogWarning("没有找到相机跟随的目标");
return;
}
//获取玩家位置和调整
Vector3 targetPosition = target.position;
targetPosition.z = -10;
//相机移动范围限制
targetPosition.x =Mathf.Clamp(targetPosition.x, -minMaxXY.x, minMaxXY.x);
targetPosition.y =Mathf.Clamp(targetPosition.y, -minMaxXY.y, minMaxXY.y);
//随时改变相机位置
transform.position = targetPosition;
}
}
拖动脚本,修改Unity中脚本字段minMax限制XY移动的最大值,先试试3。
摄像机设置完毕后, 开始搭建场景。
首先使用sprits里面的wall作为边界:
复制4个,放在适合的位置并调整长宽:
为wall们添加碰撞器Box Collider 2D。同时为角色添加circle collider 2D ,比起复杂的碰撞器,circle碰撞器能够很大程度上优化性能。
运行!但是一个问题出现了玩家的上半部分被场景所遮挡了。
解决方法就是在玩家的Order in Layer中将值高于墙面。即渲染顺序。
但是更规范的方法应该是:
layer新建一个Sortinglayer,叫做bottom,拖到最上方,意思是所有bottom层的对象将被放置在最下方。
最后,创建一个新的空物体Walls,将XYZ重置为0,wall都作为子物体。
这个walls只是为了便于参考,下一张将会有更好的地形制作方法。