3d游戏设计读书笔记四

一、基本操作演练【建议做】

  1. 下载 Fantasy Skybox FREE, 构建自己的游戏场景
    a. 在AssetStore中搜索Fantasy Skybox FREE并下载。

    b. unity添加天空盒有两种方法,分别为向场景添加和向摄像机添加。首先我们在assert里面导入skybox素材。
    (1)向camera里导入:
    点击camera或者daomain camera,再点击component,选renderin,点skybox.再inspector里面会成这样,注意,第一个框框必须是skybox。然后在第二个框框里面导入素材。
    (2)向scene里导入:
    旧版:
    在edit里点render setting即可。再在红框框处选择。
    scene里面添加skybox什么时候都可以看到,camera只有在该摄像机里面可以看到。
    新版:
    在 window菜单下的lighting,找到Environment选项,天空盒和雾效等等都在里面

c. 在场景中添加地形并画出路、草、树、房子。这些材料都可以在AssetStore中找到。


ps:理解天空盒子(Understanding skybox)

天空盒是一个全景视图,分为六个纹理,表示沿主轴(上,下,左,右,前,后)可见的六个方向的视图。如果天空盒被正确的生成,纹理图像会在边缘无缝地拼接在一起,可以在内部的任何方向看到周围连续的图像。全景图片会被渲染在场景中的所有其他物体后面,并旋转以匹配相机的当前方向(它不会随着相机的位置而变化,而照相机的位置总是位于全景图的中心)。因此,天空盒子是在图形硬件上以最小负载向场景添加现实性的简单方式。

  1. 写一个简单的总结,总结游戏对象的使用

Empty:空对象,常用作载体,可用来挂载脚本或作为其他游戏对象的父类
3D Object:三维实体对象,有几何属性。游戏可见的对象之一
2D Object:二维实体对象,有几何属性,游戏中可见的对象之一
Light:光源,用来营造光影效果
Audio:音频,用以创造游戏音效
Video:视频
Camera:摄像机,用以从某个视角观察游戏世界
游戏对象可通过事先创建,脚本创建,加载预设等方式进行创建,通过改变其属性实现游戏场景的切换。
游戏对象包括常规的3D和2D对象,还包括摄像机和光源等这种特殊对象。每个对象都有自己的相关属性(如材质,位置等等),还可以附加component(脚本等),对象之前也可以有附属关系,对象还可以通过脚本来创建。

二、编程实践(二选一)

牧师与魔鬼 动作分离版

【2019开始的新要求】:设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束

动作分离的原因:场记(控制器)管的事太多,不仅要处理用户交互事件,还要游戏对象加载、游戏规则实现、运动实现等等,而显得非常臃肿。一个最直观的想法就是让更多的人(角色)来管理不同方面的工作。显然,这就是面向对象基于职责的思考,例如:用专用的对象来管理运动,专用的对象管理播放视频,专用的对象管理规则。就和踢足球一样,自己踢5人场,一个裁判就够了,如果是国际比赛,就需要主裁判、边裁判、电子裁判等角色通过消息协同来完成更为复杂的工作。

该版本改进的目的:
把每个需要移动的游戏对象的移动方法提取出来,建立一个动作管理器来管理不同的移动方法。
根据原先版本,每一个可移动的游戏对象的组件都有一个Move脚本,当游戏对象需要移动时候,游戏对象自己调用Move脚本中的方法让自己移动。
而动作分离版,则剥夺了游戏对象自己调用动作的能力,建立一个动作管理器,通过场景控制器(在我的游戏中是Controllor)把需要移动的游戏对象传递给动作管理器,让动作管理器去移动游戏对象。
当动作很多或是需要做同样动作的游戏对象很多的时候,使用动作管理器可以让动作很容易管理,也提高了代码复用性。

以下版本与上一篇版本有一些不同(原先版本我只参考了一位师兄的博客,后来再次复习老师网页上的内容时,发现在类等设置上有一些出入,所以重做了一版,同时知道了如何从商店下载模型,所以模型也有改动,同时省去了一些功能),以下只讲动作分离和裁判类,其余请参考代码。

以下是老师的UML图:

新增一个ActionManager脚本和一个Judger裁判类,将UserGUI中判断游戏是否结束以及结束时的操作全部转移给Judger,将游戏中控制小船和角色移动的动作全部改为actionManager的操作(对BaseCode.cs,Control.cs,Firstcontrol.cs需要进行一点修改)。

ActionManage

public class SSAction : ScriptableObject
{public bool enable = true;public bool destroy = false;public GameObject GameObject { get; set; }public Transform Transform { get; set; }public ISSActionCallback Callback { get; set; }protected SSAction() { }// Use this for initializationpublic virtual void Start(){throw new System.NotImplementedException();}// Update is called once per framepublic virtual void Update(){throw new System.NotImplementedException();}
}public class SSMoveToAction : SSAction{public Vector3 target; // 移动目标public float speed; // 移动速度// 创建并返回动作的实例public static SSMoveToAction GetSSMoveToAction(Vector3 target, float speed){SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();action.target = target;action.speed = speed;return action;}public override void Start(){}// 在 Update 函数中用 Vector3.MoveTowards 实现直线运动public override void Update(){this.Transform.position = Vector3.MoveTowards(this.Transform.position, target, speed * Time.deltaTime);if (this.Transform.position == target){this.destroy = true;// 完成动作后进行动作回掉this.Callback.SSActionEvent(this);}}
}public class SSSequenceAction : SSAction, ISSActionCallback{public List<SSAction> sequence; public int repeat = -1;public int start = 0; // 创建并返回动作序列的实例public static SSSequenceAction GetSSSequenceAction(int repeat, int start, List<SSAction> sequence){SSSequenceAction action = ScriptableObject.CreateInstance<SSSequenceAction>();action.repeat = repeat;action.sequence = sequence;action.start = start;return action;}// 在 Update 中执行当前动作public override void Update(){if (sequence.Count == 0) return;if (start < sequence.Count){sequence[start].Update();}}// 更新当前执行的动作public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Complete, int intParam = 0, string strParam = null, Object objectParam = null) {source.destroy = false;this.start++;if (this.start >= sequence.Count){this.start = 0;if (repeat > 0) repeat--;if (repeat == 0){this.destroy = true;this.Callback.SSActionEvent(this);}}}// Use this for initializationpublic override void Start(){foreach (SSAction action in sequence){action.GameObject = this.GameObject;action.Transform = this.Transform;action.Callback = this;action.Start();}}// 执行完毕后销毁动作void OnDestroy(){foreach (SSAction action in sequence){DestroyObject(action);}}}public class SSActionManager : MonoBehaviour{private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();private List<SSAction> waitingAdd = new List<SSAction>();private List<int> waitingDelete = new List<int>();protected void Update(){foreach (SSAction action in waitingAdd){actions[action.GetInstanceID()] = action;}waitingAdd.Clear();foreach (KeyValuePair<int, SSAction> KeyValue in actions){SSAction action = KeyValue.Value;if (action.destroy){waitingDelete.Add(action.GetInstanceID()); // release action}else if (action.enable){action.Update(); // update action}}foreach (int key in waitingDelete){SSAction action = actions[key];actions.Remove(key);DestroyObject(action);}waitingDelete.Clear();}protected void Start(){ }// 执行动作public void RunAction(GameObject gameObject, SSAction action, ISSActionCallback callback){action.GameObject = gameObject;action.Transform = gameObject.transform;action.Callback = callback;waitingAdd.Add(action);action.Start();}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Complete,int intParam = 0, string strParam = null, Object objectParam = null){}
}
public class ActionManager : SSActionManager, ISSActionCallback
{private SSMoveToAction boat_move;     private SSSequenceAction char_move;     public FirstController sceneController;protected new void Start(){sceneController = (FirstController)Director.getInstance().currentSceneController;sceneController.actionManager = this;}public void moveBoat(BoatController boatCtrl, Vector3 dest, float speed){boat_move = SSMoveToAction.GetSSMoveToAction(dest, speed);this.RunAction(boatCtrl.getGameobj(), boat_move, this);}public void moveChar(MyCharacterController charCtrl,Vector3 dest, float speed){//moveable.setDestion()的功能Vector3 middle = dest;Vector3 chara = charCtrl.getGameobj().transform.position;if (dest.y < chara.y) {  // character from bank to boat,说明角色在岸上,可以上船middle.y = chara.y;}else {                                // character from boat to bank   说明角色在船上,可以上岸middle.x = chara.x;}SSAction action1 = SSMoveToAction.GetSSMoveToAction(middle, speed);SSAction action2 = SSMoveToAction.GetSSMoveToAction(dest, speed);char_move = SSSequenceAction.GetSSSequenceAction (1, 0, new List<SSAction> { action1, action2 });this.RunAction(charCtrl.getGameobj(), char_move, this);}
}

Judger

public class Judger : MonoBehaviour{void Start(){}public void judge(UserGUI userGUI,GUIStyle style,GUIStyle buttonStyle){if (userGUI.status == 1) {GUI.Label(new Rect(Screen.width/2-50, Screen.height/2-85, 100, 50), "You Lose!", style);if (GUI.Button(new Rect(Screen.width/2-70, Screen.height/2, 140, 70), "Restart", buttonStyle)) {userGUI.status = 0;userGUI.action.restart ();}} else if(userGUI.status == 2) {GUI.Label(new Rect(Screen.width/2-50, Screen.height/2-85, 100, 50), "You win!", style);if (GUI.Button(new Rect(Screen.width/2-70, Screen.height/2, 140, 70), "Restart", buttonStyle)) {userGUI.status = 0;userGUI.action.restart ();}}}
}

结果图:

我的github
运行视频

3d游戏设计读书笔记四相关推荐

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

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

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

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

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

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

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

    3D游戏设计读书笔记一 二.游戏分类与热点探索 1.使用思维导图描述游戏的分类.(游戏分类方法特别多) 2. 结合手机游戏市场的下载量与排名等数据,结合游戏分类图,描述游戏市场的热点. (1)2016 ...

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

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

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

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

  7. 3D游戏设计作业(四)

    一.下载 Fantasy Skybox FREE, 构建自己的游戏场景 1.下载Fantasy Skybox   2.创建material   3.将下载好的素材拖动到material中  4.显示效 ...

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

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

  9. 《关键对话——注意观察,如何判断对话氛围是否安全》读书笔记(四)

    <关键对话--注意观察,如何判断对话氛围是否安全>读书笔记(四) 在对话过程中,既要关注对话内容(即讨论的主题),也要观察对话气氛(即参与者的反应).越早意识到你和对方退出了对话机制,就越 ...

最新文章

  1. 基于GPUImage的美颜BeautifyFace详细注释
  2. WIN7下回收站不小心删除的文件怎么恢复,免费数据恢复软件下载
  3. go 语言系列(二)基本数据类型和操作符
  4. 过程 线 多线程 并发 同步异步
  5. 将普通文章内容替换为微信图文消息符合的内容
  6. ubuntu20.04安装MySQL、卸载MySQL命令
  7. ASP.NET2.0的控件状态和视图状态探讨
  8. 唧唧Down(B站视频下载) 彻底解决你的B站视频下载问题
  9. Java Web实战详细教程(二)第一个Java Web项目+JSP模板设置
  10. 苹果ID登陆第三方有漏洞?硬核!Gartner报告腾讯云数据库增速国内第一;“小米快递”商标注册,这是要入局物流领域?...
  11. 2022年央视315晚会曝光名单企业完整一览
  12. CHI到底是干嘛的 保证cache一致性 2.3 snoop
  13. 【win10自定义默认应用】
  14. react + ant design 实现动态合并Table表格(相同数据合并为一条)
  15. JavaScript BOM和DOM部分
  16. 会议签到web_基于Web的网络签到系统设计与实现
  17. easyrecovery2023最新版本电脑数据恢复软件特点介绍
  18. pandas----difference()
  19. 【JavaScript-内置对象】找对象,那家好,内置对象错不了,方便简单,还好用
  20. 家用计算机历史记录,怎么查上网的历史记录?

热门文章

  1. 月报|公众号 4月文章汇总
  2. 腾讯开源启动疯狂模式
  3. 读《20个月赚130亿》有感
  4. 【C++基础编程(二)】类和对象(重点)、文件操作
  5. 深度学习,使用RNN的NLP,您可以成为下一个莎士比亚吗?
  6. 1042 字符统计 (20 分)
  7. 【软件】Excel打开空白,需要在里面再次选择文件位置打开
  8. 计算机硬件有关的课程,电气、电子信息类专业计算机硬件.PDF
  9. Vue+SpringBoot,一款企业级的进销存管理系统,星标2.7k
  10. Gatsby精粹,面向未来的blog