Unity2d平台动作游戏教程

2024-02-05 18:10

本文主要是介绍Unity2d平台动作游戏教程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最终效果如下:

目录

玩家的基础移动

加入移动和跳跃动画

加入攻击动作

实现打击感

添加敌人受击动画与击退

添加敌人受击特效

 攻击时的屏幕振动


首先实现最基础的功能,将环境拖拽进来,注意到环境的各个前后景的层次感是通过设定layer实现的:

 

玩家的基础移动

我们将玩家设定在第七个layer,以便于突出玩家处于环境中间。

并为了跳跃手感改变重力scale,这可以实现重力对不同的物体有不同的效果。

下面这段代码实现了移动和跳跃

public class MyPlayerController : MonoBehaviour
{new private Rigidbody2D rigidbody;private float input;private bool isGround;[SerializeField]public Vector3 checkPointOffset;[SerializeField]public LayerMask groundLayer;public int moveSpeed = 10;public int jumpStartSpeed = 10;// Start is called before the first frame updatevoid Start(){rigidbody = GetComponent<Rigidbody2D>();}// Update is called once per framevoid Update(){input = Input.GetAxisRaw("Horizontal");isGround = Physics2D.OverlapCircle(transform.position + new Vector3(checkPointOffset.x, checkPointOffset.y, 0), checkPointOffset.z, groundLayer);Move();}void Move(){rigidbody.velocity = new Vector2(input * moveSpeed, rigidbody.velocity.y);if (Input.GetKeyDown(KeyCode.W) && isGround){rigidbody.velocity = new Vector2(0, jumpStartSpeed);}if (rigidbody.velocity.x < 0)transform.localScale = new Vector3(-1, 1, 1);else if (rigidbody.velocity.x > 0)transform.localScale = new Vector3(1, 1, 1);}
}

这两个标头具有序列化的作用:

 

 

加入移动和跳跃动画

exit time打断时间(从哪一帧开始逐渐降低当前动画的权重)、

fixed duration固定持续时间(这其实是一个切换开关,切换是按照秒显示还是按照百分比显示)、transition duration过度持续时间 (过度有多长)、

勾选这个选项其实影响的是以百分比还是秒来显示:

transition offset过度抵消(从下一个动画的什么位置开始播放)、

interruption source中断来源 

先创建控制器并且拖入站立和跑步和跳跃的动画,并进行衔接:

同时删去过渡时间:

在动画控制器中 如果动画切换的条件是用一个与来表示的话 可以这样:

(注意对于速度的设置判断有时候不要判断是否为0,因为有时候即使没动,物体的速度可能也是一个非常小的值:

如果是用或条件表示的话,就多添加一次transtition,就会变成下图所示:

 此处举例,从站立到跑有两个切换条件

 

 jump的切换使用触发器:

随后即可实现跑跳

接下来加入降落的动画,即人物到达最高点后,会播放降落的动画:

三种状态都有可能进入fall状态,因此进行设置

 为了降落更加流畅,给Fall添加一个无条件的falling动画,之后动画变成这样:

之后即可实现降落。

接下来实现着陆地面,由于着陆到地面有三种前置可能:jump、fall、falling,因此都需要添加转换。并且落地后无条件变为idle,如下所示:

 让玩家着陆1秒后变为idle状态:

实现如下:

 

此时代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MyPlayerController : MonoBehaviour
{new private Rigidbody2D rigidbody;private float input;private bool isGround;[SerializeField]public Vector3 checkPointOffset;[SerializeField]public LayerMask groundLayer;public int moveSpeed = 5;public int jumpStartSpeed = 10;//----------下面这部分实现动画private Animator animator;// Start is called before the first frame updatevoid Start(){rigidbody = GetComponent<Rigidbody2D>();animator = GetComponent<Animator>();}// Update is called once per framevoid Update(){input = Input.GetAxisRaw("Horizontal");isGround = Physics2D.OverlapCircle(transform.position + new Vector3(checkPointOffset.x, checkPointOffset.y, 0), checkPointOffset.z, groundLayer);Move();}void Move(){rigidbody.velocity = new Vector2(input * moveSpeed, rigidbody.velocity.y);animator.SetFloat("Horizontal", rigidbody.velocity.x);animator.SetFloat("Vertical", rigidbody.velocity.y);animator.SetBool("isGround", isGround);if (Input.GetKeyDown(KeyCode.W) && isGround){rigidbody.velocity = new Vector2(0, jumpStartSpeed);animator.SetTrigger("Jump");}if (rigidbody.velocity.x < 0)transform.localScale = new Vector3(-1, 1, 1);else if (rigidbody.velocity.x > 0)transform.localScale = new Vector3(1, 1, 1);}
}

加入攻击动作

首先导入资源,加入三个轻攻击动画到动画机里,由于希望任何状态都可以攻击,所以用any state衔接:

设置好过度条件

并且播放完攻击动画希望玩家再次进入idle,因此可以将过度衔接到exit:

重攻击同理,随后效果如下:

接下来书写Attack函数:

private int lightCombo = 1;private int heavyCombo = 1;private int comboInterval = 2;//连击的间隔,一旦超过这个间隔则玩家连击会中断private float comboTimer = 0;//连击计时器,用来记录连击到上次过了多久bool isAttack = false;    void Attack(){if (!isAttack && Input.GetKeyDown(KeyCode.J)){isAttack = true;animator.SetTrigger("LightAttack");animator.SetInteger("LightCombo", lightCombo);lightCombo++;if (lightCombo > 3) lightCombo = 1;comboTimer = 0;}if (!isAttack && Input.GetKeyDown(KeyCode.K)){isAttack = true;animator.SetTrigger("HeavyAttack");animator.SetInteger("HeavyCombo", heavyCombo);heavyCombo++;if (heavyCombo > 3) heavyCombo = 1;comboTimer = 0;}comboTimer += Time.deltaTime;if (comboTimer >= comboInterval){comboTimer = 0;lightCombo = 0;heavyCombo = 0;}}

以及一个attackOver函数,用于函数结束时调用:

    public void AttackOver()//用来给unity在动画结束时调用,采用帧事件的形式{isAttack = false;}

接下来添加帧事件,在动画播放完关键连击时插入关键帧,用于调用attackover函数。

通常这种关键帧不会放在动画的最后一帧,这样有助于连击的连贯性。 

但是我们发现攻击时仍可以移动,我们需要取消这点,取而代之,使用攻击时自动位移的方式实现位移补偿。

    private string attackType;[Header("补偿速度")]public float lightAttackSpeed=1.3f;public float heavyAttackSpeed=0.7f;    void Move(){if (!isAttack) {rigidbody.velocity = new Vector2(input * moveSpeed, rigidbody.velocity.y);}else{if(attackType=="Light") rigidbody.velocity = new Vector2(transform.localScale.x * lightAttackSpeed, rigidbody.velocity.y);if (attackType == "Heavy") rigidbody.velocity = new Vector2(transform.localScale.x * heavyAttackSpeed, rigidbody.velocity.y);}}

此处代码犯了一个错,清空连击应该设置为1而不是设置为0:

此处还犯了一个bug,bug动图如下:如果在移动中按下攻击键,则玩家不会立即进入攻击状态而是跑一小段距离再进入攻击,如果把衔接的has exit time移除即可。

在实际上自己做这一步的时候一下子犯了两个bug,以后也可能会出现一下子遇见多个bug的情况

解决bug的思路其实很简单,重点观察那些参数,检查代码是否有误,无误则检查是否是动画器某个衔接设置错了

实现打击感

添加敌人受击动画与击退

我们接下来添加敌人,并为玩家的layer设置为player,敌人的layer设置为enemy,并且我们不希望player和enemy发生碰撞,因此在设置中选择:

为敌人添加动画控制器:

 

 接下来需要在攻击动画的对应时刻进行攻击范围的判定,因此需要加特定的因素然后在特定帧修改,通过录制动画的形式。

 

加好之后,接下来书写代码:

给玩家添加attackArea后,注意层级不能设置为player否则无法发生触碰。

触碰敌人的代码:

    private void OnTriggerEnter2D(Collider2D other){if (other.CompareTag("Enemy")){if (transform.localScale.x > 0) other.GetComponent<MyEnemy>().GetHit(Vector2.right);if (transform.localScale.x < 0) other.GetComponent<MyEnemy>().GetHit(Vector2.left);Debug.Log("attack success");}}

Enemy的函数:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MyEnemy : MonoBehaviour
{private new Rigidbody2D rigidbody;private bool isHit;private Animator animator;private AnimatorStateInfo animStateInfo;public float speed;private Vector2 direction;// Start is called before the first frame updatevoid Start(){animator = GetComponent<Animator>();rigidbody = GetComponent<Rigidbody2D>();}// Update is called once per framevoid Update(){animStateInfo = animator.GetCurrentAnimatorStateInfo(0);if (isHit){rigidbody.velocity = direction * speed;if (animStateInfo.normalizedTime > 0.6f)//敌人后退的时间{isHit = false;}}}public void GetHit(Vector2 direction)//公开的给玩家调用的函数{transform.localScale = new Vector3(-direction.x, 1, 1);//与玩家的方向相反isHit = true;this.direction = direction;//让敌人按照玩家朝向的方向后退animator.SetTrigger("Hit");}
}

效果如下

添加敌人受击特效

为敌人添加子物体,并为其创建帧动画,帧动画由特效组成:

然后设置动画器:

 在enemy脚本中添加:

效果如下:

 攻击时的屏幕振动

此处希望这个类作为工具类,让其他脚本方便的调用里面的函数,所以这里采用单例模式编写,可以直接调用其方法而无需实例化。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AttackShake : MonoBehaviour
{private static AttackShake instance;public static AttackShake Instance{get{if (instance == null)instance = Transform.FindObjectOfType<AttackShake>();return instance;}}public void HitPause(int duration){StartCoroutine(Pause(duration));}IEnumerator Pause(int duration){float pauseTime = duration / 60f;Time.timeScale = 0;//暂时暂停时间yield return new WaitForSecondsRealtime(pauseTime);Time.timeScale = 1;}private bool isShake;public void CameraShake(float duration,float strength){if (!isShake) StartCoroutine(Shake(duration, strength));}IEnumerator Shake(float duration,float strength){isShake = true;Transform camera = Camera.main.transform;Vector3 startPos = camera.position;while (duration > 0){camera.position = Random.insideUnitSphere * strength+startPos;duration -= Time.deltaTime;yield return null;}isShake = false;}
}

上面实现了卡顿和抖动的函数,接下来只需要让玩家命中敌人时调用该函数并传入参数即可。

在playerController中:

[Header("打击感")]public float shakeTime=0.1f;public int lightPause = 6;public float lightStrength=0.015f;public int heavyPause=12;public float heavyStrength=0.065f;private void OnTriggerEnter2D(Collider2D other){if (other.CompareTag("Enemy")){if (transform.localScale.x > 0) other.GetComponent<MyEnemy>().GetHit(Vector2.right);if (transform.localScale.x < 0) other.GetComponent<MyEnemy>().GetHit(Vector2.left);Debug.Log("attack success");if (attackType == "Light"){AttackShake.Instance.HitPause(lightPause);AttackShake.Instance.CameraShake(shakeTime, lightStrength);}if (attackType == "Heavy"){AttackShake.Instance.HitPause(heavyPause);AttackShake.Instance.CameraShake(shakeTime, heavyStrength);}}}

然后根据攻击类型是轻重攻击调用不同的参数即可,最终效果如下:

这篇关于Unity2d平台动作游戏教程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/681750

相关文章

springboot家政服务管理平台 LW +PPT+源码+讲解

3系统的可行性研究及需求分析 3.1可行性研究 3.1.1技术可行性分析 经过大学四年的学习,已经掌握了JAVA、Mysql数据库等方面的编程技巧和方法,对于这些技术该有的软硬件配置也是齐全的,能够满足开发的需要。 本家政服务管理平台采用的是Mysql作为数据库,可以绝对地保证用户数据的安全;可以与Mysql数据库进行无缝连接。 所以,家政服务管理平台在技术上是可以实施的。 3.1

Steam邮件推送内容有哪些?配置教程详解!

Steam邮件推送功能是否安全?如何个性化邮件推送内容? Steam作为全球最大的数字游戏分发平台之一,不仅提供了海量的游戏资源,还通过邮件推送为用户提供最新的游戏信息、促销活动和个性化推荐。AokSend将详细介绍Steam邮件推送的主要内容。 Steam邮件推送:促销优惠 每当平台举办大型促销活动,如夏季促销、冬季促销、黑色星期五等,用户都会收到邮件通知。这些邮件详细列出了打折游戏、

比较学习难度:Adobe Illustrator、Photoshop和新兴在线设计平台

从入门设计开始,几乎没有人不知道 Adobe 公司两大设计软件:Adobe Illustrator和 Photoshop。虽然AI和PS很有名,有一定设计经验的设计师可以在早期探索和使用后大致了解AI和PS的区别,但似乎很少有人会系统地比较AI和PS。目前,设计软件功能多样,轻量级和网页设计软件已成为许多设计师的需求。对于初学者来说,一篇有针对性的AI和PS比较总结文章具有非常重要的指导意义。毕竟

X-AnyLabeling使用教程

1.AI 模型自动分割标注使用教程 2.AI 模型自动目标检测标注使用教程

智慧环保一体化平台登录

据悉,在当今这个数字化、智能化的时代,环境保护工作也需要与时俱进,不断创新。朗观视觉智慧环保一体化平台应运而生,它利用先进的信息技术手段,为环保工作提供了更加便捷、高效的管理方式,成为推动绿色发展的重要力量。 一、智慧环保一体化平台的诞生背景 随着工业化进程的加快,环境污染问题日益严重,传统的环保管理模式已经难以满足现代社会的需求。为了提高环保工作的效率和质量,智慧环保一体化平台应运而

青龙面板2.9之Cdle傻妞机器人编译教程

看到有的朋友对傻妞机器人感兴趣,这里写一下傻妞机器人的编译教程。 第一步,这里以linux amd64为例,去官网下载安装go语言安装包: 第二步,输入下方指令 cd /usr/local && wget https://golang.google.cn/dl/go1.16.7.linux-amd64.tar.gz -O go1.16.7.linux-amd64.tar.gz

青龙面板部署通用教程,含服务器、路由器、X86等部署方法

1. 拉取镜像/更新镜像 docker pull whyour/qinglong:latest 2. 删除镜像 docker rmi whyour/qinglong:latest 3. 启动容器 普通服务器 docker run -dit \-v $PWD/ql/config:/ql/config \-v $PWD/ql/log:/ql/log \-v $PWD/ql/db:

宝塔面板部署青龙面板教程【简单易上手】

首先,你得有一台部署了宝塔面板的服务器(自己用本地电脑也可以)。 宝塔面板部署自行百度一下,很简单,这里就不走流程了,官网版本就可以,无需开心版。 首先,打开宝塔面板的软件商店,找到下图这个软件(Docker管理器)安装,青龙面板还是安装在docker里,这里依赖宝塔面板安装和管理docker。 安装完成后,进入SSH终端管理,输入代码安装青龙面板。ssh可以直接宝塔里操作,也可以安装ssh连接

PS系统教程25

介绍软件 BR(bridge) PS 配套软件,方便素材整理、管理素材 作用:起到桥梁作用 注意:PS和BR尽量保持版本一致 下载和安装可通过CSDN社区搜索,有免费安装指导。 安装之后,我们打开照片只需双击照片,就自动在Ps软件中打开。 前提:电脑上有PS软件 三种预览格式 全屏预览 评星级 直接按数字键就可以 方向键可以更换图片 esc退出 幻灯片放

flex布局学习笔记(flex布局教程)

前端笔试⾯试经常会问到:不定宽⾼如何⽔平垂直居中。最简单的实现⽅法就是flex布局,⽗元素加上如下代码即 可: display: flex; justify-content: center; align-items :center; 。下⾯详细介绍下flex布局吧。   2009年,W3C提出了 Flex布局,可以简便⼂完整⼂响应式地实现各种页⾯布局。⽬前已得到了所有浏览器的⽀持,这意味着,现