Unity3D学习FPS游戏(5)武器瞄准和准星

前言:一个FPS游戏最基本的角色控制,在前面几篇已经基本实现,接下来我们将进入到武器篇。本篇将实现武器武器瞄准和准星。

武器瞄准

思路

FPS游戏在准备开枪的时候,点击右键的时候会把武器抬起来对准中间。

带玩家模型动画的可能会通过动画来实现,像我们这种没有玩家模型的,可以通过移动武器或者摄像机来实现。

思路是这样的,这里我们参考Unity官方的是通过移动武器来实现的,武器右键瞄准就把武器的位置移动到最中间。

实现

调整Weapon对象

由于现在我们对武器的操作要变多了,需要对Weapon游戏对象进行更好的层级管理,调整为下图所示。
在这里插入图片描述

新建代码和挂载

新建一个WeaponController的C#代码,挂载到武器Weapon01的上。

代码逻辑

如前面思路所说的,武器瞄准就把武器的位置移动到最中间,平时我们拿着武器是在右手边。

代码思路上,记录武器移动的两个坐标坐标,然后在按下右键的时候移动到中间位置,松开的时候回到原位位置。
但是直接移动位置的话,表现出来的效果会非常生硬。就如我们上一篇文章讲到的跳跃那样,直接到某个位置是非常生硬的,需要一些过渡。

我们可以通过协程和线性插值实现自然的位置过渡,具体如下,关于协程和线性插值的具体的知识会在补充知识中详细解释,这里我们简单提一下。
我们只需要知道协程是一个特殊的函数,它可以主动暂停和唤醒,常用的方法有“yield return null”主动暂停一帧再执行。
线性插值Lerp(当前位置,终点位置,进度百分比)函数,通过协程循环配合,能够创造出枪快速移动,在快靠近中间的越来越缓慢的视觉效果。

代码
根据前面的逻辑编写出如下代码。

public class WeaponController : MonoBehaviour
{
    [Header("武器数值")]
    public Vector3 defaultPosition;// 默认位置
    public Vector3 centerPosition;// 中心位置
    public float positionLerpRatio = 0.5f;// 线性插值参数
    
    void Start()
    {
        // 自己在Unity中挪位置试出来的
        defaultPosition = new Vector3(0.4F, -0.6F, 1.15F);
        centerPosition = new Vector3(0F, -0.6F, 0.807F);
    }

    void Update()
    {
        ChangePosition();// 变换武器位置
    }
    private void ChangePosition()
    {
        // 按下右键
        if (Input.GetMouseButtonDown(1))
        {
            StopCoroutine("ToDefault");// 停掉另一个协程再开启下个一个
            StartCoroutine("ToCenter");
        }
        // 松开右键
        if (Input.GetMouseButtonUp(1))
        {
            StopCoroutine("ToCenter");
            StartCoroutine("ToDefault");
        }
    }
    IEnumerator ToCenter() {
        while (transform.localPosition!=centerPosition)
        {
            transform.localPosition = Vector3.Lerp(transform.localPosition, centerPosition, positionLerpRatio);// 线性插值过渡更自然
            yield return null;// 等待一帧
        }
    }
    IEnumerator ToDefault()
    {
        while (transform.localPosition != defaultPosition)
        {
            transform.localPosition = Vector3.Lerp(transform.localPosition, defaultPosition, positionLerpRatio);
            yield return null;// 等待一帧
        }
    }
}

效果

在这里插入图片描述

武器准星

FPS游戏中,屏幕中间通常会有个准星。

思路

这个准星实际上是UI界面的一部份,即在界面中间常驻一个准星UI,UI界面在Unity中可以通过Canvas来实现。

实现

新建Canvas和Image

在Scene中右键UI-Canvas新建Canvas,然后在Canvas下面右键UI-Image新建Image。

在这里插入图片描述
拖入准星UI
在这里插入图片描述
根据自己需求调整Width和Height。

切换天空盒

因为天空太白了,不方便看到准星。

菜单-Window-Rendering-Lighting,按照如下拖入素材中的天空盒子。
在这里插入图片描述

效果

在这里插入图片描述

补充知识

协程

协程是什么

在游戏客户端开发的时候,一般是不考虑多线程的,因为游戏逻辑更新和画面更新的时间点要求有确定性,尤其是网络同步的时候。用协程会比较多。

协程是一种可以主动暂停和唤醒的特殊函数,看起来像轻量级线程,但本质还是运行在主线程上,类似于Unpdate方法。

协程和线程的区别,协程串行所以同一时间只能执行一个协程,线程并发所以同时有多个线程在运行;协程是运行在线程中的;协程是程序员控制的,线程是操作系统控制的。

协程怎么用

协程挂在MonoBehaviour上的,必须要通过一个MonoBehaviour才能开启协程。即使MonoBehaviour被Disable(隐藏)也会继续执行,只有被销毁才会被销毁。

协程在Unity中形式,是以IEnumerator为返回值的函数。

开始和停止分别是StartCoroutine(协程名)和StopCoroutine(协程名)。

使用方法通常是在协程中写一些功能,并根据自己需求暂停和唤醒,常用的有如下:

IEnumerator CoroutineA(int a)
{
    Debug.Log("协程A被开启了");
    yield return null;
    Debug.Log("协程A暂停了一帧");
    yield return new WaitForSeconds(1.0f);
    Debug.Log("协程A暂停了一秒");
    yield return StartCoroutine(CoroutineB(a));
    Debug.Log("协程A暂停直到CoroutineB运行结束");
    Debug.Log("协程A运行结束");
}

协程的应用

如同我们这篇文章实现的枪从快到慢移动到中间的动画效果。

打字机效果,人物对话中的文字很多是一点点显示出来的。

加载资源,游戏开始的时候,IO资源加载很慢会卡顿游戏,可以放到协程中每次加载一点。

定时器操作,每隔一段时间调用一次。

协程和Update

我们会发现协程能做的,其实Update都可以做到,为什么还要用协程呢?用协程可以把多帧的操作封装到一个方法内部,能使得代码逻辑更加清晰。

线性插值

Lerp函数

线性插值Lerp(起始位置a,终点位置b,进度百分比t)函数。

进度百分比t是一个0到1之间的值,返回的是a + (b - a) * t。

Lerp应用

本篇中,线性插值Lerp(当前位置,终点位置,进度百分比)函数,通过协程循环配合,能够创造出枪快速移动,在快靠近中间的越来越缓慢的视觉效果。

还可以做相机尾随,摄像机先迅速的移动,后来越接近玩家越慢,形成了缓动效果,这个用在横板游戏比较常见。

还有一些淡出淡出的动画效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值