游戏引擎:Unity
编译版本:2021.3.11f1c2
VS2019
一、游戏的实现目标
玩家可以通过左右键控制人物左右移动,空格键实现人物跳跃,玩家可进行攻击动作,若碰到怪物则玩家死亡,若攻击到怪物则怪物死亡,玩家可以通过顶砖块,将砖块销毁。
二、实现的任务切分
2.1 音效
创建一个空对象,命名为Audio Source,并给该对象挂载一个Audio Source的组件,将默认的背景音乐拖进去,再挂载一个脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance;//定义一个静态变量来表示(AudioManager.Instance),方便后面调用
//调用组件,播放声音
private AudioSource player;
// Start is called before the first frame update
void Start()
{
Instance = this;//初始化指向自己
player = GetComponent<AudioSource>();//从自己身上获取一个组件
}
//播放音效
public void PlaySound(string name)//name表示的就是音效的名称
{
//从Resources文件夹中调用名为"name"的音效,加载音效片段,所有的音效片段都等于AudioClip
AudioClip clip = Resources.Load<AudioClip>(name);
//播放
player.PlayOneShot(clip);
}
}
如果我想在别的脚本调用AudioManager,比如我想跳跃的时候有跳跃音效,就可以AudioManager.Instance.PlaySound("jump");来调用。
2.2 人物精灵
2.2.1 人物动画
对于动画,我们的控制逻辑如下,除了idle到attack是触发以外,其他的动画都是bool判断:
2.2.2 人物组件
人物由于需要物理效应,比如跳跃后可以落下等,所以需要挂载一个Rigidbody 2D,而由于人物有一个攻击动作,所以挂载一个Box Collider 2D组件,并且该组件设置为是触发器,人物可以在地面上行走,且可以顶飞砖块,所以自身还需要一个碰撞器,人物碰撞器也可以用Capsule Collider 2D,为椭圆形的碰撞器。
最重要的是,我们需要在人物对象下创建一个IsGround的子对象,这个子对象也要挂载一个碰撞器,为的是让人物只有在地面上的时候才能进行跳跃动作。
Is Ground挂载脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IsGround : MonoBehaviour
{
//当前是否踩在地面
public bool isGround = false;
//这是一个不会产生bug的方法,创建一个数组Collider2D,它就代表和我们产生碰撞的物体
//为什么要用一个数组来操作,因为如果一个游戏做复杂了,可能会有多个地面,就有可能玩家同时踩到两个地面
private List<Collider2D> list = new List<Collider2D>();
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(list.Count > 0)
{
isGround = true;
}
else
{
isGround = false;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Ground")//如果我们和地面产生碰撞,我们就把地面加到数组里
{
list.Add(collision);
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == "Ground")//如果我们和地面离开碰撞,我们就把地面移除出数组
{
list.Remove(collision);
}
}
}
人物主体挂载脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour
{
//定义一个攻击判定距离,将组件关联到这个变量上
public Collider2D AttackTrigger;
//需要用到以下组件并给予静态变量名
private Animator ani;//人物动画
private IsGround isGround;//人物是否踩在地面
void Start()
{
ani = GetComponent<Animator>();//从我自身获取Animation组件
isGround = GetComponentInChildren<IsGround>();//从子对象中获取IsGround组件
}
// Update is called once per frame
void Update()
{
//移动 -1 0 1 就是左右,0不动
float horizontal = Input.GetAxis("Horizontal");//获取键盘横轴
if (horizontal != 0)//就证明我按了左右键,左右移动,这里涉及到人物翻转问题,调用tansform里的scale
{
//人物面对方向
transform.localScale = new Vector3(horizontal > 0 ? 1 : -1, 1, 1);//如果horizontal>0,就证明我们向右走,scale的x还是1,如果horizontal< 0,就证明我们向左走,则将scale的x改为-1
//移动
transform.Translate(Vector2.right * horizontal * Time.deltaTime);//默认向右走
//动画
ani.SetBool("IsRun", true);
}
else
{
ani.SetBool("IsRun", false);
}
//跳跃
if (Input.GetKeyDown(KeyCode.Space) && isGround.isGround)//是否按了键盘的空格键,并且是踩在地面上才给跳
{
//给一个力
GetComponent<Rigidbody2D>().AddForce(Vector2.up * 180);//获取我们身上的刚体组件,给我们一个向上的力180
//音效
AudioManager.Instance.PlaySound("jump");
}
//跳跃动画
if (isGround.isGround)//在地面
{
ani.SetBool("IsJump", false);
AttackTrigger.enabled = false;
}
else//在空中
{
ani.SetBool("IsJump", true);
AttackTrigger.enabled = true;
}
//攻击
if (Input.GetKeyDown(KeyCode.J))
{
ani.SetTrigger("Attack");//显示一个攻击动画
}
}
//开始攻击
public void Attack()
{
AttackTrigger.enabled = true;
}
//结束攻击
public void AttackEnd()
{
AttackTrigger.enabled = false;
}
//死亡
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Enemy")//如果碰到一个物体标签是敌人
{
//死亡,死亡的时候人会变成雪球先往天上弹然后掉下去
Destroy(GetComponent<Collider2D>());//删除自身的碰撞器
Destroy(GetComponent<Collider2D>());//删除攻击的触发器,否则触发器依然存在的话,敌人碰到我们敌人也会死亡
GetComponent<Rigidbody2D>().AddForce(Vector2.up*150);//弹一下
ani.SetTrigger("Die");//播放死亡动画
AudioManager.Instance.PlaySound("dead");//播放死亡音效
}
}
}
2.3 砖块精灵
砖块精灵很简单,设置合适的大小,挂载碰撞器,关键在于,人物只有从下往上顶的时候,才让砖块销毁,而人物跳上去的时候还是可以正常行走的,所以我们要给砖块建立一个子对象,并且给其挂载碰撞器,并挂载脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallControl : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Player")
{
//删除碰撞器(子物体和父物体)
Destroy(GetComponent<Collider2D>());
Destroy(transform.parent.GetComponent<Collider2D>());
//给砖块一个向上的力
transform.parent.gameObject.AddComponent<Rigidbody2D>().AddForce(Vector2.up * 50);
//2s后删除砖块
Destroy(transform.parent.gameObject, 2f);
//声音
AudioManager.Instance.PlaySound("hit");
}
}
}
2.4 敌人精灵
2.4.1敌人动画
动画逻辑如下:
从run 到 die 为触发效果。
2.4.2 敌人挂载组件
敌人挂载一个是碰撞一个是刚体,挂载脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyControl : MonoBehaviour
{
private float Speed = 0.2f;//敌人移动速度
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//敌人一直在向右移动
transform.Translate(Vector2.right * Speed * Time.deltaTime);
}
//碰到玩家
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Player")
{
//往回走
Speed *= -1;
//敌人进行一个旋转
transform.localScale = new Vector3(transform.localScale.x * -1,1,1);
}
}
//进入玩家的攻击区域
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag== "Player")
{
//死亡动画
GetComponent<Animator>().SetTrigger("Die");
Speed *= -3;
//音效
AudioManager.Instance.PlaySound("chui");
//销毁
Destroy(gameObject, 3f);
}
}
}