MDD

写这篇博客技术实现倒是其次,主要想分享一下篇尾的思考。

时间缩放的概念

在游戏开发中所提到的时间缩放

我认为就是在游戏世界内做到控制时间流速的效果

经典例子:

猎天使魔女的魔女时间

鬼泣5最终boss的时间立场

dota中虚空假面的大招

如何做到

unity并未天然支持组件级别的时间缩放

其提供的Time轮询计时器只能支持全局时间缩放,这用来暂停游戏恢复游戏十分方便

但如果我们要做到每个角色都能有单独时间缩放尺度,unity的天然支持就无法做到了

所以我们需要自己精确定义游戏中的个体,并为其提供单独的时间缩放尺度。

个体级别的时间缩放控制是一个老老实实穿针引线的活,几乎没有技巧可言

在MDDSkillEngine中影响角色时间流速表现的系统如下

1.动画

2.特效

3.FSM

4.行为树

5.BuffSystem

6.角色控制器(包括寻路--其实暂时也只有寻路)

7.物理

接下来我们要做的事情就很简单了

我们需要为每一个系统指定一个PlayableSpeed

这部分代码我就不具体展示了

当每个系统有了一个PlayableSpeed以后

使用观察者模式,将一个角色的总PlayableSpeed与所有的关联系统串起来即可

类似于如下代码


blackboard.Set<VarFloat>("PlayableSpeed", 1);

blackboard.AddObserver("PlayableSpeed",CacheAction);

 public virtual void ObservingPlayableSpeed(Blackboard.Type type, Variable newValue)
        {
            if (type == Blackboard.Type.CHANGE)
            {
                VarFloat varFloat = (VarFloat)newValue;
                if (CachedAnimancer != null)
                {
                    CachedAnimancer.Playable.Speed = varFloat.Value;
                }

                if (CacheMove != null)
                {
                    CacheMove.PlayableSpeed = varFloat.Value;
                }
            }           
        }

        /// <summary>
        /// 时间缩放适配函数
        /// </summary>
        /// <param name="type"></param>
        /// <param name="newValue"></param>
        public override void ObservingPlayableSpeed(Blackboard.Type type, Variable newValue)
        {
            base.ObservingPlayableSpeed(type, newValue);
            if (type == Blackboard.Type.CHANGE)
            {
                VarFloat varFloat = (VarFloat)newValue;
                IBuffSystem buffsystem = Game.Buff.GetBuffSystem(Id.ToString());
                if (buffsystem != null)
                {
                    buffsystem.PlayableSpeed = varFloat.Value;
                }

                IFsm<Entity> fsm = Game.Fsm.GetFsm<Entity>(Id.ToString());
                fsm.PlayableSpeed = varFloat.Value;
            }
            
        }

这样我们需要控制一个角色的时间缩放只需要如下代码

//将指定实体的时间缩放参数设为0.3 
entity.blackboard.Set<VarFloat>("PlayableSpeed",0.3f);

需要注意的点

在回收个体以及与个体关联的模块的时候,一定要注意时间尺度的复原。

在制作过程产生的一个思考--不要忘记自己是在做游戏

我在给各个模块适配时间缩放的时候

卡壳在了物理模块

众所周知游戏中的物理模块就是对现实物理的模仿

而在unity中我们也无法为rigbody指定一个playablespeed

所以我就思考

一个物理效果被时间尺度所影响

在代码中如何体现

:改变了速度与重力,还要考虑能量守恒。。所以要记录影响的时间长度。。。如果整理出一个公式。。。。。。。。

很显然我在犯傻

目前来说,正确的答案应该是:按相应比例改变速度表现即可,时间尺度恢复就直接恢复速度。

如果忘记自己是在做游戏,陷入在问题本身,很容易做相当大的无用功。付出了精力,可能也无法达到一个好的游戏效果。

所以,不要忘记自己是在做游戏。


记录历程,整理思路,共享知识,分享思维。