第四章 摄像机与场景

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只是为了便于参考,下一张将会有更好的地形制作方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值