如何制作一个Unity2D闯关游戏(五)
回顾
在上一篇的教程里我们给Player添加了手机动画和受击反馈,以及添加了KillPlane来防止玩家调出世界,然后又加入了的重生点系统以及Gem和Cherry,增添了游戏的可玩性。
开始第五天的制作
上一篇我们增加了玩家的受伤反馈,但是一般的闯关游戏还会再添加一个无敌时间来保证玩家的游戏性。
添加无敌时间
我们打开 PlayerHealthController 脚本,我们无敌时间的功能在这里面来添加新的代码。
首先我们先添加两行定义,分别是无敌时间以及计数器,还需要一个SpriteRenderer,通过修改透明度来表示是否处于无敌状态。
private readonly float invincibleTime =0.5f;//无敌时间
private float invincibleCounter;//无敌时间计数器
private SpriteRenderer spriteRenderer;
然后我们需要再 DealDamage 函数里把无敌时间赋值给计数器。
public void DealDamage(int damage)
{
if(invincibleCounter<=0)
{
//原先代码
//如果血量为零了则不需要无敌时间
if (currentHealth <= 0)
{
//原先代码
}
else//如果血量不为零,则需要添加无敌时间
{
//给予无敌时间
invincibleCounter = invincibleTime;
//让玩家的透明度为50%来表示无敌状态
var color = spriteRenderer.color;
spriteRenderer.color = new Color(color.r, color.g, color.b, 0.5f);
//受伤了调用反馈
PlayerController.instance.KnockBack();
}
}
}
然后计数器部分的代码在Update函数里面。
private void Update()
{
//无敌时间
if (invincibleCounter >= 0)
{
invincibleCounter -= Time.deltaTime;
//如果无敌时间为零,取消半透明
if (invincibleCounter <= 0)
{
var color = spriteRenderer.color;
spriteRenderer.color = new Color(color.r, color.g, color.b, 1f);
}
}
}
添加拾取特效
在资源包 "\2D Platformer Assets\Graphics\Collectibles" 路径下找到 Collect_Effect 素材。然后按照之前的之前的方法创建拾取特效。
我们在最后两帧将SpriteRenderer取消勾选。
添加死亡特效
素材路径以及设置方法同上。
创建特效消失脚本
我们创建一个名为 DestoryOverTime 的脚本,将其挂载在两个特效上。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyOverTime : MonoBehaviour
{
//存在时间
public float lifeTime;
private void Update()
{
Destroy(gameObject,lifeTime);
}
}
将拾取特效的lifetime设置为0.5,死亡特效的lifetime设置为0.75,设置完之后把两个特效制成预设体。
在游戏中添加特效
接下来我们先去到 Pickup 脚本里,添加生成特效脚本。
//获取特效预设体
public GameObject effects;
private void OnTriggerEnter2D(Collider2D other)
{
if (!other.CompareTag("Player")) return;
if (isGem)
{
//原先代码
Instantiate(effects, transform.position, transform.rotation);
Destroy(gameObject);
}
else if (isHeal && PlayerHealthController.instance.currentHealth!=PlayerHealthController.instance.maxHealth)
{
//原先代码
Instantiate(effects, transform.position, transform.rotation);
Destroy(gameObject);
}
}
然后再 PlayerHealthController 脚本的 DealDamage 函数里,在玩家死亡部分添加生成特效代码。
//获取死亡特效预设体
public GameObject deathEffect;
//生成代码
Instantiate(deathEffect, transform.position, transform.rotation);
添加敌人
我们在素材中找到敌人Frog,首先我们需要一个空物体作为父物体,然后将Frog放在空物体下,将空物体命名为 FrogEnemy,添加 Rigidbody 2D 和 Box Collier 2D 组件。
然后继续按照之前的方法设置动画,动画组件是在FrogEnemy上,图像是其子物体。
这个动画应该有一定的间隔,所以我们在最后让他保持原状一定时间。
接下来给FrogSprite添加一个 Box Collier 2D,设置碰撞体大小。
然后调整碰撞体和图像位置一致。
在 Animator 窗口中添加一个bool类型的 isMoving
接着我们创建两个空物体,分别作为Frog移动的两个端点,设置好位置之后将这两个空物体放入FrogEnemy下。
以上为两个物体上的组件。
编写敌人移动脚本
在制作完敌人模型之后,接下来就是添加敌人的移动逻辑。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public float moveSpeed;//敌人移动速度
public Transform leftPoint, rightPoint;//左右端点的位置
private bool movingRight=true;
private Rigidbody2D rbody;
private Animator anim;
private SpriteRenderer spriteRenderer;
private static readonly int IsMoving = Animator.StringToHash("isMoving");
public float moveTime, waitTime;//给敌人设定移动时间和暂停时间
private float moveCount, waitCount;//移动暂停计数器
void Start()
{
rbody = GetComponent<Rigidbody2D>();
spriteRenderer = transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
//将作为位置放到世界中
leftPoint.parent = null;
rightPoint.parent = null;
//因为移动是父物体移动,所以需要把端点放到世界中
moveCount = moveTime;
}
void Update()
{
//青蛙左右移动
if(moveCount>0) //移动
{
anim.SetBool(IsMoving,true);
moveCount -= Time.deltaTime;
//向右移动
if (movingRight)
{
rbody.velocity = new Vector2(moveSpeed, rbody.velocity.y);
if (transform.position.x > rightPoint.position.x)
{
movingRight = false;
spriteRenderer.flipX = false;
}
}
else//向左移动
{
rbody.velocity = new Vector2(-moveSpeed, rbody.velocity.y);
if (transform.position.x < leftPoint.transform.position.x)
{
movingRight = true;
spriteRenderer.flipX = true;
}
}
if (moveCount <= 0)
{
waitCount =Random.Range(waitTime*0.75f,waitTime*1.25f) ;
}
}
else if(waitCount>0)//暂停
{
anim.SetBool(IsMoving,false);
waitCount -= Time.deltaTime;
rbody.velocity = new Vector2(0f, rbody.velocity.y);
if (waitCount <= 0)
{
moveCount =Random.Range(moveTime*0.75f,moveTime*1.25f) ;
}
}
}
}
最后给FrogEnemy挂载DamagePlayer脚本,使Frog具有对玩家造成伤害的功能。
总结
本篇完善了角色的受伤是的一些反馈内容,增加了游戏特效,新增了新的敌人,增加了游戏的可玩性。