Unity——#14 一段攻击


  这节打算新增一段攻击动画,但一般一段攻击是不够的,完整的一套平A应该要有三段或四段攻击,在以后我打算做三段攻击,这节先看看一段攻击如何实现。



  我认为现在这一层的动画状态机已经完整了,一些角色的基本动作例如走、跑、跳、翻滚都有了,不应该再往上添加动画了。所以我想把多段攻击放在一层新的状态机上,然后实现两者同时存在且互不干扰,说起来简单但做起来就不一定了。OK, Let's do it.
  首先就要新增一层Layer,在Animator的Layer里点选+号,新增一层Layer并命名为attack:


attack

  新增之后第一件事并不是直接加动画哦,而是应该点开attack右边的小齿轮:

  里面的几个属性我来解释一下:
  • Weight 这个代表当前Layer的权重值,就是如果几个Layer同时存在的话,Animator会判断当前谁的Layer的权重值最大就去执行那个Layer的状态机,如果多个Layer的权重值都是最大(最大为1),那么都执行。第一层Layer(Base Layer)的权重值一直最大且不能修改,这是为了保持至少有一个Layer得到执行(我是这么认为的)。新增Layer的权重默认为0。
  • Mask 这里它接受一个Avatar Mask,何为Avatar Mask?Avatar Mask就是一个动画遮罩图层,通过选定人形模型身体上某些部位,这些部位会在某个Layer的动画执行时覆盖其他Layer的动画。这么说可能说得不太明白哦,我们可以新建一个Avatar Mask来看看其中的究竟。在Project视图点击右键create→Avatar Mask(我命名为fullbody):

     在它的Inspector视窗里能看到Humanoid选项,点开它:
    Avatar Mask

     能看到一个人形的大致关节图,可以通过点击这些关节,来选定哪些关节是你想在动画里面发生运动的,例如如果我只选中右手:

     那么使用这个Avatar Mask的Layer它里面的动画播放时将只有右手有动作(即使动画本身是整个身体都动起来),其余部分不为所动。
  • Blending 这个是Avatar Mask的混合方式,有additive和override两个选择,分别是附加和重载的意思,重载就是我上面说的那样(只有右手活动),而附加就是跟其他Layer一起播放。
  • sync 同步层,就是让该层复刻其他层的动画,其他层可以从Source Layer 选择。这个不多做解释,因为这节用不上。
  • IK Pass 这个是开启IK通道,让OnAnimatorIK()函数调用起来,如果不勾选这个选项即使你的代码里有OnAnimatorIK()这个方法,也不会被调用。而这个方法的作用是在运行时改变动画模型本身的一些参数。在日后讲述防御的时候会用到
      那么,由于现在还没有代码实现这个权重的变化,所以我们可以先把它拉满,主要是为了测试接下来添加的动画。另外,还要给它一个Avatar Mask,不过刚才在示范时我已经创建了一个命名为fullbody的Avatar Mask,所以可以直接套用给它,在给予了Avatar Mask后,该Layer的小齿轮左边会有一个M的符号:

      然后就可以加动画了,首先先要添加一个闲置状态的动画(idle),这是必须的,因为不可能这Layer一开始就是一段攻击,那么就一直攻击出不去了。然后在添加了一个一段攻击的动画,命名为attack1hA,意思是单手攻击(1h)的第一段攻击(A)。这两者先拉Transition,如图:

      先说简单的attack1hA→idle,这个没什么好说的,当前触发这个转换的条件就是当attack1hA播放完毕后自动转回idle。
      然后到idle→attack1hA,这个就有点难度了,首先考虑Has Exit Time,这个消勾,应该不用解释为什么了:

      其次来考虑触发这个转换的条件,肯定需要一个Trigger参数,像实现跳跃和翻滚那样,那么就给它整一个,命名为attack:

      然后在这个转换的Conditions里新增这个attack:

      这时就该考虑用代码把输入和信号连接起来了:
      在PlayerInput.cs里,宣告一个bool变量命名为attack,宣告一个string变量记录触发attack的keyname。
    public string keyC;
    public bool attack;
    void Upate(){
        ...
        attack = Input.GetKeyDown(keyC);
    }

  对于keyC我设置为j,对于该用什么按键攻击并没仔细考虑,现在先测试这个Trigger能不能正常使用要紧。



  然后在ActorController.cs里将这个bool变量的attack与Trigger attack联系起来:

    void Update(){
        ...
        if (pi.attack) {
            anim.SetTrigger ("attack");
        }
    }

  现在先来看看效果哦:


  噢上帝这效果简直不堪入目,一堆bug,我们来看看现在究竟都出些啥问题:
1.完全没有了走路的动画,整个模型就在滑行
2.按空格没有任何反馈,既不能跳又不能翻滚
3.攻击随意转向
  遇到这么多问题哦肯定会慌张,感觉无从下手,都是像我这些小白常有的心态。先别急,回想一下是不是哪个环节出了问题,我沉思了一下,发现:

  可能就是这两个玩意搞得我一地鸡毛,重载嘛,全身嘛,然后在attack这个Layer的idle动画直接覆盖Base Layer的所有动画了,所以Base Layer的所有动画突然都不奏效了。那这肯定不是我想要的,怎么解决?我现在需要一个动态调节attack这个Layer的权重值的方法,只要权重值为0那么这两个玩意就不会奏效了,在我没有键入j键时,attack的权重值为0,此时就能正常播放Base Layer里的所有动画;在我键入j后,进入到attack的Layer里,此时将不能播放Base Layer里的动画,不过在攻击时不能跑跳滚也是合理的。这个该怎么实现呢?
  此时我们应该了解关于状态机的一个特点,这有助于我们去实现这个动态调节的方法。就是即使某层的的权重值为0,但它在状态机里依旧会运行,只是不会表现在角色的动画里,这个是我键入一次j的效果:

  那么我们就想,能不能这样做:当我们键入j,在进入到attack1hA的动画时,把attack这个Layer的权重值拉满,然后在attack1hA播放完毕,回到idle时,把权重值拉回0,感觉可行是不是?还能顺便把输入给锁死了。事不宜迟,马上动身!
  先在attack1hA和idle身上add Behaviour,就是FSMCallOnEnter,老招了,现在应该驾轻就熟了:


  至于怎么调节权重值,Animator给了一个方法就是Animator.SetLayerWeight(),它就只有一个Signature,那就是:
public void SetLayerWeight(int layerIndex, float weight);
  参数不难理解:

Parameters Mean
layerIndex The layer index.
weight The new layer weight.

  要注意的是,它接的是Layer的索引值,并不是Layer的名字,对于Animator的Layers,它是按索引值区分的,而这个索引值类似于数组那般,从0开始。



  像这样Base Layer的索引值就是0,attack的索引值就是1,以此类推。
  而这个函数的官方描述呢也是通俗易懂:

Description
Sets the weight of the layer at the given index.

  前面提到,Animator.SetLayerWeight()的第一个参数要求的是Layer的索引值,那么直接喂给它数字1是不好的,万一以后attack的位置改变了,这种写死的行为就会带来灾难。所以还是把这个写活好,用Layer的名字就最好,毕竟名字会改的情况不多,那么如何通过Layer的名字获得它当前的索引值呢,那就要用到Animator的另外一个函数Animator.GetLayerIndex(),这个函数也不难理解:
public int GetLayerIndex(string layerName);给它layerName,就返还指定layerName的索引值。
  至此两个要用到的函数就绪,可以动手:

    void OnAttackIdleEnter()
    {
        pi.InputEnabled = true;
        anim.SetLayerWeight (anim.GetLayerIndex ("attack"), 0);
    }

    void OnAttack1hAEnter()
    {
        pi.InputEnabled = false;
        anim.SetLayerWeight (anim.GetLayerIndex ("attack"),1.0f);   
    }

  现在我想要做就实现了,可以看看效果:



  现在恢复正常了,可以走路了,而且平A时也不能转向了,但动作有点生硬,原因就是没给到它一个向前的冲量,而且现在attack这个Layer的权重值缺少了平滑处理,不是0就是1,导致两个Layer之间的切换太过突兀:



  可以看到这个蓝条,不是满就是空的,要对其进行平滑处理,做到慢慢拉满的效果。
  除了这些问题,其实还有一些很严重的问题,那就是现在我能进行跳劈加翻滚这种逆天操作,而且还有在奔跑时键入攻击键之后键入跳跃键,会在平A完接一个翻滚。这其实都是jump和attack两个Trigger的冲突问题,这么多问题,这节应该是讲不完了,只能留到下节在逐一击破。共勉!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容