好吧,这次的题目有点标题党之嫌,提出这个设计,是因为最近玩了鬼泣,其中有一个关卡叫做“为了自己的主人”,任务中,需要利用克洛诺斯之匙将时间变慢,便于通过激光镇。

使用克洛诺斯之匙之后,主角的行动是正常的,运走,攻击等等。而其他的如怪物,死亡特效等对象的更新都变慢了。当时我想,如何让不同的对象能够按不同频率更新呢?

在unity中,脚本按时更新的是Time.FixedUpdate,改变其速率只需要修改 Time.timeScale就行了。然而这么做非常“鲁莽”,因为这个值是全局的,所有以Time.FixedUpdate为更新的游戏对象都会受到影 响。例如实现游戏的暂停功能,很多初学者会将对象的更新使用Time.FixedUpdate,然后动态修改timeScale。这样可以将所有以 FixedUpdate为更新的游戏对象都停了。

貌似没有什么问题,然而却会影响所有以FixedUpdate更新的脚本,例如DFGUI,NGUI等。我曾经使用上面的方法,结果出了问题,就是把timeScale设为0之后,UI的监听事件竟然没反应了,当时调试很久才反应过来。

后来为了解决这个问题,以及局部对象的暂停,定义了很多变量来控制,感觉太麻烦。后来玩到鬼泣的时候,突然有了灵感,为何不自己写一个时间控制器呢?

首先要清楚需求是什么:在unity自带更新脚本的基础上设计一个时间控制器,用来控制所有对象的更新频率。

我的设计方案是这样的,写一个父类,实现Update,LateUpdate,FixedUpdate的正常更新与计时,暂停控制。然后所有需要控制更新的对象脚本继承这个控制类,复写相应的方法。

使用的时候,直接控制几个全局的静态变量就可以控制所有继承此类的游戏对象,用来实现暂停,或者局部对象的延时。这 个可以很好的扩展,你复写不同的方法就可以实现不同对象的更新频率。这个你自己发挥即可。就像鬼泣中那样,主角的行动不收时间钥匙的影响,而其他对象都会 延时。

说起来挺高大上,但是实现的代码却是很简单(我喜欢用最精简的代码来实现功能),就是使用静态变量全局控制,简单计时器,以及继承和复写。好不多说上代码:

  1. using UnityEngine;
  2. public abstract class GameControllor : MonoBehaviour
  3. {
  4. //先写一个主框架,用来声明更新的函数
  5. public abstract void FixedUpdateGame();//一个按照FixedUpdate更新的函数,当然你可以自己定义或者添加,在子类中复写就行了,注意你的需求是基于哪个更新
  6. public abstract void UpdateGame();//一个按照Update更新的函数,同上
  7. public abstract void LateUpdateGame();//一个按照LateUpdate更新的函数,同上
  8. }

using UnityEngine;

public abstract class GameControllor : MonoBehaviour
{

//先写一个主框架,用来声明更新的函数
    public abstract void FixedUpdateGame();//一个按照FixedUpdate更新的函数,当然你可以自己定义或者添加,在子类中复写就行了,注意你的需求是基于哪个更新
    public abstract void UpdateGame();//一个按照Update更新的函数,同上
    public abstract void LateUpdateGame();//一个按照LateUpdate更新的函数,同上

}

  1. using UnityEngine;
  2. public abstract class MyGameControllor : GameControllor
  3. {
  4. //为什么要写成抽象类的,因为这个控制器本身没有具体的意义,只是控制时间,而且直接控制属性就行了。
  5. private static bool isStopGame = false;//控制是否暂停
  6. public static bool IsStopGame
  7. {
  8. get { return MyGameControllor.isStopGame; }
  9. set { MyGameControllor.isStopGame = value; }
  10. }
  11. private static float gameTime = 0;//脚本更新的时间,0为正常更新,1代表1秒更新一次
  12. public static float GameTime
  13. {
  14. get { return MyGameControllor.gameTime; }
  15. set { MyGameControllor.gameTime = value; }
  16. }
  17. private static float runtime = 0;//计时器
  18. private bool IsOnTime = false;
  19. void Update()//Update更新
  20. {
  21. if (IsOnTime)
  22. {
  23. UpdateGame();
  24. }
  25. }
  26. void FixedUpdate()//FixedUpdate更新
  27. {
  28. if (IsOnTime = (IsRun()))
  29. {
  30. FixedUpdateGame();
  31. }
  32. }
  33. void LateUpdate()
  34. {
  35. if (IsOnTime)
  36. {
  37. LateUpdateGame();
  38. }
  39. }
  40. private bool LateTime()//这个判断是否到了更新的时间
  41. {
  42. if (GameTime <= 0) return true;
  43. runtime += Time.fixedDeltaTime;
  44. if (runtime >= GameTime)
  45. {
  46. runtime = 0;
  47. return true;
  48. }
  49. return false;
  50. }
  51. private bool IsRun()//判断是否暂停
  52. {
  53. if (!IsStopGame)
  54. {
  55. if (LateTime())//不是暂停时判断是否到了更新的时间
  56. {
  57. return true;
  58. }
  59. }
  60. return false;
  61. }
  62. public override void FixedUpdateGame() { }
  63. public override void UpdateGame() { }
  64. public override void LateUpdateGame() { }
  65. }

using UnityEngine;
public abstract class MyGameControllor : GameControllor
{
    //为什么要写成抽象类的,因为这个控制器本身没有具体的意义,只是控制时间,而且直接控制属性就行了。
    private static bool isStopGame = false;//控制是否暂停

public static bool IsStopGame
    {
        get { return MyGameControllor.isStopGame; }
        set { MyGameControllor.isStopGame = value; }
    }
    private static float gameTime = 0;//脚本更新的时间,0为正常更新,1代表1秒更新一次

public static float GameTime
    {
        get { return MyGameControllor.gameTime; }
        set { MyGameControllor.gameTime = value; }
    }
    private static float runtime = 0;//计时器
    private bool IsOnTime = false;

void Update()//Update更新
    {
        if (IsOnTime)
        {
            UpdateGame();

}
    }
    void FixedUpdate()//FixedUpdate更新
    {
        if (IsOnTime = (IsRun()))
        {
            FixedUpdateGame();
        }
    }

void LateUpdate()
    {
        if (IsOnTime)
        {
            LateUpdateGame();
        }

}
    private bool LateTime()//这个判断是否到了更新的时间
    {
        if (GameTime <= 0) return true;
        runtime += Time.fixedDeltaTime;
        if (runtime >= GameTime)
        {
            runtime = 0;
            return true;
        }
        return false;
    }
    private bool IsRun()//判断是否暂停
    {
        if (!IsStopGame)
        {
            if (LateTime())//不是暂停时判断是否到了更新的时间
            {
                return true;
            }
        }
        return false;
    }
    public override void FixedUpdateGame() { }
    public override void UpdateGame() { }
    public override void LateUpdateGame() { }
}

代码很简单,关键是方案和思路。怎么使用呢?所有逻辑更新的脚本继承这个MyGameControllor,然后复写你更新的方法就行了,好吧,测试一下(这是照顾一下小白):

  1. using UnityEngine;
  2. using System.Collections;
  3. public class PlayerMove : MyGameControllor {
  4. //继承MyGameControllor,并复写UpdateGame方法
  5. public void Move() {
  6. //一个简单移动的方法,用来观察测试
  7. transform.Translate(new Vector3(Random.Range(-1, 1), Random.Range(-1, 1), Random.Range(-1, 1))*Time.deltaTime);
  8. }
  9. public override void UpdateGame()
  10. {
  11. //复写UpdateGame
  12. Move();
  13. }
  14. }

最后是一个时间控制器代码,就是按下esc暂停的,代码很简单,好再给小白看一下:

  1. using UnityEngine;
  2. using System.Collections;
  3. public class SystemTimeControl : MonoBehaviour
  4. {
  5. void Update()
  6. {
  7. if (Input.GetKeyDown(KeyCode.Escape))
  8. {
  9. MyGameControllor.IsStopGame = !MyGameControllor.IsStopGame;
  10. }
  11. }
  12. }

好了,关于时间的架构设计就介绍到这了,方案简单实用,也许有更好的方法,欢迎交流。打个广告:大三软件工程专业(java方向),擅长面向对象设计,常用算法。自学js,C#,以及unity3D引擎,擅长前端开发以及系统架构优化。

作者:决晴谷

来源:51CTO

简单Unity时间架构设计(克洛诺斯之匙)相关推荐

  1. Unity应用架构设计(10)——绕不开的协程和多线程(Part 1)

    阅读目录 是否需要多线程? 协程的内部原理 小结 在进入本章主题之前,我们必须要了解客户端应用程序都是单线程模型,即只有一个主线程(Main Thread),或者叫做UI线程,即所有的UI控件的创建和 ...

  2. 视频教程-Unity网络游戏架构设计-Unity3D

    Unity网络游戏架构设计 网名:海洋,CSDN社区讲师,3D游戏引擎开发者,IT讲师,计算机图形学方向研究生,曾在浙江大学CAD&CG;国家重点实验室学习.从事IT行业15年,主导或参与了1 ...

  3. Angular.js前端简单微服务架构设计

    1.使用angular脚手架进行多项目工作区搭建* 搭建后的项目到project层,后续项目需自主配置 ng new my-workspace --create-application false 2 ...

  4. Unity应用架构设计(11)——一个网络层的构建

    对于客户端应用程序,免不了和远程服务打交道.设计一个良好的『服务层』能帮我们规范和分离业务代码,提高生产效率.服务层最核心的模块一定是怎样发送请求,虽然Mono提供了很多C#网络请求类,诸如WebCl ...

  5. Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 2)

    MVVM回顾 经过上一篇文章的介绍,相信你对MVVM的设计思想有所了解.MVVM的核心思想就是解耦,View与ViewModel应该感受不到彼此的存在. View只关心怎样渲染,而ViewModel只 ...

  6. Unity应用架构设计(9)——构建统一的 Repository

    谈到 『Repository』 仓储模式,第一映像就是封装了对数据的访问和持久化.Repository 模式的理念核心是定义了一个规范,即接口『Interface』,在这个规范里面定义了访问以及持久化 ...

  7. Unity应用架构设计(7)——IoC工厂理念先行

    一谈到 『IoC』,有经验的程序员马上会联想到控制反转,将创建对象的责任反转给工厂.IoC是依赖注入 『DI』 的核心,大名鼎鼎的Spring框架就是一个非常卓越的的控制反转.依赖注入框架.遗憾的是, ...

  8. Unity应用架构设计(6)——设计动态数据集合ObservableList

    什么是 『动态数据集合』 ?简而言之,就是当集合添加.删除项目或者重置时,能提供一种通知机制,告诉UI动态更新界面.有经验的程序员脑海里迸出的第一个词就是 ObservableCollection.没 ...

  9. 架构设计本质-架构思维

    前言: 本篇文章结合多数人在工作中的模块开发,架构设计情况,以及相关权威性文章和书籍,总结下如何在开发过程中,慢慢养成架构思维,共设计以下几个方面: 正文: 简单介绍下架构设计: 软件架构是一个系统的 ...

最新文章

  1. $.when().done().then()的用法
  2. 存储过程—导出table数据为inser sqlt语句
  3. 如何用crontab每隔1分钟执行一个命令行脚本
  4. codeblocks如何让输出结果 空格_简单讲讲如何实现两个正整数相加,然后输出这个结果...
  5. 如何计算神秘的Google Adwords 品质分数– 提升到10分神的境界
  6. Winform导入文件
  7. python学习笔记(对象)
  8. 高性能的“流水线技术”网页
  9. python基本词汇的特点_Python 爬完评论只会做词云?情感分析了解一下
  10. mysql 面试题 总结
  11. java 自定义列表_自定义列表标签
  12. 谈谈自信,为什么自信是成功的第一秘诀?
  13. for循环后面的分号
  14. 单自由度振动系统 matlab,单自由度系统的振动及matlab分析
  15. 《人人都能玩赚ChatGPT》:一份简明易懂的 ChatGPT 技术指南
  16. iframe 无刷新图片上传图片
  17. 无需剪辑软件,教你简单快速进行剪辑视频
  18. 清华计算机系校服,北大清华(清华大学各系校服)
  19. 默默前行的livego--基于go语言的rtmp直播服务器
  20. 一个完整网页制作的实例积累

热门文章

  1. Java 多维数组遍历
  2. Shell教程(五):替代、引用机制、输入输出重定向
  3. 编程之美-最大公约数问题方法整理
  4. Spring MVC 4.1 支持jsonp
  5. 团队项目个人进展——Day08
  6. 海西数据获评优秀服务器租用服务商奖项
  7. Cisco BFD双向转发检测技术部署案例
  8. asp.net MVC iis6 虚拟主机兼容开发方式
  9. nginx+passenger下504 Gateway-Timeout问题的解决办法
  10. javascript的self和this使用小结