【unity实战】Unity实现2D人物双击疾跑

简介: 【unity实战】Unity实现2D人物双击疾跑

最终效果

前言

我们要实现的功能是双击疾跑,当玩家快速地按下同一个移动键两次时能进入跑步状态


我假设快速按下的定义为0.2秒内,按下同一按键两次


简单的分析一下需求,实现它的关键在于获得按键按下的时间,我们需要知道第一次按下按键的时间,然后判断规定时间内有没有按下按键


有两种实现方法

第一种

启动一个计时器,判断在计时器结束之前有没有再次按下这个键

第二种

是分别记录下两次按键的时间,然后用第二次按下的时间减去第一次按下的时间,判断是否小于0.2

这里我采用第二种方法,为了获取按下的时间,我们需要使用到Unity给我们提供的Time类,里面的Time.time会提供游戏启动到现在运行了多少秒,这个需求还需要我们检测到按键是否被按下,我打算使用Input Manager来实现

public static float GetAxis (string axisName);
public static float GetAxisRaw(string axisName);

GetAxisRaw会在检测到按键后,马上返回1或-1,松开按键后马上变成0

而GetAxis会在检测到按键的时候,从0过渡到1或-1,松开按键后再过渡到0


为了方便,我使用GetAxisRaw来获得输入的时间,当按键按下时意味着GetAxisRaw的返回值为1的绝对值,我们在符合条件的时候使用Time.time来获得当前的时间即可


但显然,我们不希望玩家按下a后马上按下d,还能让人物进入到疾跑状态,所以两个按键的输入时间要分开存储,还有一个需要注意的地方是,当玩家开始走路或疾跑时,a键或d键是按住不放的,所以当玩家在移动的时候,我们要使个bool变量为真,当这个变量为真时,就不再刷新输入的时间


我们设想一下,玩家进入游戏以后,马上按下了一次移动键,如果他电脑开游戏开的特别的快,他第一次按下移动键的时间,离打开游戏不到0.2秒,如果我们存储按键时间的变量,没有初始化,那么会默认赋值为0,当他第一次按下移动时,就会进入到疾跑状态,这很明显是我们不想要看到的bug


所以最后一个要点是给存储按键时间的变量进行初始化,但初始化的只要赋值为多少也是一个值得考虑的问题,如果赋值为一个极大的正数,就算赋值为1万,万一玩家一开始在挂机刚好在10,000.01秒,按一下移动按键,还是会错误地进入到疾跑状态,所以可以给他赋值为,负的最大等待输入时间,如果实在不放心,可以赋值为2倍,这样第一次输入就不会出现bug


经过了这么多的分析,相信你此时此刻已经完全明白了,接下来我们进入到代码实战环节

开始

配置动画,walk为true进入走路动画,run为true进入跑步动画

新增人物控制脚本

public class PlayerController : MonoBehaviour
{
    private Rigidbody2D rb;  // 刚体组件
    private Animator animator;  // 动画控制器
    public float maxAwaitTime;  // 最大等待时间
    private float leftPressTime, rightPressTime;  // 左键按下时间,右键按下时间
    private bool moving, canRun;  // 是否在移动,是否可以奔跑
    public int walkSpeed, runSpeed;  // 步行速度,奔跑速度
    private int currentSpeed;  // 当前速度
    private float h;  // 水平输入

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();  // 获取刚体组件
        animator = GetComponent<Animator>();  // 获取动画控制器
        leftPressTime = rightPressTime = -maxAwaitTime;  // 初始化左右按下时间
    }

    private void Update()
    {
        h = Input.GetAxisRaw("Horizontal");  // 获取水平输入
        ChangeFaceDirection();  // 更改角色朝向
        CheckRun();  // 检查奔跑状态
    }

    private void ChangeFaceDirection()
    {
        if (h == 1)
        {
            transform.localScale = new Vector3(1, 1, 1);  // 面向右侧
        }
        else if (h == -1)
        {
            transform.localScale = new Vector3(-1, 1, 1);  // 面向左侧
        }
    }

    private void CheckRun()
    {
        if (h == 1 && !moving)
        {
            if (Time.time - rightPressTime <= maxAwaitTime)
            {
                canRun = true;
            }
            rightPressTime = Time.time;
        }
        
        if (h == -1 && !moving)
        {
            if (Time.time - leftPressTime <= maxAwaitTime)
            {
                canRun = true;
            }
            leftPressTime = Time.time;
        }

    // 取 h 的绝对值
        if (Mathf.Abs(h) == 1)
        {
            moving = true;
            if (canRun)
            {
                currentSpeed = runSpeed;
                animator.SetBool("run", true);  // 设置奔跑动画
            }
            else
            {
                currentSpeed = walkSpeed;
                animator.SetBool("walk", true);  // 设置行走动画
            }
        }
        else
        {
            animator.SetBool("run", false);  // 关闭奔跑动画
            animator.SetBool("walk", false);  // 关闭行走动画
            moving = false;
            canRun = false;
        }
    }

    private void FixedUpdate()
    {
        rb.velocity = new Vector2(h * currentSpeed * Time.deltaTime, rb.velocity.y);  // 更新刚体速度
    }
}

效果

参考

如果觉得本文实现的效果不错的话,非常推荐大家去支持一下原作者

【视频】https://www.bilibili.com/video/BV1YN4113771/

目录
相关文章
|
6月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
331 6
|
6月前
|
开发者 图形学 Java
揭秘Unity物理引擎核心技术:从刚体动力学到关节连接,全方位教你如何在虚拟世界中重现真实物理现象——含实战代码示例与详细解析
【8月更文挑战第31天】Unity物理引擎对于游戏开发至关重要,它能够模拟真实的物理效果,如刚体运动、碰撞检测及关节连接等。通过Rigidbody和Collider组件,开发者可以轻松实现物体间的互动与碰撞。本文通过具体代码示例介绍了如何使用Unity物理引擎实现物体运动、施加力、使用关节连接以及模拟弹簧效果等功能,帮助开发者提升游戏的真实感与沉浸感。
219 1
|
5月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
522 0
|
6月前
|
开发者 图形学 API
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
223 0
|
6月前
|
开发者 图形学 C#
揭秘游戏沉浸感的秘密武器:深度解析Unity中的音频设计技巧,从背景音乐到动态音效,全面提升你的游戏氛围艺术——附实战代码示例与应用场景指导
【8月更文挑战第31天】音频设计在游戏开发中至关重要,不仅能增强沉浸感,还能传递信息,构建氛围。Unity作为跨平台游戏引擎,提供了丰富的音频处理功能,助力开发者轻松实现复杂音效。本文将探讨如何利用Unity的音频设计提升游戏氛围,并通过具体示例代码展示实现过程。例如,在恐怖游戏中,阴森的背景音乐和突然的脚步声能增加紧张感;在休闲游戏中,轻快的旋律则让玩家感到愉悦。
203 0
|
8月前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
248 2
|
8月前
|
人工智能 定位技术 图形学
【unity实战】制作敌人的AI,使用有限状态机、继承和抽象类多态 定义不同状态的敌人行为
【unity实战】制作敌人的AI,使用有限状态机、继承和抽象类多态 定义不同状态的敌人行为
236 1
|
8月前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
121 0
|
8月前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
129 0
|
8月前
|
存储 JSON 图形学
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
237 0