Unity初级案例 - 吃豆人(Unity2017.2.0)Day 2
1.用代码控制动画状态机及设置渲染顺序
//获取移动方向Vector2 dir = dest - (Vector2)transform.position;//把获取到的移动方向设置给动画状态机anim.SetFloat("DirX", dir.x);anim.SetFloat("DirY", dir.y);
2.为迷宫加入可以被吃掉的豆点
创建豆点Pacdot,添加碰撞体,并且添加Pacdot脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Pacdot : MonoBehaviour
{private void OnTriggerEnter2D(Collider2D collision){if(collision.gameObject.name == "Pacman"){Destroy(gameObject);}}
}
运行程序,结果如下
3.创建四个敌人并采用重写状态机控制动画
4.用现有的知识模拟AI的思路讲解
使用A*寻路和感知系统来完成鬼的寻路。
5.让鬼可以按照单条路径巡逻
首先添加路径点
然后给鬼添加GhostMove脚本,让它移动
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GhostMove : MonoBehaviour
{//储存所有路径点的Transform组件public Transform[] wayPoints;public float speed = 0.2f;//当前在前往哪个路径点的途中private int index = 0;private Animator anim;private void Awake(){anim = GetComponent<Animator>();}private void FixedUpdate(){if (transform.position != wayPoints[index].position){Vector2 temp = Vector2.MoveTowards(transform.position, wayPoints[index].position, speed);GetComponent<Rigidbody2D>().MovePosition(temp);}else{index = (index + 1) % wayPoints.Length;}Vector2 dir = (Vector2)wayPoints[index].position - (Vector2)transform.position;anim.SetFloat("DirX", dir.x);anim.SetFloat("DirY", dir.y);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.name == "Pacman"){Destroy(collision.gameObject);}}
}
运行程序,结果如下
6.改进巡逻系统使鬼可以随机选择一条路径巡逻
重新编写巡逻系统
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GhostMove : MonoBehaviour
{public GameObject[] wayPointsGos;public float speed = 0.2f;//当前在前往哪个路径点的途中private int index = 0;private Animator anim;private List<Vector3> wayPoints = new List<Vector3>();private void Awake(){anim = GetComponent<Animator>();}private void Start(){LoadAPath(wayPointsGos[Random.Range(0, 2)]);}private void FixedUpdate(){if (transform.position != wayPoints[index]){Vector2 temp = Vector2.MoveTowards(transform.position, wayPoints[index], speed);GetComponent<Rigidbody2D>().MovePosition(temp);}else{index++;if(index >= wayPoints.Count){index = 0;LoadAPath(wayPointsGos[Random.Range(0, 2)]);}}Vector2 dir = (Vector2)wayPoints[index] - (Vector2)transform.position;anim.SetFloat("DirX", dir.x);anim.SetFloat("DirY", dir.y);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.name == "Pacman"){Destroy(collision.gameObject);}}private void LoadAPath(GameObject go){wayPoints.Clear();foreach (Transform t in go.transform){wayPoints.Add(t.position);}}
}
运行程序结果如下
7.完善用巡逻来模拟AI的逻辑
添加GameManager脚本,让鬼的初始路径各不相同
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GhostMove : MonoBehaviour
{public GameObject[] wayPointsGos;public float speed = 0.2f;//当前在前往哪个路径点的途中private int index = 0;private Animator anim;private List<Vector3> wayPoints = new List<Vector3>();private Vector3 startPos;private void Awake(){anim = GetComponent<Animator>();}private void Start(){startPos = transform.position + new Vector3(0, 3, 0);//初始化路径LoadAPath(wayPointsGos[GameManager._instance.usingIndex[GetComponent<SpriteRenderer>().sortingOrder - 2]]);}private void FixedUpdate(){if (transform.position != wayPoints[index]){Vector2 temp = Vector2.MoveTowards(transform.position, wayPoints[index], speed);GetComponent<Rigidbody2D>().MovePosition(temp);}else{index++;if(index >= wayPoints.Count){index = 0;LoadAPath(wayPointsGos[Random.Range(0, wayPointsGos.Length)]);}}Vector2 dir = (Vector2)wayPoints[index] - (Vector2)transform.position;anim.SetFloat("DirX", dir.x);anim.SetFloat("DirY", dir.y);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.name == "Pacman"){Destroy(collision.gameObject);}}private void LoadAPath(GameObject go){wayPoints.Clear();foreach (Transform t in go.transform){wayPoints.Add(t.position);}wayPoints.Insert(0, startPos);wayPoints.Add(startPos);}
}
然后在GhostMove中初始化路径
//初始化路径LoadAPath(wayPointsGos[GameManager._instance.usingIndex[GetComponent<SpriteRenderer>().sortingOrder - 2]]);
运行程序结果如下
8.引入超级豆点奖励道具
在GameManager中添加生成超级豆点的代码
private void CreateSuperPacdot(){int tempIndex = Random.Range(0, pacdotGos.Count);pacdotGos[tempIndex].transform.localScale = new Vector3(3, 3, 3);pacdotGos[tempIndex].GetComponent<Pacdot>().isSuperPacdot = true;}
在Pacdot中添加吃豆人碰到超级豆点的方法
private void OnTriggerEnter2D(Collider2D collision){if(collision.gameObject.name == "Pacman"){if (isSuperPacdot){//TODO//告诉GameManager我是超级豆子而且还被吃了//让吃豆人变成超级吃豆人,可以吃鬼}Destroy(gameObject);}}
在GhostMove中添加吃了超级豆点的吃豆人碰到鬼的方法
private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.name == "Pacman"){if (GameManager._instance.isSuperPacman){//TODO//真倒霉,碰到了超级吃豆人,我要回家躲躲}Destroy(collision.gameObject);}}
9.完善超级豆点的功能
在GameManager中添加有关超级豆的一些代码
private void Start(){Invoke("CreateSuperPacdot", 10f);}public void OnEatPacdot(GameObject go){pacdotGos.Remove(go);}public void OnEatSuperPacdot(){Invoke("CreateSuperPacdot", 10f);isSuperPacman = true;FreezeEnemy();StartCoroutine("RecoverEnemy");}IEnumerator RecoverEnemy(){yield return new WaitForSeconds(3f);DisFreezeEnemy();isSuperPacman = false;}private void CreateSuperPacdot(){int tempIndex = Random.Range(0, pacdotGos.Count);pacdotGos[tempIndex].transform.localScale = new Vector3(3, 3, 3);pacdotGos[tempIndex].GetComponent<Pacdot>().isSuperPacdot = true;}private void FreezeEnemy(){binky.GetComponent<GhostMove>().enabled = false;clyde.GetComponent<GhostMove>().enabled = false;inky.GetComponent<GhostMove>().enabled = false;pinky.GetComponent<GhostMove>().enabled = false;binky.GetComponent<SpriteRenderer>().color = new Color(0.7f, 0.7f, 0.7f, 0.7f);clyde.GetComponent<SpriteRenderer>().color = new Color(0.7f, 0.7f, 0.7f, 0.7f);inky.GetComponent<SpriteRenderer>().color = new Color(0.7f, 0.7f, 0.7f, 0.7f); pinky.GetComponent<SpriteRenderer>().color = new Color(0.7f, 0.7f, 0.7f, 0.7f);}private void DisFreezeEnemy(){binky.GetComponent<GhostMove>().enabled = true;clyde.GetComponent<GhostMove>().enabled = true;inky.GetComponent<GhostMove>().enabled = true;pinky.GetComponent<GhostMove>().enabled = true;binky.GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 1);clyde.GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 1);inky.GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 1);pinky.GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 1);}
在 Pacdot中修改碰撞代码
private void OnTriggerEnter2D(Collider2D collision){if(collision.gameObject.name == "Pacman"){if (isSuperPacdot){GameManager._instance.OnEatPacdot(gameObject);GameManager._instance.OnEatSuperPacdot();Destroy(gameObject);}else{GameManager._instance.OnEatPacdot(gameObject);Destroy(gameObject);}}}
在 GhostMove中修改碰撞代码
private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.name == "Pacman"){if (GameManager._instance.isSuperPacman){transform.position = startPos - new Vector3(0, 3, 0);index = 0;}else{Destroy(collision.gameObject);} }}
运行程序,结果如下
10.设计UI界面
11.处理准备时的倒计时动画
在GameManager中添加游戏逻辑处理
public GameObject startpanel;public GameObject gamePanel;public GameObject startCountDonwPrefab;public GameObject gameoverPrefab;public GameObject winPrefab;public AudioClip startClip;private void Start(){SetGameState(false); }public void OnStartButton(){StartCoroutine(PlayerStartCountDown());AudioSource.PlayClipAtPoint(startClip, Vector3.zero);startpanel.SetActive(false);}public void OnExitButton(){Application.Quit();}IEnumerator PlayerStartCountDown(){GameObject go = Instantiate(startCountDonwPrefab);yield return new WaitForSeconds(4f);Destroy(go);SetGameState(true);Invoke("CreateSuperPacdot", 10f);gamePanel.SetActive(true);GetComponent<AudioSource>().Play();}public void OnEatPacdot(GameObject go){pacdotGos.Remove(go);}public void OnEatSuperPacdot(){Invoke("CreateSuperPacdot", 10f);isSuperPacman = true;FreezeEnemy();StartCoroutine("RecoverEnemy");}private void SetGameState(bool state){pacman.GetComponent<PacmanMove>().enabled = state;binky.GetComponent<GhostMove>().enabled = state;clyde.GetComponent<GhostMove>().enabled = state;inky.GetComponent<GhostMove>().enabled = state;pinky.GetComponent<GhostMove>().enabled = state;}
12.UI逻辑的完善与计分面板的显示
private int pacdotNum = 0;private int nowEat = 0;public int score = 0;//更新显示private void Update(){if(nowEat == pacdotNum && pacman.GetComponent<PacmanMove>().enabled != false){gamePanel.SetActive(false);Instantiate(winPrefab);StopAllCoroutines();SetGameState(false);}if(nowEat == pacdotNum){if (Input.anyKeyDown){SceneManager.LoadScene(0);}}if (gamePanel.activeInHierarchy){remainText.text = "Remain:\n\n" + (pacdotNum - nowEat);nowText.text = "Eaten:\n\n" + nowEat;remainText.text = "Remain:\n\n" + score;}}
在合适的地方对三个参数进行添加
在GhostMove中完善游戏结束的代码
private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.name == "Pacman"){if (GameManager._instance.isSuperPacman){transform.position = startPos - new Vector3(0, 3, 0);index = 0;GameManager._instance.score += 500;}else{collision.gameObject.SetActive(false);GameManager._instance.gamePanel.SetActive(false);Instantiate(GameManager._instance.gameoverPrefab);Invoke("ReStart", 3f);} }}private void ReStart(){SceneManager.LoadScene(0);}
运行程序结果如下
13.发布游戏
Unity初级案例 - 吃豆人(Unity2017.2.0)Day 2相关推荐
- 理解siki学院吃豆人案例脚本
Gamemanager.cs(全局控制) using System.Collections; using System.Collections.Generic; using UnityEngine; ...
- Unity吃豆人敌人BFS广度(宽度)优先算法实现怪物追踪玩家寻路
本人正在努力建设自己的公众号,大家可以关注公众号,此文章最近也会上线我的公众号,公众号将免费提供大量教学Unity相关内容,除了从Unity入门到数据结构设计模式外,我还会免费分享我再游戏开发中使用的 ...
- 【历史上的今天】1 月 25 日:电子游戏起源;《吃豆人》作者出生;“蠕虫王”问世
整理 | 王启隆 透过「历史上的今天」,从过去看未来,从现在亦可以改变未来. 今天是 2022 年 1 月 25 日,在 1979 年的今天,史上发生首例机器人致死事件.美国密歇根州的罗伯特·威廉姆斯 ...
- 如何用Machinations示意图来模拟《吃豆人》的游戏机制?
下面我们来展示一下如何用Machinations 示意图来模拟一个简单游戏的机制.我们使用的案例是经典街机游戏<吃豆人>(Pac-Man),我们将会把模拟这个游戏的过程分解成六步,并在Ma ...
- AI与游戏——吃豆人(4)方法综述
这一部分先提一下一些基本的目前广泛用于游戏中的AI算法.这里最好现有点机器学习相关知识,不然可能会不知所云.后面提到具体算法我会尽量列出一些参考文献,例子也继续在吃豆人上面举例. 目前主流方法主要有, ...
- 吃豆人游戏-第12届蓝桥杯Scratch选拔赛真题精选
[导读]:超平老师计划推出Scratch蓝桥杯真题解析100讲,这是超平老师解读Scratch蓝桥真题系列的第79讲. 蓝桥杯选拔赛每一届都要举行4~5次,和省赛.国赛相比,题目要简单不少,再加上篇幅 ...
- Python游戏开发pygame模块,Python实现吃豆人,儿时的回忆
老规矩,先上效果图 这是一个吃豆人的小游戏.我们8090后这一代人肯定会碰到过.黄点是我们自己,红点就是怪物们.这是最原始版的电子游戏. 然后我们可以在随便一个地方新建一个游戏代码,利用这个包的代码, ...
- 观看5万个游戏视频后,英伟达AI学会了自己开发「吃豆人」
晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI AI学会玩游戏已经不是什么新鲜事了,无论是星际争霸还是王者荣耀,AI的水平都已经超过了顶级选手. 现在,AI不仅能玩游戏,还学会了造游戏. ...
- C语言,画吃豆人剖析
接上一篇文章,很多人还是搞不清楚ptr1[-1]是怎么回事,可以看看这篇文章,看完的同学还是多转发的,让更多的人看到. 一道90%都会做错的指针题 偶然的一次机会在知乎上看到这个代码,里面涉及的C语言 ...
- FZU 2124 吃豆人 bfs
题目链接:吃豆人 比赛的时候写的bfs,纠结要不要有vis数组设置已被访问,没有的话死循环,有的话就不一定是最优解了.[此时先到的不一定就是时间最短的.]于是换dfs,WA. 赛后写了个炒鸡聪明的df ...
最新文章
- flex和box、flexbox高度自适应常见坑
- FFmpeg入门之常用命令
- vs 没有足够的内存继续执行程序_科赋内存条:韩国和台湾产的有不同?
- Lua 和 C 交互中虚拟栈的操作和遍历
- 前端学习(1186):双向数据绑定
- java程序源代码如何保存到桌面_如何编写JAVA小白第一个程序
- LintCode 795. 4种独特的路径(DFS)
- 大楼(bzoj 2165)
- python对于字典d d.get(x、y)_给定字典 d ,哪个选项对 d.get(x, y) 的描述是正确的?_学小易找答案...
- windows 2008 server 各版本功能差异
- 资深开发者告诉你“页游转手游”应注意的五大点
- 《Go语言实战》摘录:7.2 并发模式 - pool
- 当直播带货回归商品销售本质?
- 【暑期每日一题】洛谷 P5708 【深基2.习2】三角形面积
- gmail如何设置邮箱别名
- 崩溃日志保存本地log,服务器上传
- 安装宝塔远程工具流程
- ubuntu16.04安装firefox的flash播放插件
- 中标麒麟操作系统,yum安装软件时提示:“已加载插件:langpacks,无须任何处理“的解决办法
- Activity A 调用Activity B 里的方法探索