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

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

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

[[144808]]

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

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

[[144809]]

[[144809]]

using UnityEngine;

public abstract class GameControllor : MonoBehaviour
{


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




}

[[144809]]

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

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() { }
}

[[144809]]

 

 

[[144809]]

 

 

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

 

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

 

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

 

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

 

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

 原文地址:http://www.cnblogs.com/jqg-aliang/p/4719429.html

责任编辑:王雪燕 来源: 博客园
相关推荐

2022-10-08 11:57:30

Linux内核架构

2015-06-02 04:17:44

架构设计审架构设计说明书

2015-06-02 04:34:05

架构设计

2012-05-30 09:43:45

业务逻辑层

2009-06-22 14:48:21

DRY架构设计

2014-05-19 10:08:36

IM系统架构设计

2023-04-13 08:23:28

软件架构设计

2024-09-18 09:04:33

架构模式查询

2012-06-07 10:25:35

架构设计服务层软件设计

2023-08-16 12:34:16

同步备份异步备份

2024-09-09 09:00:12

架构设计算法

2013-03-11 11:39:14

2013-05-27 10:58:28

Tumblr架构设计雅虎收购

2023-02-22 08:12:30

KafkaSender 线程

2023-09-23 12:59:45

2023-04-11 07:50:27

软件架构设计

2023-07-05 08:00:52

MetrAuto系统架构

2022-06-14 08:02:35

关系模型数据模型文档模型

2014-09-02 10:54:20

架构设计权限系统

2023-04-28 08:23:51

软件架构设计
点赞
收藏

51CTO技术栈公众号