【你问我答】Unity实现类似DNF地下城勇士的2D人物移动跳跃

news2024/11/27 2:43:40

文章目录

  • 前言
  • 人物节点创建
  • 实现简单移动
  • 实现攻击效果
  • 实现跳跃
  • 人物移动跳跃完整代码
  • 人物脚底的影子效果
  • 最终运行效果
  • 源码
  • 参考
  • 完结

前言

之前有个小伙伴微信找我,想做一个类似DNF地下城勇士的移动跳跃功能,特别是关于2d的跳跃,之前还不是很有头绪,后面去查找相关资料,还真让我找到了,今天就一起来实现一下吧!
在这里插入图片描述

实现类似2.5d的地下城勇士效果,正常来说2d 3d都可以做,但是我还是选择2d,2d操作起来更为简单,而且素材也容易寻找。

先来看看实现的最终效果吧
在这里插入图片描述

人物节点创建

Player挂载刚体和碰撞器,主要控制主角移动
Mbody为人物身体,挂载animator组件,主要控制主角动画切换
Shadow为阴影
在这里插入图片描述

实现简单移动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerParentMove : MonoBehaviour
{
    public float moveSpeed = 10;//移动速度(父物体)
    private Vector2 direction;//移动方向(父物体,xy轴平面)
    private Animator ani;//动画控制器(子物体)
    private Rigidbody2D rig;//刚体组件(父物体)
    
    void Start()
    {
        ani = GetComponentInChildren<Animator>();//初始化获得子物体的动画控制器
        rig = GetComponent<Rigidbody2D>();//初始化获得自身的刚体组件
    }

    void Update()
    {
        direction.x = Input.GetAxisRaw("Horizontal");//获取键盘x轴输入,赋值给移动方向的x值
        direction.y = Input.GetAxisRaw("Vertical")  *  0.7f;//获取键盘x轴输入,赋值给移动方向的x值(*0.7是因为视觉效果,向里走要慢一点,可根据实际效果改变)
    }


    //之所以在FixUpdate里面执行移动和跳跃方法,是因为父物体移动用的是刚体的Velocity方法,子物体跳跃虽然是用Transform,但是为了跳跃时配合移动不出现卡顿,也放在FixUpdate里面执行
    private void FixedUpdate()
    {
        Move();//移动方法(父物体)
        Anima();//执行动画控制方法
    }

    void Move()
    {
        rig.velocity = direction * moveSpeed * 50 * Time.fixedDeltaTime;//父物体沿移动方向移动
        if (rig.velocity.x >= 0.05)
        {
            transform.rotation = new Quaternion(0, 0, 0, 0);//如果速度向右不翻转
        }
        else if (rig.velocity.x <= -0.05)
        {
            transform.rotation = new Quaternion(0, 180, 0, 0); //如果速度向左翻转180°
        }
    }

    void Anima() {}
}

效果
在这里插入图片描述

实现攻击效果

public bool isAttack = false;//攻击状态

void Update()
{
	//检测键盘攻击键输入并且攻击状态为false
	if(Input.GetMouseButtonDown(0) && !isAttack)
 	{
     	isAttack = true;//攻击状态赋值为true
     	Accatk();
 	}
}

private void FixedUpdate()
{
    if (isAttack) direction = new Vector2(0, 0);
}

void Accatk() {}

效果
在这里插入图片描述

实现跳跃

public float jumpHeight = 5;//跳跃高度
public float aSpeed = -9.8f;//重力加速度
private bool isJump = false;//跳跃状态
private float velocity_Y;//跳跃速度(子物体)
public Transform childTransform;//Transform组件(子物体)
    
void Update()
{
    //检测键盘跳跃键输入并且跳跃状态为false
    if (Input.GetKeyDown(KeyCode.Space) && !isJump &&!isAttack)
    {
        isJump = true;//跳跃状态赋值为true
        ReadyJump();//执行准备跳跃方法
    }
}

//之所以在FixUpdate里面执行移动和跳跃方法,是因为父物体移动用的是刚体的Velocity方法,子物体跳跃虽然是用Transform,但是为了跳跃时配合移动不出现卡顿,也放在FixUpdate里面执行
private void FixedUpdate()
{
   Jump();//跳跃方法(子物体)
}
    
void Jump()
{
    velocity_Y += aSpeed * Time.fixedDeltaTime;//重力模拟(子物体垂直速度始终受重力加速度影响)
    //判断子物体是在下落状态(velocity小于零)并且距离父物体小于等于0.05
    if (childTransform.position.y <= transform.position.y + 0.05f && velocity_Y < 0)
    {
        //如果满足
        velocity_Y = 0;// 子物体垂直速度清零
        childTransform.position = transform.position;//子物体position与父物体对齐
        //检测是否对齐,理论上多此一举,但是之前有遇到过位置不准确的情况,所以加一个双保险
        if (childTransform.position == transform.position)
        {
            //满足位置对齐
            isJump = false;//则将跳跃状态设置为false,等待下一次跳跃
        }
    }
    childTransform.Translate(new Vector3(0, velocity_Y) * Time.fixedDeltaTime);//子物体按照速度移动
}

void ReadyJump()
{
    velocity_Y = Mathf.Sqrt(jumpHeight * -2f * aSpeed);
}

效果
在这里插入图片描述

人物移动跳跃完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerParentMove : MonoBehaviour
{
    public float moveSpeed = 10;//移动速度(父物体)
    public float jumpHeight = 5;//跳跃高度
    public float aSpeed = -9.8f;//重力加速度

    private Vector2 direction;//移动方向(父物体,xy轴平面)
    private bool isJump = false;//跳跃状态
    public bool isAttack = false;//攻击状态
    private float velocity_Y;//跳跃速度(子物体)

    private Animator ani;//动画控制器(子物体)
    private Rigidbody2D rig;//刚体组件(父物体)

    public Transform childTransform;//Transform组件(子物体)
    void Start()
    {
        ani = GetComponentInChildren<Animator>();//初始化获得子物体的动画控制器
        rig = GetComponent<Rigidbody2D>();//初始化获得自身的刚体组件
    }

    // Update is called once per frame
    void Update()
    {
        direction.x = Input.GetAxisRaw("Horizontal");//获取键盘x轴输入,赋值给移动方向的x值
        direction.y = Input.GetAxisRaw("Vertical")  *  0.7f;//获取键盘x轴输入,赋值给移动方向的x值(*0.7是因为视觉效果,向里走要慢一点,可根据实际效果改变)

        //检测键盘跳跃键输入并且跳跃状态为false
        if (Input.GetKeyDown(KeyCode.Space) && !isJump &&!isAttack)
        {
            isJump = true;//跳跃状态赋值为true
            ReadyJump();//执行准备跳跃方法
        }

        //检测键盘攻击键输入并且攻击状态为false
        if(Input.GetMouseButtonDown(0) && !isAttack && !isJump)
        {
            isAttack = true;//攻击状态赋值为true
            //Accatk();
        }
    }


    //之所以在FixUpdate里面执行移动和跳跃方法,是因为父物体移动用的是刚体的Velocity方法,子物体跳跃虽然是用Transform,但是为了跳跃时配合移动不出现卡顿,也放在FixUpdate里面执行
    private void FixedUpdate()
    {
        if (isAttack) direction = new Vector2(0, 0);
            Move();//移动方法(父物体)
            Jump();//跳跃方法(子物体)
            Anima();//执行动画控制方法
    }

    void Move()
    {
        rig.velocity = direction * moveSpeed * 50 * Time.fixedDeltaTime;//父物体沿移动方向移动
        if (rig.velocity.x >= 0.05)
        {
            transform.rotation = new Quaternion(0, 0, 0, 0);//如果速度向右不翻转
        }
        else if (rig.velocity.x <= -0.05)
        {
            transform.rotation = new Quaternion(0, 180, 0, 0); //如果速度向左翻转180°
        }
    }

    void Jump()
    {
        velocity_Y += aSpeed * Time.fixedDeltaTime;//重力模拟(子物体垂直速度始终受重力加速度影响)
        //判断子物体是在下落状态(velocity小于零)并且距离父物体小于等于0.05
        if (childTransform.position.y <= transform.position.y + 0.05f && velocity_Y < 0)
        {
            //如果满足
            velocity_Y = 0;// 子物体垂直速度清零
            childTransform.position = transform.position;//子物体position与父物体对齐
            //检测是否对齐,理论上多此一举,但是之前有遇到过位置不准确的情况,所以加一个双保险
            if (childTransform.position == transform.position)
            {
                //满足位置对齐
                isJump = false;//则将跳跃状态设置为false,等待下一次跳跃
            }
        }
        childTransform.Translate(new Vector3(0, velocity_Y) * Time.fixedDeltaTime);//子物体按照速度移动
    }

    void ReadyJump()
    {
            velocity_Y = Mathf.Sqrt(jumpHeight * -2f * aSpeed);
    }

    void Anima()
    {
        ani.SetFloat("Velocity", velocity_Y);
        ani.SetBool("isJump", isJump);

        if(!isJump)
        {
            if (Mathf.Abs(rig.velocity.x) >= 0.05 || Mathf.Abs(rig.velocity.y) >= 0.05)
            {
                ani.SetBool("Running", true);
            }
            else ani.SetBool("Running", false);
        }
        else
        {
            ani.SetBool("Running", false);
        }

        if(isAttack)
        {
            ani.SetBool("isAttack", true);
        }
    }
}

挂载脚本和参数配置
在这里插入图片描述

人物脚底的影子效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerShadow : MonoBehaviour
{
    public Transform playerTranform;//玩家(子物体)Transform
    public float shadowSizeFloat = 0.5f;//影子最小缩放比例(在原有基础上)

    private float heightDifference;//玩家跳跃高度差
    private Vector3 scale;//初始影子缩放大小
    private PlayerParentMove playerMove;//声明玩家(父物体)移动脚本,主要是获取玩家设置的跳跃高度
    void Start()
    {
        playerMove = GetComponentInParent<PlayerParentMove>();//得到玩家(父物体)移动脚本
        scale = transform.localScale;//将影子初始缩放赋值给scale
    }

    void Update()
    {
        heightDifference = playerTranform.position.y - transform.position.y;//高度差计算:子物体y值-父物体y值
        //按照最大跳跃高度和高度差的比例来缩放影子大小,限制影子最小缩放
        //Mathf.Clamp()这里有三个参数,第一个参数是要限制的变量,第二个是最小值,第三个是最大值
        //用scale.x-(heightDifference/playerMove.jumpHeight)*scale.x,计算根据高度差与最大高度比例从0到初始值的变换
        //并且在最小值使用scale.x*shadowSizeFloat,来限制最小值,即使计算出来是0小于最小值,返回值也会是最小值
        //scale.y缩放同理
        transform.localScale = new Vector3(Mathf.Clamp(scale.x-(heightDifference/playerMove.jumpHeight)*scale.x, scale.x * shadowSizeFloat, scale.x), Mathf.Clamp(scale.y - (heightDifference / playerMove.jumpHeight) * scale.y, scale.y * shadowSizeFloat, scale.y), scale.z);
    }
}

脚本挂载在人物Shadow上,并配置参数
在这里插入图片描述
运行效果
在这里插入图片描述

最终运行效果

在这里插入图片描述

源码

链接:https://pan.baidu.com/s/1LL8gEhjeEHLMXzWXQayFwQ
提取码:zcq9

参考

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

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/979844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Lua03——开发环境搭建

1 安装开发插件 在 idea 或 vscode 中安装 lua 的开发插件 EmmyLua 2 创建工程 在 idea 中创建一个新的工程 工程的类型选择 lua 输入工程名及目标目录 在工程结构的SDK中设置lua在本地安装目录 在工程结构的modules中选择 lua 3 编写第一个lua程序 在工程下添加程序包&#…

C# OpenVinoSharp PP-TinyPose 人体姿态识别

效果 项目 部分代码 using OpenCvSharp; using OpenCvSharp.Extensions; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;name…

【代码随想录day24】不同的二叉搜索树

题目 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5示例 2&#xff1a; 输入&#xff1a;n 1 输出&#xf…

TOWE模块化积木式定制PDU的应用优势

随着计算机网络技术发展&#xff0c;服务器、交换机、各种电子设备等关键设备的需求也日益增加&#xff0c;其承担的业务越来越关键&#xff0c;对设备所处的环境&#xff08;如机房、机柜等&#xff09;要求也越高&#xff0c;所有参与关键设备运行的设施都必须具有高可靠性与…

给苹果手机相册上锁,有3种方法!

手机跟个人的联系越来越密切&#xff0c;总有些不想让别人看到的图片。如果你使用的恰好是苹果手机&#xff0c;想要隐藏相册里的图片&#xff0c;要怎么做&#xff1f;本篇教大家3个方法。 方法1 将iOS更新至16.0版本&#xff0c;打开苹果手机的【设置】&#xff0c;点击【照…

Stable Diffuse AI 绘画 之 ControlNet 插件及其对应模型的下载安装

Stable Diffuse AI 绘画 之 ControlNet 插件及其对应模型的下载安装 目录 Stable Diffuse AI 绘画 之 ControlNet 插件及其对应模型的下载安装 一、简单介绍 二、ControlNet 插件下载安装 三、ControlNet 插件模型下载安装 四、ControlNet 插件其他的下载安装方式 五、Co…

原来Linux这么牛:称霸全球超级电脑 500 强!

还记得之前《全球超级电脑 500 强&#xff0c;中国拿走冠亚军》新闻&#xff1f;虽然昔日超级电脑强权的美国在超级计算机竞赛中落后&#xff0c;但不管哪国打造的超级电脑&#xff0c;还有一件事情值得留意喔──几乎全部都是执行以 Linux 为基础的操作系统&#xff08;注&…

视频号小店怎么进优选联盟?聊下视频号店铺的选品细节,建议收藏

我是王路飞。 视频号小店可能还有很多人不太了解&#xff0c;但是你要知道&#xff0c;红利与机会从来不会消失。 它只会悄悄的转移&#xff0c;转移到你的认知以外&#xff0c;转移到那些新的平台&#xff0c;转移到那些被人忽略的事情里面。 而视频号小店就是目前除了抖音…

【PowerQuery】连接组的复制与粘贴

在实际的应用场景中&#xff0c;单一连接的场景非常少见。通常存在着两个或者两个以上的PowerQuery数据源。在这类场景下一个一个的复制数据源效率非常低下&#xff0c;是否存在更加有效率的数据源复制方式呢&#xff1f;接下来分享的连接组功能就是这样的概念。在PowerQuery中…

动手实践:从栈帧看字节码是如何在 JVM 中进行流转的

Java全能学习面试指南&#xff1a;https://www.javaxiaobear.cn/ 前面我们提到&#xff0c;类的初始化发生在类加载阶段&#xff0c;那对象都有哪些创建方式呢&#xff1f;除了我们常用的 new&#xff0c;还有下面这些方式&#xff1a; 使用 Class 的 newInstance 方法。使用…

【C++】—— 特殊类设计

目录 序言 &#xff08;一&#xff09;设计一个不能被拷贝的类 &#xff08;二&#xff09;设计一个只能在堆上创建对象的类 &#xff08;三&#xff09;设计一个只能在栈上创建对象的类 &#xff08;四&#xff09;设计一个不能被继承的类 总结 序言 特殊类设计是指在面…

AR产业变革中的“关键先生”和“关键力量”

今年6月的WWDC大会上&#xff0c;苹果发布了头显产品Vision Pro&#xff0c;苹果CEO库克形容它&#xff1a; 开启了空间计算时代。 AR产业曾红极一时&#xff0c;但因为一些技术硬伤又减弱了声量&#xff0c;整个产业在起伏中前行。必须承认&#xff0c;这次苹果发布Vision P…

百度文心一言可以接入微信小程序啦!

文心一言(英文名:ERNIE Bot)是百度全新一代知识增强大语言模型,文心大模型家族的新成员,能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感 …

python学习之【深拷贝】

#我的编程语言学习笔记# 前言 上一篇文章python学习之【浅拷贝】 学习了python中的浅拷贝相关内容&#xff0c;这篇文章接着学习深拷贝。 简单回顾 浅拷贝只拷贝浅层元素&#xff0c;深层元素的内存地址不改变 &#xff1b;当对拷贝产生的新的对象的浅层元素进行更改时&…

擎创技术流 | 深入浅出运维可观测工具(三):eBPF如何兼容多架构模式性能管理

嗨~又见面了大家&#xff01; 之前给大家分享过2篇eBPF技术干货&#xff0c;后台收到的反馈还挺好的&#xff0c;以至于总有朋友过来催更这一系列&#xff0c;这不第3篇在大家的千呼万唤下终于出来了。 新来的朋友点这里&#xff0c;键回看eBPF精彩技术贴&#xff0c;别忘了随…

Vue2安装vuex和vue-router报错处理

Vue2安装vuex和vue-router报错处理 Vue2.6安装VuexVue2.6安装vue-router Vue2.6安装Vuex 报错信息 处理方法 #查看vuex版本 npm view vuex versions --json #安装合适版本 npm install vuex3.6.2 --saveVue2.6安装vue-router 报错信息 处理方法 #查看vue-router版本 npm…

2009-2022年商业银行竞争度数据(勒纳指数)(含原始数据和计算代码 dofile+结果)

2009-2022年商业银行竞争度数据&#xff08;勒纳指数&#xff09;&#xff08;含原始数据和计算代码 dofile结果&#xff09; 1、时间&#xff1a;2009-2022年 2、来源&#xff1a;整理自wind 3、指标&#xff1a;证券代码、证券简称、上市日期、年份、资产总计、利息支出、…

C语言系统化精讲(一):C 语言开发环境搭建

文章目录 一、Windows 开发环境搭建1.1 安装 mingw 编译器1.2 下载并安装 CLion1.3 启动 CLion 二、Linux 开发环境搭建&#xff08;建议使用&#xff09;2.1 VMware Workstation Pro软件简介及安装2.2 安装 Ubuntu 系统2.2.1 Ubuntu 下载2.2.2 安装 Ubuntu2.2.3 安装共享文件夹…

汽车3D HMI图形引擎选择

2002年,电影《少数派报告》让观众深入了解未来。 除了情节的核心道德困境之外,大多数人都对它的技术着迷。 我们看到了自动驾驶汽车、个性化广告和用户可以无缝交互的 3D 计算机界面。 令人惊讶的是,虽然故事发生在 2054 年,但许多科幻想象的作品已经成为现实。 对于汽车和…