在上次做的牧师和魔鬼的游戏中,场记基本负责了所有的工作,加载资源,移动游戏对象,很明显这样的游戏结构很难维护,很难拓展,很不面向对象,所以这次的工作就是利用工厂模式来生产动作。弥补了上次没有上船动作的缺点。


先上UML图:

UML图实在是花的丑,有空再改。

工厂模式解释:

CCAction, CCSequenceAction等就是工厂,他的产品就是SSAction,由SSActionManager统一管理。具体的动作都是继承SSAction进行自定义。这里我定义了两个动作,一个是MoveToAction 用于船的移动,因为船是直线移动同时确定终点起点,第二个是MoveAction,用于上船的运动,因为魔鬼和牧师出发的位置不一定,所以要根据具体位置进行计算重点,但是其移动的距离和方向却是确定的,再利用CCSequenceAction进行简单动作的组合。

每个SSAction都包含一个callback属性,在完成后通知动作的管理者。

值得说明的是,在编写这个游戏的过程中,我遇到了一个bug解决了两天。就是一个动作只能执行一次,下一次就不能正常的执行了。我排查了许久,终于发现是action.destroy 和 action.enable没有进行初始化。

关键代码讲解:
SSActionManager.cs

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 ac in waitingAdd){actions[ac.GetInstanceID()] = ac;}waitingAdd.Clear();foreach (KeyValuePair<int, SSAction> kv in actions) {SSAction ac = kv.Value;if (ac.destory) {waitingDelete.Add(ac.GetInstanceID());} else if (ac.enable) {ac.Update();}}foreach(int key in waitingDelete) {SSAction ac = actions[key];actions.Remove(key);DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {action.gameobject = gameobject;// just let it move relative to their fatheraction.transform = gameobject.transform;action.callback = manager;/* !!!!!!!!!!!!!!!!!!!!!!!!!!* bug happen here --20170320 2306* if this action is used twice, we need to reset* action.destory and action.enable* But this is not a good convention* -- by BowenWu*/action.destory = false;action.enable = true;waitingAdd.Add(action);action.Start();}protected void Start() {}
}

RunAction方法:

这个方法负责所有动作的执行,其他动作在需要执行的时候就调用这个方法。这个方法会将需要执行的动作放入集合中,在每个Update统一管理,调用Update。这是因为其他动作的类并没有继承MonoBehavior并不会在每帧自动执行,而这个manger是会在每帧自动执行。

waitingAdd队列:

由于动作可能在任何时候进入,同时他进入的时候并不一定会是在一帧刚好结束时,这其中情况很多,不可预料,所以将其先放入waitingAdd队列中,然后在update下一次执行时再使其加入到actions字典中。

waitingDelete队列:

当游戏规模变大时,游戏资源、对象相关的依赖性增加,如果立即销毁对象,可能导致离散引擎并发的行为之间依赖关系产生不可预知错误。所以在渲染前才删去。


以下代码为这次的内容,上次的代码也需要进行少部分改变,那些内容不是很难,如果需要的可以给我留言。
将CCActionManger和GenGameobject挂在空对象上,就可以运行啦!


SSAction.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSAction : ScriptableObject {public bool enable = true;public bool destory = false;public GameObject gameobject {get; set; }public Transform transform {get; set; }public ISSActionCallback callback {get; set;}protected SSAction () {}public virtual void Start() {throw new System.NotImplementedException();}public virtual void Update() {throw new System.NotImplementedException();}
}

SSActionManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;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 ac in waitingAdd){actions[ac.GetInstanceID()] = ac;}waitingAdd.Clear();foreach (KeyValuePair<int, SSAction> kv in actions) {SSAction ac = kv.Value;if (ac.destory) {waitingDelete.Add(ac.GetInstanceID());} else if (ac.enable) {ac.Update();}}foreach(int key in waitingDelete) {SSAction ac = actions[key];actions.Remove(key);DestroyObject(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {action.gameobject = gameobject;// just let it move relative to their fatheraction.transform = gameobject.transform;action.callback = manager;/* !!!!!!!!!!!!!!!!!!!!!!!!!!* bug happen here --20170320 2306* if this action is used twice, we need to reset* action.destory and action.enable* But this is not a good convention* -- by BowenWu*/action.destory = false;action.enable = true;waitingAdd.Add(action);action.Start();}protected void Start() {}
}

ISSActionCallback.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public enum SSActionEventType: int
{Started, Competeted
}public interface ISSActionCallback
{void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Competeted,int intParam = 0,string strParam = null,Object objectParam = null);
}

CCActionManager.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCActionManager : SSActionManager, ISSActionCallback {public CCMoveToAction boat_to_end, boat_to_begin;// simple moves used to make a sequence movepublic CCMoveAction move_up, move_down;public CCMoveToAction move_to_boat_left_begin, move_to_boat_right_begin;public CCMoveToAction move_to_boat_left_end, move_to_boat_right_end;public CCSequenceAction get_on_boat_left_begin, get_on_boat_right_begin;public CCSequenceAction get_on_boat_left_end, get_on_boat_right_end;// public CCSequenceAction get_off_boat;private float object_speed;private float boat_speed;public GenGameObjects sceneController;protected new void Start() {object_speed = 4.0f;boat_speed = 4.0f;sceneController = (GenGameObjects)SSDirector.getInstance().currentSceneController;sceneController.actionManager = this;move_up = CCMoveAction.GetSSAction(new Vector3(0, 1, 0), object_speed);move_down = CCMoveAction.GetSSAction(new Vector3(0, -1, 0), object_speed);move_to_boat_left_begin = CCMoveToAction.GetSSAction(new Vector3(-2.3f, 2, 0), object_speed);move_to_boat_right_begin = CCMoveToAction.GetSSAction(new Vector3(-1.2f, 2, 0), object_speed);move_to_boat_left_end = CCMoveToAction.GetSSAction (new Vector3 (0.7f, 2, 0), object_speed);move_to_boat_right_end = CCMoveToAction.GetSSAction (new Vector3 (1.8f, 2, 0), object_speed);get_on_boat_left_begin = CCSequenceAction.GetSSAction(0, 0, new List<SSAction> {move_up, move_to_boat_left_begin, move_down});get_on_boat_right_begin = CCSequenceAction.GetSSAction(0, 0, new List<SSAction> {move_up, move_to_boat_right_begin, move_down});get_on_boat_left_end = CCSequenceAction.GetSSAction (0, 0, new List<SSAction> {move_up,move_to_boat_left_end,move_down});get_on_boat_right_end = CCSequenceAction.GetSSAction (0, 0, new List<SSAction> {move_up,move_to_boat_right_end,move_down});boat_to_end = CCMoveToAction.GetSSAction (new Vector3 (1.7f, 0, 0), boat_speed);boat_to_begin = CCMoveToAction.GetSSAction (new Vector3 (-1.7f, 0, 0), boat_speed);}protected new void Update() {base.Update();}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null) {Debug.Log ("change back Game_state");sceneController.game_state = GenGameObjects.State.normal;// sceneController.game_state = sceneController.State.moving;}
}

CCMoveToAction.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCMoveToAction : SSAction {public Vector3 target;public float speed;public static CCMoveToAction GetSSAction(Vector3 target, float speed) {CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();action.target = target;action.speed = speed;return action;}public override void Update() {this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed * Time.deltaTime);if (this.transform.position == target) {this.destory = true;this.callback.SSActionEvent(this);}}public override void Start() {Debug.Log ("MoveToAction, target is " + target);// make move on relative cordinate}
}

CCMoveAction.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCMoveAction : SSAction {// this kind of action move towards the Vector3// but not move to a targetpublic Vector3 distance;private Vector3 target;public float speed;public static CCMoveAction GetSSAction(Vector3 distance, float speed) {CCMoveAction action = ScriptableObject.CreateInstance<CCMoveAction>();action.distance = distance;action.speed = speed;return action;}public override void Update() {this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed * Time.deltaTime);if (this.transform.position == target) {this.destory = true;this.callback.SSActionEvent(this);}}public override void Start() {target = this.transform.position + distance;Debug.Log ("on MoveAction Start!");Debug.Log ("target is :" + target);}
}

CCSequenceAction.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCSequenceAction : SSAction, ISSActionCallback {public List<SSAction> sequence;public int repeat = -1;public int start = 0;public static CCSequenceAction GetSSAction(int repeat, int start, List<SSAction> sequence) {CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();action.repeat = repeat;action.sequence = sequence;action.start = start;return action;}public override void Update() {/*if (sequence.Count == 0) return;if (start < sequence.Count) {sequence[start].Update();}*/sequence [start].Update ();}public override void Start() {Debug.Log ("on CCSequenceActionStart");// Debug.Log (this.transform.parent);foreach (SSAction action in sequence){action.gameobject = this.gameobject;action.transform = this.transform;action.callback = this;}start = 0;sequence [0].Start ();}public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null) {source.destory = false;this.start++;if (this.start >= sequence.Count) {this.start = 0;if (repeat > 0) repeat--;if (repeat == 0) {this.destory = true;this.callback.SSActionEvent(this);}} else {sequence [start].Start ();}}
}

Unity3D学习笔记(四)牧师和魔鬼游戏改进相关推荐

  1. unity3d 学习笔记四 skybox(天空盒) light(光源) halo(光晕)

    Unity3D学习笔记(四)天空.光晕和迷雾 六年前第一次接触<魔兽世界>的时候,被其绚丽的画面所折服,一个叫做贫瘠之地的地方,深深印在我的脑海里.当时在艾泽拉斯大陆还不能使用飞行坐骑,试 ...

  2. 用Unity3D实现简单的牧师与魔鬼游戏

    用Unity3D实现简单的牧师与魔鬼游戏 项目地址 牧师与魔鬼游戏 完成效果图 实现心得 游戏所使用的是MVC模式开发. 遵循的动作表为: 动作 条件 开船 船上至少有一个角色(牧师或魔鬼) 牧师在左 ...

  3. Unity3D学习笔记6——GPU实例化(1)

    文章目录 1. 概述 2. 详论 3. 参考 1. 概述 在之前的文章中说到,一种材质对应一次绘制调用的指令.即使是这种情况,两个三维物体使用同一种材质,但它们使用的材质参数不一样,那么最终仍然会造成 ...

  4. Unity3D学习笔记8——GPU实例化(3)

    文章目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1) ...

  5. Unity3D学习笔记(二、小球滚动吃金币)

    源码:键盘方向键操作小球滚动吃金币Unity3D源码 下篇:Unity3D学习笔记(三.小球跑酷) 一.颜色材质球创建  二.Plane平板创建 三.围墙 同理二,新建Cube,并调整属性,设立围墙 ...

  6. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  7. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  8. RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决)

    RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决) 参考文章: (1)RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决) (2)https://www.cnblogs. ...

  9. JSP学习笔记(四十九):抛弃POI,使用iText生成Word文档

    POI操作excel的确很优秀,操作word的功能却不敢令人恭维.我们可以利用iText生成rtf文档,扩展名使用doc即可. 使用iText生成rtf,除了iText的包外,还需要额外的一个支持rt ...

  10. Ethernet/IP 学习笔记四

    Ethernet/IP 学习笔记四 EtherNet/IP Quick Start for Vendors Handbook (PUB213R0): https://www.odva.org/Port ...

最新文章

  1. hdu4585 amp; BestCoder Round #1 项目管理(vector应用)
  2. career opportuties
  3. zookeeper应用之分布式锁
  4. bzoj4484[JSOI2015]最小表示
  5. 用python把相同名称的放在一起,python实现将具有相同名称的文件放入相应的文件夹中,把,对应,内...
  6. 什么是并发与并行?有另类举例,适用于新手
  7. Gentle.NET笔记(二)-列表示例
  8. 系统动力学软件vensim学习之lookup
  9. 经典商业模式案例第1例:校园O2O
  10. H桥和NMOS,PMOS理解
  11. Latex 温度单位命令
  12. 攻防世界-Web-练习区12题解
  13. 企业微信批量操作工具1.0
  14. Eclipse MyEclipse 代码提交时,让svn忽略classpath、target、.project
  15. JS标签选择器以及节点操作
  16. Scipy中积分的计算
  17. 地下室气味难闻,地下室车库co浓度报警一招解决!
  18. 对SQL慢查询的优化(MySQL)
  19. 焊盘、封装、电路板的创建
  20. win7计算机引用账户被锁定,win7引用的账户当前已锁定

热门文章

  1. 《Science》睡眠碎片化的机制:过度兴奋的神经元
  2. 【人生苦短,我学 Python】基础篇——初步认识(Day1)
  3. .NET Compact Framework 移动开发步步来(2)
  4. ant design vue 表格中时间戳转换成时间格式显示
  5. Failed to initialize NVML
  6. Java_文件大小单位转换_基本类型长度
  7. Lighting - UE5中的灯光练习
  8. 软件测试面试题:缺陷等级应如何划分?
  9. linux用户环境变量配置文件问题 profile 和 ~/.bashrc区别
  10. 玩转鼠标右键,只需要这两个~