学习链接

【Creator3】实现时间倒放效果,游戏开发时间倒流的技术实现方案,时间回溯在游戏开发中如何实现,来个tenet信条玩玩_哔哩哔哩_bilibili

早上看了这个学习视频,心里挺痒的,正好有一些灵感。提前写了一些学习心得分享。


实现思路

1.使用数据结构存储状态(类似 堆栈,可根据游戏自定义设计特定数据结构)。
           使用多个栈存储所需的状态(类)。
    2.根据游戏设计记录时间轴状态规则:记录频率、记录长度、记录的内容。
    3.需要时间回溯时,不断出栈 获取上一个时间轴的数据进行重置。


如何做到只记录最近5秒内的回溯?
    1.记录一个下标值,以此作为回溯索引,这么的话是不是栈结构也无所谓了。如5秒每0.1秒分为一个下标,共有50个空间存储。当记录下标为6秒时,即60P = 10,该存储的位置为第10个位置。当读取时也是从第6秒开始逆序-1的读取,59P = 9、49P = 49······直到逆序访问到第一个空null的值(坐标为10)或者算法手动计算固定周期的长度(50个)。当记录时间为固定周期的长度2倍时(100),则索引减去前一个周期的长度(100-50)来完全使新周期取代旧周期。


如何做到长周期的回溯
    系统每隔一定的周期自动存档。当玩家需要长周期回溯时,直接读取系统的自动存档即可。


缺点:

必须针对游戏设计特定的时间回溯算法,并且回溯规则越复杂,性能消耗越大。
    如果只是针对玩家的个体进行时间回溯,那么性能消耗完全是可以接受的。但是如果想让整个场景进行回溯,算法会变得复杂与大量的性能消耗。而且这可能会因为算法的遗漏导致许多隐藏的bug。虽然有几个简单的优化策略,如只在玩家可视范围内进行信息记录或一定距离内记录回溯信息;只对特定目标如敌人、施法效果等进行距离;将需要记录的目标放在同一节点下并添加是否记录的标签(如死亡超过一定时常则不必记录)·····这些算法优化了性能,但是与时间回溯原则已经不符(游戏时间完全回溯,而不是重要的对象回溯)。
    回溯规则越复杂,性能消耗越大,这是不可避免的。具体的回溯规则还是得根据游戏需求进行定义。如果规则设定的合理,那么游戏就会显得自然。比如游戏的回溯规则比较复杂,希望做到真正意义上的回溯。如果是3D游戏,则尽量让场景简洁(有意识的不设计复杂场景,从根本上减低性能消耗),2D游戏,相对3D不会太过复杂,那么真正意义上的回溯导致的性能消耗是可以接受。设定一个规则,如玩家的时间回溯能力如果周围的对象越多,则越弱。周围对象越少,则越强(总的记录消耗控制在开发者手中,性能消耗=对象*记录消耗。根据实际场景调节这2个参数,但是总的性能消耗仍在预期内。这也是相对好些的解决方案)。需要记录的对象越多,则给每个对象记录回溯的信息空间就减少,反之,则增多。例如,玩家被允许有500点的时间回溯性能消耗(假设记录一个对象一秒钟的信息需要消耗1点的性能)。此时玩家周围有50个对象需要记录回溯信息,每个对象则可以记录最多10秒的回溯信息(50*10 = 500),那么玩家使用时间回溯能力时,可以最多回溯10秒。如果玩家周围有5个对象需要记录回溯信息,则每个对象可以记录最多100秒的回溯信息(5*100 = 500),那么玩家使用时间回溯能力时,可以最多回溯100秒。
    具体的可允许最大时间回溯性能消耗,取决于具体游戏的性能优化情况。每个固定周期更新回溯信息会增加这一时间段的系统性能压力。
    也许可以设计好系统的时间轴,将不同的性能消耗任务分配到不同的时间轴上进行。这样时间回溯可以独享固定时间片断的系统全力支持运算。其次,一个时间片断中,系统完成了该片断的任务,则剩余的运算时间可用于其他的任务(未完成的任务可按照优先级进行排序到一个存储结构中,当有剩余运算时间时则开始优先级高的任务,但任务完成时从这个存储结构中移除该任务),这样最大化利用系统。
    
    玩家角色个体时间回溯能力给人族使用比较合适,肉体比较羸弱,时间回溯能量消耗会更小。也能作为对角色死亡,空间发动的复活功能


简单的实现效果

   PS:只进行了位置信息的回溯,没有对旋转信息进行记录,所有演示视频,碰撞到物体导致旋转改变了出现bug。


代码:

使用了装饰器模式,便于后续扩展,并用一个类统一管理这些装饰器。

接口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IFunction
{void Ues();
}

接口的实体类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 基类
/// 说明:
///     包含“使用”
/// </summary>
public class FunTime : IFunction
{public void Ues(){Debug.Log("FunTime使用能力");}
}

实现了接口的抽象装饰类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// IFunction接口的抽象装饰类(保存接口的实体类,并在构造函数中进行赋值)
/// </summary>
public abstract class DecTime : IFunction
{protected IFunction decTime;public  DecTime(IFunction func){this.decTime = func;}public void Ues(){decTime.Ues();}
}

扩展了抽象装饰类的实体装饰类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//扩展了抽象装饰类的实体装饰类
//时间回溯能力
public class DecTimeBack : DecTime
{//栈·角色位置信息public Stack<Vector3> stackPos = new Stack<Vector3>();public DecTimeBack(IFunction decFun) : base(decFun){}public void Use(GameObject go){//调用父类的方法base.Ues();//调用装饰器·时间回溯方法TimeBack(go);}public void TimeBack(GameObject go){Debug.Log("时间回溯");go.transform.position = stackPos.Pop();}}

扩展了抽象装饰类的实体装饰类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//扩展了抽象装饰类的实体装饰类
//时间暂停能力
public class DecTimeStop : DecTimeBack
{public bool stop = false;public DecTimeStop(IFunction decFun) : base(decFun){}public void Use(){//调用父类的方法base.Ues();//调用装饰器·时间暂停方法TimeStop();}//时停public void TimeStop(){if (stop){Time.timeScale = 0;Debug.Log("时间静止");}else{Time.timeScale = 1;Debug.Log("时间开始流动");}}
}

实体装饰类Mgr

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 时间能力的控制总类(实体装饰类Mgr)
/// 说明:
///     时间系的每多一种变化则多一个时间装饰器来扩展
/// </summary>
public class FunTimeControl
{//时间回溯能力public DecTimeBack timeBack = new DecTimeBack(new FunTime());//时间暂停能力public DecTimeStop timeStop = new DecTimeStop(new FunTime());}

执行程序类

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Testss : MonoBehaviour
{private float speed = 5;public GameObject player;private FunTimeControl fun = new FunTimeControl();// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){Crtl();Move();}private void Crtl(){//空格·时间回溯//R·时间静止(开/关)if (Input.GetKey(KeyCode.Space)){if (fun.timeBack.stackPos.Count>0){fun.timeBack.Use(player);}}else if (Input.GetKeyDown(KeyCode.R)){Debug.Log("砸挖了朵");if (fun.timeStop.stop){fun.timeStop.stop = false;fun.timeStop.Use();}else{fun.timeStop.stop = true;fun.timeStop.Use();}}}private void Move(){//移动时记录位置信息,加入时间回溯类的栈中if (Input.GetKey(KeyCode.W)){player.transform.Translate(Vector3.forward * Time.deltaTime * speed, Space.Self);fun.timeBack.stackPos.Push(player.transform.position);}else if (Input.GetKey(KeyCode.D)){player.transform.Translate(Vector3.right * Time.deltaTime * speed, Space.Self);fun.timeBack.stackPos.Push(player.transform.position);}else if (Input.GetKey(KeyCode.A)){player.transform.Translate(Vector3.left * Time.deltaTime * speed, Space.Self);fun.timeBack.stackPos.Push(player.transform.position);}else if (Input.GetKey(KeyCode.S)){player.transform.Translate(Vector3.back * Time.deltaTime * speed, Space.Self);fun.timeBack.stackPos.Push(player.transform.position);}}}

今天又对暂时用不到的功能进行了头脑风暴,接下来的内容就留到下一次再写吧

【游戏面包屑】时间回溯·逆流吧相关推荐

  1. 【游戏面包屑】开发类职业攻略1.0

    简单的做了一个技术类的职业规划,以及一些提升能力的方式.仅供参考,具体职位的介绍可以自行查阅资料. 游戏开发工程师职业路线 职业要求(偏独立开发者) 初级游戏客户端工程师     定位:掌握基础专业能 ...

  2. 【游戏面包屑】图片自定义裁剪

    栏目介绍 本栏目主要是介绍一些游戏开发的逻辑思路以及记录可能的游戏心得.不会对排版进行追求(懒). 思路 通过给图片设定定点,并将定点按顺序连接进行裁剪,然后将裁剪获得的图片替代原图即可. 详细过程 ...

  3. 【游戏面包屑】简单的导航栏设计

    前言 为了便于UI的开发,设计了一个简单的导航栏结构.目前版本的导航栏抽象类简化了导航栏选项的事件监听.移除.后续根据需求再丰富功能.结构. 本次实例用于设计角色·技能UI窗口的左侧导航栏以及右下角的 ...

  4. 【游戏面包屑】功能:排序(过滤器)、查找(最相似)、记忆回退Esc

    通过过滤器模式实现功能:根据不同选择对数据进行针对性排序. 思路 1.获得玩家的排序选择(如类型.数量.价格等,可使用简单的按钮button组合或者下拉框等方式). 2.使用过滤器模式进行设计. 3. ...

  5. 面包屑导航:最佳实践和范例

    译文出处:http://www.cogu.cn/archives/65 本文翻译自:http://www.hongkiat.com/blog/breadcrumb-navigation-examine ...

  6. 浅析面包屑导航对网站SEO优化有哪些作用?

    众所周知,每个优化人员都知道面包屑导航对于网站来说是不可或缺的一部分,面包屑导航就是像面包一样一层一层的导航结构.能够更好的帮助用户在栏目页可以返回网站首页或者点击进入下一层内容页面,提升用户体验好感 ...

  7. java面包屑实现_在Java中实现过滤器和面包店锁

    java面包屑实现 为了了解锁的工作原理,实现自定义锁是一种好方法. 这篇文章将展示如何在Java上实现Filter和Bakery锁(自旋锁),并将它们的性能与Java的ReentrantLock进行 ...

  8. Php数组面包屑导航,thinkphp实现面包屑导航(当前位置)例子分享

    以前栏目很少,就用死办法做的(首页 -> 栏目的名字),现在栏目多了,渐渐二级栏目,三级栏目也来了,这样的方式显然不太合适,于是就改进了一下.也不难,利用一个递归函数就可以了. 使用例子: 复制 ...

  9. Crumb -面包屑状的嵌套按钮

    下载source code and demo project, and an executable in the debug folder - 70.3 KB 介绍 这么长时间以来,我一直在尝试寻找一 ...

最新文章

  1. 微信摇一摇插件ios_微信开发平台 Jeewx-Boot
  2. 载:看了你能懂几个?
  3. Doing Homework HDU - 1074
  4. 国产木乃伊走进CTO编辑部
  5. WPF学习之路由事件
  6. Strassen算法
  7. Python接口自动化实战(第二阶段)- unittest框架
  8. 联想笔记本大写提示软件_联想威6 2021款怎么样?值得买吗?下面几点或许可以帮到您...
  9. 转载 JavaScript的24条实用建议
  10. zlog 纯C日志函数库
  11. 识别车牌是什么神经网络,bp神经网络车牌识别
  12. 相信我,这些web前端技术会让你虎躯一震
  13. antv L7地图 绘制大小不受控制bug
  14. python如何模拟微信扫码登录_python 微信扫码登录故障解决
  15. 显示硬件发展与视频开发系列(6)----显示标注与视频处理单元(2):VPU
  16. uint与int的区别
  17. 基因-药物相互作用数据库 DGIdb 介绍
  18. 【LINUX驱动开发】AMG8833红外成像模块在HI3516上的应用
  19. 碟中谍5中的科技:详解“步态分析”
  20. poj3678 Katu Puzzle 【解法一】

热门文章

  1. html判定会员,会员详情查询.html
  2. 邮箱-手机账号格式如何进行正则表达式校验
  3. 方直发展冲刺港股上市:利润连增、债务高企,董事长陈专持股95%
  4. e-r数据建模-概念模型 逻辑模型 物理模型-总结
  5. vtkPropPicker拾取功能
  6. php 监听redis,php监听redis key失效触发回调事件_后端开发
  7. 剑网三游戏延迟太高卡顿进不去怎么处理?
  8. CF1324F Maximum White Subtree
  9. 你可能不知道的canvas烟花秀
  10. Js控制页面刷新(局部刷新全页面刷新)