版权声明:

  • 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号“优梦创客”(微信号:unitymaker)
  • 您可以自由转载,但必须加入完整的版权声明!

场景搭建

  1. 将第一关的3张背景图片收尾相接

按住V键可以选中4个角进行拖拽和拼接





  1. 给它们一个共同的碰撞器作为地面
  2. 给场景中的石头添加碰撞器
  3. 给木头平台添加平台效果器

预制体的制作

  1. 木桶预制体

    1. 设置碰撞器,刚体设置为静态
    2. 添加脚本和动画控制器



    3. 制作动画

    当木桶碰到子弹则修改木桶的sprite

    木桶有两滴血,当血量等于0的时候,播放闪烁的动画

  2. 敌人预制体

    1. 设置碰撞器和刚体
    2. 添加脚本和动画控制器



    3. 制作动画

    敌人碰到子弹后会播放死亡动画

    敌人每隔5秒之后会向前移动一段距离,如果碰到玩家则会发起攻击,如果没有碰到则再过5秒之后继续移动

    敌人只有出现在Camera内的时候才会移动,否则不进行移动计时

  3. 老人预制体

    1. 设置碰撞器、触发器和刚体
    2. 添加脚本和动画控制器



    3. 制作动画









    当老人在被绑住的时候碰到子弹,则被释放,播放释放动画

    当老人在被绑住的时候碰到玩家,玩家可以穿过它

    当老人被释放后碰到玩家,则会给玩家一个礼物,玩家吃掉礼物后会改变自身子弹的sprite

    当老人给完礼物后会穿过玩家跑走

  4. 敌机预制体

    1. 设置碰撞器和刚体
    2. 添加脚本和动画控制器



    3. 制作动画

    敌机在玩家走到某个位置时才会显示,并且追踪玩家的位置

    当与玩家的位置小于0.5时,会向下投放炸弹,若玩家被炸弹击中则游戏结束

    敌机有10滴血,若血量降到0,则播放爆炸动画,动画播放完成销毁敌机

  5. 子弹预制体

    1. 设置碰撞器和刚体
    2. 添加脚本和动画控制器

    利用对象池,在游戏开始的时候就创建10个子弹,每当玩家发出子弹则改变对象池中的某个子弹的位置

    当子弹位置离开玩家5个单位以上则会重置到开始位置

    若子弹碰到碰撞体之后子弹会被重置

  6. 炸弹预制体

    1. 设置碰撞器和刚体
    2. 添加脚本和动画控制器

Player的制作

  1. 将Body和Foot进行拼接,放在一个空节点下
  2. 创建一个空节点作为子弹的发出位置,并作为玩家的子节点
  3. 在Player脚下的碰撞器之外创建两个空节点作为射线检测的开始和结束位置用于检测是否落地



4. Player动画控制器的制作



5. Player移动的脚本实现

玩家的转身是通过旋转Y轴180°实现的

通过获取按键的数值,改变对象Y轴的旋转

Y轴的速度不能为0,不然跳不起来

Y轴的在空中或地上都要判断,而X轴的移动只能在地上才能取得

只有在地上的时候才能播放walk动画

跳跃的时候要将Walk的条件置为非,否则动画会在Jump和Walk之间来回切换

在下一帧才播放shoot动画,但子弹却在这一帧出现,有点违和

解决方法:将子弹出现的位置延后 并且将渲染关掉,当子弹的X轴位置大于人物X轴位置+1时,开启渲染

当蹲下射击的时候子弹的位置为player的位置(player的位置比bulletLeftRight靠下一点,刚好满足下蹲发射降低高度的需求)

void FixedUpdate()
{
if (!GameControl.instance.isGameOver)
{
x = Input.GetAxis("Horizontal");
y = Input.GetAxis("Vertical");
absx = Mathf.Abs(x); ground = Physics2D.Linecast(hitlinestart.position, hitlineend.position, 1 << this.gameObject.layer); //通过获取按键的数值,改变对象Y轴的旋转,除去0 是为了让player保持之前一个方向
if (x > 0 && ground)
transform.eulerAngles = new Vector3(0, 180, 0);
else if (x < 0 && ground)
transform.eulerAngles = Vector3.zero; playerDir = transform.eulerAngles.y == 0 ? -1 : 1;//判断人物方向有没有改变,取得子弹的方向 GetComponent<Rigidbody2D>().velocity = new Vector2(x * xspeed, GetComponent<Rigidbody2D>().velocity.y);//Y轴的速度不能为0,不然跳不起来 GetComponent<Animator>().SetFloat("DirY", y);//Y轴的在空中或地上都要判断,而X轴的移动只能在地上才能取得 if (ground)//只有在地上的时候才能播放walk动画
{
GetComponent<Animator>().SetFloat("DirX", absx);
//GetComponent<Animator>().SetFloat("DirY", y);
GetComponent<Animator>().SetBool("Jump", false); if (Input.GetKeyDown(KeyCode.K))//按了空格且在地上
{
GetComponent<Rigidbody2D>().AddForce(new Vector2(0, yspeed));
GetComponent<Animator>().SetBool("Jump", true);
GetComponent<Animator>().SetFloat("DirX", 0);//跳跃的时候要将Walk的条件置为非,否则动画会在Jump和Walk之间来回切换
}
} if (Input.GetKeyDown(KeyCode.J) && ground)//播放射击动画的逻辑
{
GetComponent<Animator>().SetBool("Shoot", true); //在下一帧才播放shoot动画,但子弹却在这一帧出现,有点违和
//解决方法:将子弹出现的位置延后 ,并且将渲染关掉,当子弹的X轴位置大于人物X轴位置+1时,开启渲染 bullets[bulletIndex].GetComponent<SpriteRenderer>().enabled = false; bullets[bulletIndex].transform.position = bulletLeftRight.position; //子弹的出现位置
bullets[bulletIndex].transform.rotation = transform.rotation;//子弹的旋转跟人物的旋转一致
bullets[bulletIndex].GetComponent<Rigidbody2D>().velocity = new Vector2(playerDir * bulletSpeed, 0);//默认子弹的朝向跟人物一致,Y轴速度为0 if (Input.GetKey(KeyCode.W)) //按住上的同时按下J,向上射击
{
bullets[bulletIndex].transform.position = transform.position + Vector3.up + playerDir * Vector3.right;//修改子弹出现的位置
bullets[bulletIndex].transform.eulerAngles = new Vector3(0, 0, -90f);//旋转子弹的角度
bullets[bulletIndex].GetComponent<Rigidbody2D>().velocity = new Vector2(0, bulletSpeed);//给子弹一个向上的速度
}
else if (Input.GetKey(KeyCode.S)) //按住下的同时按下J,蹲下射击
{
bullets[bulletIndex].transform.position = transform.position;//子弹的位置为player的位置(player的位置比bulletLeftRight靠下一点,刚好满足下蹲发射降低高度的需求)
} bulletIndex++;
bulletIndex %= bullets.Length;
}
else if (!ground && Input.GetKeyDown(KeyCode.J) && Input.GetKey(KeyCode.W))//禁止玩家在空中左右射击
{
GetComponent<Animator>().SetBool("Shoot", true); //在下一帧才播放shoot动画,但子弹却在这一帧出现,有点违和
//解决方法:将子弹出现的位置延后,并且将渲染关掉,当子弹的X轴位置大于人物X轴位置+1时,开启渲染 bullets[bulletIndex].GetComponent<SpriteRenderer>().enabled = false; bullets[bulletIndex].transform.position = transform.position + Vector3.up + playerDir * Vector3.right;//修改子弹出现的位置
bullets[bulletIndex].transform.eulerAngles = new Vector3(0, 0, -90f);//旋转子弹的角度
bullets[bulletIndex].GetComponent<Rigidbody2D>().velocity = new Vector2(0, bulletSpeed);//给子弹一个向上的速度 bulletIndex++;
bulletIndex %= bullets.Length;
}
//将射击动画改为idel动画的条件,是子弹的位置跟人物位置距离超过5
if (bulletIndex >= 1)
{
if (Mathf.Abs(bullets[bulletIndex - 1].transform.position.x - transform.position.x) > 2)
GetComponent<Animator>().SetBool("Shoot", false);
}
else
{
if (Mathf.Abs(bullets[bullets.Length - 1].transform.position.x - transform.position.x) > 2)
GetComponent<Animator>().SetBool("Shoot", false);
}
} }

Car的制作

  1. 将图片按照顺序进行拼接
  2. 将拼接好的车子放到一个空节点,给这个空节点一个刚体用于给它速度



GameOver和Win的显示

  1. 添加两个Text的UI组件,Text的内容分别为GameOver和You Win
  2. 在玩家死亡或者胜利的时候enable对应的Text



摄像机移动的脚本实现

  1. 将摄像机的X轴控制在它自身到35之内,并随着玩家位置改变(保证摄像机不能往回走)
 camerax = Mathf.Clamp(player.transform.position.x, camerax > 0 ? camerax : 0, 35.5f*level);

 playerx = Mathf.Clamp(player.transform.position.x, camerax - 8f, camerax + 8f);//将玩家位置控制在摄像机范围之内(保证玩家不能往回走)

 player.transform.position = new Vector3(playerx, player.transform.position.y, player.transform.position.z);

 mainCamera.transform.position = new Vector3(camerax, mainCamera.transform.position.y, -10);

开场动画的实现

  1. 通过时间来控制Car的移动和停止
  2. 通过MovePosition来让玩家有一个从车上跳出的效果,且在站定之后转向
    private void JumpOutOfCar()//开场动画
{
if (car.position.x >= -0.01)
{
player.SetActive(true);
time += Time.fixedDeltaTime;
if (time < 0.4f)
{
player.GetComponent<Rigidbody2D>().MovePosition(Vector2.MoveTowards(player.transform.position, new Vector2(-3f, 0f), 3.5f * Time.fixedDeltaTime));//人物跳起移动
}
else if (time > 0.4f && time < 1f)
{
player.GetComponent<Rigidbody2D>().MovePosition(Vector2.MoveTowards(player.transform.position, new Vector2(-4f, -1.65f), 3.5f * Time.fixedDeltaTime));//人物下落移动
}
else if (time > 1.5f)
{
player.transform.rotation = new Quaternion(0, 180, 0, 0);//人物转向
}
} }

敌机追踪玩家的脚本实现

  1. 判断玩家的位置是在Jet的左边还是右边,且向玩家位置移动
  2. 当与玩家位置小于0.5则扔炸弹
  3. 若血量为0 ,则在播放完成爆炸后销毁Jet
    void FixedUpdate()
{
trax = Mathf.Clamp(transform.position.x,29f,42f);
transform.position = new Vector3(trax, transform.position.y, 0); if (GameControl.instance.mainCamera.transform.position.x > 35)//摄像机的位置控制直升机的出现
GetComponent<SpriteRenderer>().enabled = true;
if(GetComponent<SpriteRenderer>().enabled == true&&hp>0)
{
if(transform.position.x > GameControl.instance.player.transform.position.x+0.5)
{
transform.eulerAngles = new Vector3(0, 0, 0);
GetComponent<Rigidbody2D>().velocity = 2*Vector2.left;
}
else if(transform.position.x < GameControl.instance.player.transform.position.x-0.5)
{
transform.eulerAngles = new Vector3(0, 180, 0);
GetComponent<Rigidbody2D>().velocity = 2 * Vector2.right;
}
else
{
GetComponent<Rigidbody2D>().velocity = Vector2.zero;
if(!boomAlive)
{
Instantiate(jetBullet, transform.position + Vector3.down, Quaternion.identity);
boomAlive = true;
}
}
}
else
GetComponent<Rigidbody2D>().velocity = Vector2.zero; if (hp == 0)
{
GetComponent<Animator>().SetBool("Explosion", true);
Invoke("DestroyThis", 3f);
Invoke("SetGameWin",3f);
} }

Older给礼物和被释放的脚本实现

  1. 老人被释放后如果不持续施加速度,那么速度会因为摩擦力而衰减,最后导致速度为0
  2. 在没被释放之前,把older的碰撞器改为触发器,使玩家可以穿过older
  3. 在没被释放之前,玩家可以穿过older,玩家离开碰撞器后还把该碰撞器改回去
    void FixedUpdate()
{
if(isRelease)
{ time += Time.fixedDeltaTime;
if (time >= 1f && time <=6f&&!isGiving)
{
GetComponent<Animator>().SetBool("run", true);
GetComponent<Rigidbody2D>().velocity = new Vector2(-4f, GetComponent<Rigidbody2D>().velocity.y);
} else if (time > 6)
Destroy(this.gameObject);
}
} public void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Bullet")
{
isRelease = true;
GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
GetComponent<Animator>().SetBool("release", true);
}
if (collision.gameObject.tag == "Player" && !isGift&&isRelease)
{
isGift = true;//防止多次给礼物
isGiving = true;//防止给礼物时还在移动
GetComponent<Rigidbody2D>().velocity = Vector2.zero;
GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Kinematic;
collision.gameObject.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Kinematic;
GetComponent<Animator>().SetBool("give", true); Invoke("GiveOver", 1f);
}
else if (collision.gameObject.tag == "Player"&& !isRelease)
{//
GetComponent<BoxCollider2D>().isTrigger = true;
}
}
public void OnTriggerExit2D(Collider2D collision)
{ if (collision.gameObject.tag == "Player")
{
if (isRelease)
{
GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
collision.gameObject.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
}
else
{//
GetComponent<BoxCollider2D>().isTrigger = false ;
} }
} private void GiveOver()
{
isGiving = false;
GetComponent<Animator>().SetBool("give", false); Instantiate(gift, transform.position + Vector3.right, Quaternion.identity);
}

Unity经典游戏教程之:合金弹头的更多相关文章

  1. Unity经典游戏教程之:雪人兄弟

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  2. Unity经典游戏教程之:贪吃蛇

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  3. Unity经典游戏教程之:是男人就下100层

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  4. Unity经典游戏教程之:冒险岛

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  5. Unity经典游戏教程之:弓之骑士

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  6. Unity经典游戏编程之:球球大作战

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  7. C#开发Unity游戏教程之Unity中方法的参数

    C#开发Unity游戏教程之Unity中方法的参数 Unity的方法的参数 出现在脚本中的方法,无论是在定义的时候,还是使用的时候,后面都跟着一对括号“( )”,有意义吗?看起来最多也就是起个快速识别 ...

  8. C#开发Unity游戏教程之Scene视图与脚本的使用

    C#开发Unity游戏教程之Scene视图与脚本的使用 Unity中Scene视图的快捷操作 Scene视图是开发者开发游戏时,操作最频繁的视图.因为一旦一个游戏对象被添加到游戏的场景中,就需要首先使 ...

  9. Unity实战案例教程之:不免费的PacMan(初级→中级)

    课程内容介绍: 本套课程适合以下人士: - 免费资料没教会你游戏开发的: - 学了Unity基础不知道怎么用在游戏项目里的: - 想快速开发一款好玩的游戏的: - 想学游戏不知道如何入门的: - 对游 ...

随机推荐

  1. docker安装gitlab-runner

    docker安装gitlab-runner docker pull gitlab/gitlab-runner:latest安装gitlab-runner 打开自己搭建的GitLab网站,点击顶栏的Sn ...

  2. CSS3常用选择器

    一.基本选择器 子元素选择器 概念:子元素选择器只能选择某元素的子元素语法格式:父元素 > 子元素 (Father > Children)兼容性:IE8+.FireFox.Chrome.S ...

  3. VS2008 专业版试用到期破解 【转】

    对于在win7内核下的vs2008破解,和在xp内核系统下的破解是不同的.传统(XP)的破解方式: 一.先安装试用版,然后在“添加或删除程序”里找到VS2008,点“更改/删除”就会看到一个输入序列号 ...

  4. [网络协议]TCP粘包分析

    关于socket粘包,socket缓冲区设置的问题,记录一下: 一 .两个简单概念长连接与短连接: 长连接     Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送 ...

  5. C# 获取计算机相关信息

    整理了一个关于计算机相关系统的资料 需要引入命名空间: 1. 在'解决方案资源管理器' 窗口中->右击项目-> '添加' -> '引用' 弹出引用管理器 2. 在引用处理器中,程序集 ...

  6. 单个单选框radio 点击选中点击取消选中

    $("input:radio").click(function(){ var domName = $(this).attr('name');//获取当前单选框控件name 属性值 ...

  7. struts2入门Demo

    一.引入必要的jar包,所需jar包如下: 二.配置web.xml.主要目的是拦截请求 <?xml version="1.0" encoding="UTF-8&qu ...

  8. Spring WebFlux之HttpHandler的探索

    这是本人正在写的<Java 编程方法论:响应式Reactor3.Reactor-Netty和Spring WebFlux>一书的文章节选,它是<Java编程方法论:响应式RxJava ...

  9. 三个标签完成springboot定时任务配置

    1. 问题描述 Java项目定时任务是必备模块,月高风黑夜跑个批处理,记录或者统计一些系统信息. 2. 解决方案: 结合springboot,只需三个标签就能完成定时任务配置. 2.1 标签1 用在s ...

  10. java算法题每日一练01,java入门简单算法题小练

    1.给数组做反序 public class Ak01 { public static void main(String[] args) { int[] a = new int[]{22,48,41,2 ...