HW7

1. 智能巡逻兵

游戏设计要求:

  1. 创建一个地图和若干巡逻兵(使用动画);
  2. 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
  3. 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
  4. 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
  5. 失去玩家目标后,继续巡逻;

程序设计要求:

  1. 必须使用订阅与发布模式传消息
  2. 工厂模式生产巡逻兵

游戏玩法:

地图上会随机产生 红球Player 需要逃避巡逻兵追捕并拾起 红球 ,拾起一个计一分,被巡逻兵抓到则游戏结束。

  1. 设计Player预设

Asset Store 下载的资源:

该资源中含有 RunDie 的动作。我们将利用其来做设计我们的脚本。

Player脚本:

我们通过W、A、S、D移动 PlayerPlayer 作为一个 Publisher 发布其所在区域位置,供 Subscriber 接收。所以我们也需要设计一个 judge_sign 函数来确定 Player 的位置,若是变换区域,就要发布公告。

具体代码如下:

public class Player : MonoBehaviour
{public delegate void AnimationHandler();Animation animation;
//    public static Player instance;public AnimationClip Die;public AnimationClip Run;public AnimationClip Idle;public AnimationHandler animationHandler;public delegate void ChangeHandler();public ChangeHandler changeHandler;public int sign;    // 1, 2, 3, 4public void judge_sign(){int tempsign;if (transform.position.x < 0){if (transform.position.z > 0)tempsign = 1;elsetempsign = 3;}else{if (transform.position.z > 0)tempsign = 2;elsetempsign = 4;}if (tempsign != sign){sign = tempsign;changeHandler();}Debug.Log(sign);}public void Start(){animationHandler = PlayRun;sign = 3;changeHandler = Director.getInstance().currentController._NPCfactory.NPC1.GetComponent<NPC>().Observe;changeHandler += Director.getInstance().currentController._NPCfactory.NPC2.GetComponent<NPC>().Observe;changeHandler += Director.getInstance().currentController._NPCfactory.NPC3.GetComponent<NPC>().Observe;//     instance = this;animation = GetComponent<Animation>();}public void PlayIdle(){animation.Play(Idle.name);}public void PlayDie(){animation.Play(Die.name);}public void PlayRun(){animation.Play(Run.name);}void Update(){if (animationHandler != PlayDie){float KeyVertical = Input.GetAxis("Vertical");float KeyHorizontal = Input.GetAxis("Horizontal");Vector3 newDir = new Vector3(KeyHorizontal, 0, KeyVertical).normalized;if (Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.D)){transform.forward = Vector3.Lerp(transform.forward, newDir, 1000000);}transform.position += newDir * Time.deltaTime * 3;}animationHandler();judge_sign();if (animationHandler == PlayDie)this.enabled = false;}}
  1. 设计NPC预设

下载了和 Player 配套的资源:

里面有 Walk、Run、Attack 的动画,我们可以用此设计我们的脚本。

NPC脚本:

NPC 相对于 Player 而言复杂一些。 NPC 的移动是这样实现的:按照朝向向前 走动 ,撞到障碍物时旋转朝向,并接着按朝向向前 走动 ;而当 Player 进入 NPC 所在区域时, NPC 将往 Player 位置 跑动 ,当 Player 转移到另外区域后,重新恢复初始巡逻状态。由此可见, NPCSubscriber ,接收 Player 的公告,并依次改变自己的状态。

具体代码如下

public class NPC : MonoBehaviour
{public int sign;   //1,2,3,4Vector3 current_position;public delegate void AnimationHandler();Animation animation;public static NPC instance;public AnimationClip Attack;public AnimationClip Run;public AnimationClip Walk;public AnimationHandler animationHandler;void Start(){current_position = transform.position;instance = this;animationHandler = PlayWalk;animation = GetComponent<Animation>();}   public void Observe(){if (Director.getInstance().currentController._player.GetComponent<Player>().sign == this.sign){animationHandler = PlayCatch;}else{animationHandler = PlayWalk;}}public void PlayCatch(){transform.forward = (Director.getInstance().currentController._player.transform.position - this.transform.position).normalized;transform.position = Vector3.MoveTowards(transform.position, Director.getInstance().currentController._player.transform.position, 3 * Time.deltaTime);animation.Play(Run.name);}public void PlayWalk(){ animation.Play(Walk.name);if ((transform.position - current_position).sqrMagnitude < 0.0001)this.transform.RotateAround(transform.position, Vector3.up, Random.Range(-180, 180));current_position = transform.position;transform.position += 1.5f * Time.deltaTime * transform.forward;}public void PlayAttack(){animation.Play(Attack.name);}void Update(){animationHandler();}private void OnCollisionEnter(Collision collision){if (animationHandler != PlayAttack){this.transform.RotateAround(transform.position, Vector3.up, Random.Range(-180, 180));}if (collision.collider.gameObject == Director.getInstance().currentController._player){animationHandler = PlayAttack;transform.forward = (Director.getInstance().currentController._player.transform.position-this.transform.position).normalized;Director.getInstance().currentController._player.GetComponent<Player>().animationHandler = Director.getInstance().currentController._player.GetComponent<Player>().PlayDie;}animationHandler();}
}
  1. 设计Controller

Controller 的设计也比较简单,它负责统筹各个组件之间的关系,所以在其中我们需要设置一下几个成员变量:_NPCfactory、__director、my_NPCfactory、_player、_playground、_bonus ,并对其进行初始化、实例化。需要注意的是, NPCfactory 采用的是单例模式。

具体代码如下

public class Controller : MonoBehaviour
{public NPCFactory _NPCfactory;public Director _director;private GameObject my_NPCfactory;public GameObject _player;public GameObject _playground;public GameObject _bonus;private void Awake(){Random.InitState((int)System.DateTime.Now.Ticks);_director = Director.getInstance();_director.currentController = this;_player = Object.Instantiate(Resources.Load("Prefabs/Player", typeof(GameObject)), new Vector3(-2, 0, -2), Quaternion.identity, null) as GameObject;my_NPCfactory = new GameObject("NPC_Factory");my_NPCfactory.AddComponent<NPCFactory>();_NPCfactory = Singleton<NPCFactory>.Instance;_playground = Object.Instantiate(Resources.Load("Prefabs/Playground", typeof(GameObject)), new Vector3(5.286964f, -1.301903f, 0.5366425f), Quaternion.identity, null) as GameObject;_bonus = Object.Instantiate(Resources.Load("Prefabs/Bonus", typeof(GameObject)), new Vector3(-4, 0.5f, -4), Quaternion.identity, null) as GameObject;}}
  1. NPCFactory 只剩下一个制造 NPC 的功能了。

具体代码如下

     public class NPCFactory : MonoBehaviour{public int choose = 0;  //0 for Kinematics_actions   1 for Dynamic_actionspublic List<GameObject> used;public List<GameObject> not_used;public int score = 0;public GameObject NPC1;public GameObject NPC2;public GameObject NPC3;static int once = 1;private void Awake(){if (once == 1){NPC1 = Object.Instantiate(Resources.Load("Prefabs/NPC", typeof(GameObject)), new Vector3(-2, 0, 2), Quaternion.identity, null) as GameObject;NPC1.GetComponent<NPC>().sign = 1;NPC2 = Object.Instantiate(Resources.Load("Prefabs/NPC", typeof(GameObject)), new Vector3(2, 0, 2), Quaternion.identity, null) as GameObject;NPC2.GetComponent<NPC>().sign = 2;NPC3 = Object.Instantiate(Resources.Load("Prefabs/NPC", typeof(GameObject)), new Vector3(2, 0, -2), Quaternion.identity, null) as GameObject;NPC3.GetComponent<NPC>().sign = 4;once++;}}}```
  1. 设计bonus机制

我们的 bonus 就是一颗红球: Player 需要不断地拾取这颗红球获得加分。而由于在设计初期,我们红球的重新产生方式是完全随机的,导致有时候在同个区域能多次拾取红球。所以进行了改进:红球的位置会按照:1->2->3->4进行变换,而各区域里的位置是随机生成的。并且在红球上还安装了一个碰撞器,被 Player 碰到后就会变换位置,并且进行加分操作。

具体代码如下

public class bonus : MonoBehaviour
{public int score;int sign;    //1,2,3,4// Start is called before the first frame updatevoid Start(){score = 0;sign = 3;}// Update is called once per framevoid Update(){}private void OnCollisionEnter(Collision collision){if (collision.collider.gameObject == Director.getInstance().currentController._player) {score++;if (sign == 1){this.transform.position = new Vector3(Random.Range(0.5f, 6.5f), 0.5f, Random.Range(1.5f, 6.5f));sign = 2;}else if (sign == 2){this.transform.position = new Vector3(Random.Range(-6.5f, -0.5f), 0.5f, Random.Range(-6.5f, 0.5f));sign = 3;}else if (sign == 3){this.transform.position = new Vector3(Random.Range(0.5f, 6.5f), 0.5f, Random.Range(-6.5f, -0.5f));sign = 4;}else if (sign == 4){this.transform.position = new Vector3(Random.Range(-6.5f, -0.5f), 0.5f, Random.Range(1.5f, 6.5f));sign = 1;} }}
}
  1. 设计My_GUI

该类的主要作用就是创建 Score 的label。并且当 Player 被抓住之后显示最终得分。

具体代码如下

public class My_GUI : MonoBehaviour
{public Director _director;// Start is called before the first frame updatevoid Start(){_director = Director.getInstance();}private void OnGUI(){if (_director.currentController._player.GetComponent<Player>().animationHandler == _director.currentController._player.GetComponent<Player>().PlayDie){GUIStyle bb = new GUIStyle();   //创建GUI的格式bb.normal.background = null;bb.normal.textColor = new Color(0, 0, 0);bb.fontSize = 50;string score = _director.currentController._bonus.GetComponent<bonus>().score.ToString();score = "FinalScore: " + score;GUI.Label(new Rect(0.3f * Screen.width, 0.4f*Screen.height, 150, 35), score, bb);}else{GUIStyle bb = new GUIStyle();   //创建GUI的格式bb.normal.background = null;bb.normal.textColor = new Color(0, 0, 0);bb.fontSize = 25;string score = _director.currentController._bonus.GetComponent<bonus>().score.ToString();score = "Score: " + score;GUI.Label(new Rect(0.7f * Screen.width, 270, 150, 35), score, bb);}}
}
  1. 设计Singleton

差点忘了单例模式的模板,这是按照老师给出的资料设计的,使用到了 FindObjectOfType 来寻找一个类型的单例,并返回这个单例。

public class Singleton<T> : MonoBehaviour where T: MonoBehaviour
{protected static T instance;public static T Instance{get{if (instance == null){instance = (T)FindObjectOfType(typeof(T));if (instance == null){Debug.LogError("No instance of " + typeof(T));}}return instance;}}
}

游戏效果展示



游戏视频请见:https://github.com/yaody7/unity3d-learning/blob/master/HW7/movie/巡逻兵.mp4

Github:https://github.com/yaody7/unity3d-learning/tree/master/HW7

3D游戏设计——模型与动画相关推荐

  1. 3D游戏设计-模型与动画

    Unity 第七次作业 智能巡逻兵 运行截图 视频网址 具体模型 发布订阅模式 源代码 player_movement.cs UI.cs MonsterMove.cs Judge.cs 智能巡逻兵 提 ...

  2. 3D游戏(7)——模型与动画

    文章目录 1.智能巡逻兵 游戏设计要求 程序设计要求 友善提示1:生成 3~5个边的凸多边型 友善提示2:参考以前博客,给出自己新玩法 游戏程序设计 1.智能巡逻兵 游戏设计要求 创建一个地图和若干巡 ...

  3. 3D游戏设计读书笔记七

    3D游戏设计读书笔记七 智能巡逻兵 提交要求: 游戏设计要求: 创建一个地图和若干巡逻兵(使用动画): 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址.即每次确定下一个目标位置,用自己当前位 ...

  4. 3D游戏设计读书笔记二

    3D游戏设计读书笔记二 一.简答题 • 解释 游戏对象(GameObjects) 和 资源(Assets)的区别与联系.   GameObjects是一个具体的实例,Assets是包括诸多游戏素材的资 ...

  5. 中山大学3D游戏设计读书笔记 unity3D Note6

    本文利用订阅与发布模式实现智能巡逻兵游戏 游戏演示视频地址:http://www.iqiyi.com/w_19rxsmp5kx.html 游戏具体代码地址:https://github.com/dic ...

  6. 3D游戏设计读书笔记九

    3D游戏设计读书笔记九 本次作业五选一,我选择制作血条预制设计,要求如下: 分别使用 IMGUI 和 UGUI 实现 使用 UGUI,血条是游戏对象的一个子元素,任何时候需要面对主摄像机 分析两种实现 ...

  7. 3d游戏设计读书笔记四

    3d游戏设计读书笔记四 一.基本操作演练[建议做] 下载 Fantasy Skybox FREE, 构建自己的游戏场景 a. 在AssetStore中搜索Fantasy Skybox FREE并下载. ...

  8. 3D游戏设计和创作工具学习教程 3D Game Design Creation Tools

    语言:英语+中英文字幕(根据原英文字幕机译更准确) 大小解压后:1.94G 1280X720 mp4 三维游戏设计和创作工具 用扎实的工作流程开始开发游戏 课程获取:3D游戏设计和创作工具学习教程 3 ...

  9. 3d游戏设计读书笔记六

    3d游戏设计读书笔记六 一.改进飞碟(Hit UFO)游戏: 游戏内容要求: 按 adapter模式 设计图修改飞碟游戏 使它同时支持物理运动与运动学(变换)运动 更改原 UFO_action 类 为 ...

最新文章

  1. nodejs redis 发布订阅_SpringBoot整合Redis,怎么实现发布/订阅?
  2. OpenGL着色器基础
  3. IT常说的协议指的是什么?—Vecloud微云
  4. 7-5 考试座位号 (15 分)
  5. vue 中的nextTick
  6. 【转】C#使用GDI+制作背景颜色淡入淡出效果的按钮
  7. svn一些基本操作含义
  8. 关于中职计算机专业,关于中职学校计算机专业改革探讨
  9. canape数据导入matlab,CANape使用介绍
  10. 人类一败涂地服务器不稳定,人类一败涂地崩溃怎么办 人类一败涂地游戏崩溃解决方法一览_游侠网...
  11. 【Cinema 4D】物体路径跟随动画
  12. 第三章:顺序结构程序设计(练习题)
  13. 胶印润版液消泡剂用来胶印润版液除泡问题处理得干干净净
  14. 一封高三班主任写给大学生的信 早看的话大学就不会那么堕落
  15. Android(一)
  16. 常用颜色的RGB值及调色方法
  17. Gate使用手册(四)数据输出
  18. 【tio-websocket】2、SpringBoot整合tio-websocket-server
  19. 软件测试和开发哪个好?软件测试就业前景怎样
  20. ISO14001环境管理体系认证 具体操作流程有哪些?

热门文章

  1. 数学建模_统计回归模型的梳理与总结:逐步回归,残差检验,自相关
  2. IOS积分墙:末落贵族与新兴势力PK
  3. 【自然语言处理】【多模态】多模态综述:视觉语言预训练模型
  4. 电子邮票出售面临着两大困境
  5. Windows获取模块基地址
  6. js 事件绑定传入自定义参数
  7. 箕星药业任命罗万里任CEO;​赛诺菲成2024年巴黎奥运会和残奥会的高端合作伙伴 | 医药健闻...
  8. 关于KOT、KOL、KOC 理解
  9. #Tensorflow Process finished with exit code 3#
  10. 混凝土静力受压弹性模量试验计算公式_混凝土静力受压弹性模量试验机测试步骤...