Unity引擎2D游戏开发,摄像机跟随及攻击抖动实现

发布时间 2023-12-30 23:27:00作者: 心霖の雨

安装摄像机插件

打开Package Manager,输入Cinemachine进行搜索安装
image

导入摄像机

在Hierarchy窗口中,添加2D Camera
image

image
会发现Game窗口没有任何东西,因为该摄像机并没有进行跟随、观看等相关的设置
image

将Player拖进FollowLook At,并将Lens Ortho Size设置为6
image

此时Game窗口聚焦到了Player身上
image

设置摄像机

Body中,能够看到有非常多的摄像机设置
image

Tracked Object Off X:能够调整摄像机中心点的偏移值
image

Lookahead Time:根据目标的运动方向调整摄像机的位移,数值越高,位移强度越高
Lookahead Smoothing:位移缓冲值,数值越高,缓冲强度越高

X、Y、Z Damping:摄像机跟随某坐标轴的阻尼强度,数值越高,阻尼强度越高,跟随速度越慢

Screen X、Y:摄像机物理偏移量

Dead Zone Width、Height、Depth:死区大小,人物在死区内移动,并不会带动摄像机移动,除非走出死区

Soft Zone Width、Height:软区大小,当人物位于软区时,人物移动后,摄像机会逐渐跟随对准中心,形成一种拖拽感
Bias X、Y:软区位置偏移量

解决摄像机画幅超出地图范围的问题

有一个Add Extension选项,它能够添加摄像机的额外插件
image

添加Cinemachine Pixel Perfect插件,它能够在像素旋转、畸变等情况时,不会产生像素扭曲,会一直保持单位像素原有的形态
image

再添加Cinemachine Confiner 2D,它能够限定摄像机的移动范围。其中的Bounding Shape 2D变量,可以通过新建一个作用于整个游戏场景的Collider 2D,来限制摄像机的移动范围
image

新建Empty Object,添加Polygon Collider 2D。将Collider勾选上Is Trigger,否则会将场景中的对象发生碰撞
image

将此Collider调整到合适的大小
image

将Collider拖入Bounding Shape 2D,即可实现该功能
image

除此之外,可以通过移除多余的点,来让Colider形成一个矩形,能够更方便的调整区域的大小
image

切换场景时,获取当前场景的摄像机边界

思路:
让Virtual Camera获取Cinemachine Confiner 2D组件,在当切换场景时,去找被标记为Bounds的这个物件,将Collider赋予给Bounding Shape 2D变量

为Bounds添加一个Tag,命名为Bounds
image

Scripts下,创建C#文件,命名为CameraControl
image

将其挂载到Virtual Camera
image

创建CinemachineConfiner2D的全局变量,并初始化

private CinemachineConfiner2D confiner2D;

private void Awake()
{
    confiner2D = GetComponent<CinemachineConfiner2D>();
}

编写GetNewCameraBounds()方法,在内部获取Tag为Bounds的GameObject,将其中的Collider2D赋予给CinemachineConfiner2D

private void GetNewCameraBounds()
{
    var obj = GameObject.FindGameObjectWithTag("Bounds");
    if (null == obj)
    {
        return;
    }
    confiner2D.m_BoundingShape2D = obj.GetComponent<Collider2D>();
}

回到Cinemachine Confiner 2D中,能够看到下方有一个按钮Invalidate Cache,它能够在场景切换后,对场景边界清除缓存,防止上一次的场景影响当前更换后的场景
image

因此,在该方法最后添加一行代码来清除缓存

private void GetNewCameraBounds()
{
    var obj = GameObject.FindGameObjectWithTag("Bounds");
    if (null == obj)
    {
        return;
    }
    confiner2D.m_BoundingShape2D = obj.GetComponent<Collider2D>();
    // 清除边界缓存
    confiner2D.InvalidateCache();
}

暂时在Start()方法中进行调用

// TODO:场景切换后更改
private void Start()
{
    GetNewCameraBounds();
}

摄像机震动

添加Cinemachine Impulse Listener,监听发生的脉冲
image
该组件将可以响应CinemachineImpulseSource脉冲来源发出的任何脉冲信号

勾选Use 2D Distance,由于Unity默认的是3D场景,那么该组件的脉冲方向也是3D的,但当前项目是2D,因此勾选上此设置
image

创建新的GameObject,命名为Camera Shake。并添加Cinemachine Impulse Source组件
image
Impulse Shape能够选择不同的震动方式,DefaultVelocity能够处理不同坐标轴的震动力度大小

CameraControl脚本内,创建CinemachineImpulseSource的全局变量

public CinemachineImpulseSource impulseSource;

Virtual Camera拖入到此变量内
image

现在无论当玩家还是敌人受伤,都去执行GenerateImpulse()脉冲执行的方法。那么就利用事件监听的方法去调用此方法

创建新的ScriptableObjectC#脚本,命名为VoidEventSO
image

由于不需要传递任何的参数,因此写上基础的Event代码

[CreateAssetMenu(menuName = "Event/VoidEventSO")]
public class VoidEventSO : ScriptableObject
{
    public UnityAction OnEventRaised;

    public void RaiseEvent()
    {
        OnEventRaised?.Invoke();
    }
}

Event文件夹下,创建刚才创建的Scriptable Object,命名为CameraShakeEvent
image

在Player的Character中,在On Take Damage内拖入上述的Scriptable Object,选择RaiseEvent()方法
image

CameraControl中,添加VoidEventSO的全局变量

public VoidEventSO cameraShakeEvent;

添加OnEnable()OnDisable()OnCameraShakeEvent()方法来注册摄像机震动的事件

private void OnEnable()
{
    cameraShakeEvent.OnEventRaised += OnCameraShakeEvent;
}

private void OnDisable()
{
    cameraShakeEvent.OnEventRaised -= OnCameraShakeEvent;
}

private void OnCameraShakeEvent()
{
    impulseSource.GenerateImpulse();
}