第五章     游戏外包装

底层规则和单位代码的制作基本就算告一段落了,现在我们还剩下一个重要的事情要做,那就是要给自己的游戏做出一副足够受看的外包装,否则的话,难道你想让玩家去玩一个只有概念和规则,没有具体形状的骨架式游戏?

游戏外包装的工作量似乎是整个游戏里最大的一部分,分为模型代码、音效编辑、图像编辑、3D建模等等,那么我们就依次来探索这些东西的做法。

 

1、 模型代码。SAGETS一样,也有ART代码,通过对一些W3D模型的调用来表现一个物体的外观形状,但和TS不同的是,SAGE没有专门的ART.INI,而是把ART代码作为单位代码的一个模块来对待,并保存在这个单位的代码中,因此它的使用格式和第三章中提到过的所有功能模块相同,也是一个函数,拥有函数名,并占用一个模块编号。

SAGE里的外观模块函数有很多种,不同的函数带有一定的底层功能,虽然都能调用W3D来表现物体外观,但细节上略有差异,这个在遇到的时候再略加点评。

 

纵观外观模块的定义法,不难看出两个规律:一是通过不同的条件标签(ConditionState)来区分一个物体在不同状态下的外观,二是通过不同的过渡标签来创建物体在两个状态之间变形时的过程动画。因此在举例之前有必要先讲解一状态标签和过渡过程的作用原理。

 

条件标签的作用是用来标志一个物体在不同的条件下具有什么什么样的特征,而这个特征可以是第三章里提到过的武器系统、装甲系统、运动模式等,也可以是本章里将要介绍的外观摸样。因此可以这样来理解,一个单位在游戏中会受到自身动作或外界环境的影响(例如空闲动作、移动动作、开火动作、白天、夜晚、温和、雪地、健康、受伤、获得升级等等)以至于使自己处于不同的情况,因此SAGE用条件标签来作为判断物体处于不同情况的依据,每种情况都可以细分为多中条件标签的组合逻辑,因此我们可以借助对这些条件标签组合逻辑情况的判定来得知这个单位目前处于什么状态,应该显示成什么样的外观,好比一个坦克,初生的时候是正常的外观模样,而在战斗中受伤,变成红血时,外观则变成了破烂不堪的形象。

所有条件标签又分为多种类型,除了NONE表示“没有任何特别情况”(可以理解为默认情况)外,其余的标签分别如下:

1)破损阶段

DAMAGED                                                                          轻伤(黄血),生命值介于35%70%之间

REALLYDAMAGED                                                             重伤(红血),生命值介于0%35%之间

RUBBLE                                                                             尸体/残骸,生命值=0但死亡动作尚未进行完毕的时候,通常体现在有延迟死亡模块作用的情况下

2)天气时段

NIGHT                                                                                夜晚,地图编辑器里指定的一个时段

SNOW                                                                                雪地,地图编辑器里指定的一个环境

3)自身动作

MOVING                                                                             移动

ATTACKING                                                                        攻击,覆盖瞄准、开火、换弹夹等全套动作

USING_WEAPON_[X]                                                         使用武器,[X]可以取ABC,分别对应主、副、第三武器,覆盖该武器的瞄准、开火、开火间隔、换弹夹等全套动作

PREATTACK_[X]                                                                 瞄准,[X]可以取ABC,分别对应主、副、第三武器

FIRING_[X]                                                                         开火,[X]可以取ABC,分别对应主、副、第三武器

BETWEEN_FIRING_SHOTS_[X]                                        开火间隔,[X]可以取ABC,分别对应主、副、第三武器

RELOADING_[X]                                                                换弹夹,[X]可以取ABC,分别对应主、副、第三武器

RAPPELLING                                                                     下滑,借助空降绳下落,但尚未落地时(让我想起了魂斗罗)

CLIMBING                                                                          攀爬,用于贝顿越过山脊

UNPACKING                                                                       部署,用于黑客、红卫兵等开始施展技能,将工具摆设到地面上

PACKING                                                                            回收,相对上面的部署来说,是把刚才部署下的工具再收回到箱子里装起来

SPECIAL_CHEERING                                                        欢呼,本参战方战胜时部队会挥手并呐喊助威,类似RA2里的C键效果

CARRYING                                                                         搬运,用于矿车,当车上装着箱子时

PANICKING                                                                        惊恐,用于平民受到惊吓后到处乱跑

DYING                                                                                死亡过程,好像是专门配合延迟死亡模块体现死亡动作

RAISING_FLAG                                                                  升旗,似乎特指红卫兵正在占领敌人建筑的过程,好像对类似动作的所有特殊能力都有效

PARACHUTING                                                                  空降,经降落伞空降,但尚未落地时

EXPLODED_BOUNCING                                                    爆飞,被DeathType= EXPLODED的武器杀死后将被爆起来很高

EXPLODED_FLAILING                                                       爆飞到最高点后开始下落的过程

TURRET_ROTATE                                                             炮塔转动,似乎专用于坦克,但事实上很少有坦克用这个标签来体现状态

OVER_WATER                                                                   位于水面上时

FREEFALL                                                                          自由落体,不知道有啥特殊含义,似乎和空降以及爆飞后的下落都有关系

4)级别、特殊升级

VETERAN                                                                           达到老兵级别

ELITE                                                                                 达到精英级别

HERO                                                                                 达到王牌级别

WEAPONSET_PLAYER_UPGRADE                                   获得武器升级,特指通过Upgrade项目来升级

WEAPONSET_CRATEUPGRADE_ONE                             捡垃圾捡到武器第1阶升级,特指捡垃圾捡到武器升级项目时

WEAPONSET_CRATEUPGRADE_TWO                            捡垃圾捡到武器第2阶升级,捡垃圾最多能将武器升级2

WEAPONSET_VETERAN                                                   级别提高到老兵,使武器得到强化时

WEAPONSET_ELITE                                                         级别提高到精英,使武器得到强化时

WEAPONSET_HERO                                                         级别提高到王牌,使武器得到强化时

ARMORSET_CRATEUPGRADE_ONE                               捡垃圾捡到装甲第1阶升级,特指捡垃圾捡到装甲升级项目时                             

ARMORSET_CRATEUPGRADE_TWO                               捡垃圾捡到装甲第1阶升级,特指捡垃圾捡到装甲升级项目时

POWER_PLANT_UPGRADING                                          电厂升级过程中,使用时需要有PowerPlantUpdate模块支持,否则的话会报错

POWER_PLANT_UPGRADED                                           电厂升级完成后,同样需要有PowerPlantUpdate模块支持

RADAR_EXTENDING                                                         雷达升级过程中,使用时需要有RadarUpdate模块支持,否则的话会报错

RADAR_UPGRADED                                                          雷达升级完成后,同样需要有PowerPlantUpdate模块支持

5)摩托车乘员、工厂门

RIDERS_ATTACKING                                                         乘员在其内部开火时

RIDER[X]                                                                            装入不同的乘员时,需要摩托车容器的支持,[X]可取1-88个整数,分别表示8种不同的乘员装载情况

DOOR_[X]_WAITING_OPEN                                              工厂门等待打开,通常是单位生产完成时,[X]可取1-44个整数,分别表示一个工厂的4个门,每个工厂最多可以有4个门

DOOR_[X]_OPENING                                                        工厂门打开过程,通常是单位准备下线时

DOOR_[X]_WAITING_TO_CLOSE                                     工厂门等待关闭,通常是等待单位开出工厂

DOOR_[X]_CLOSING                                                         工厂门关闭过程,通常是单位已经完全开出工厂

6)建造、拆除过程

AWAITING_CONSTRUCTION                                            地基已经布置完毕,等待基地车前来建设时,完成度停滞在0%

ACTIVELY_CONSTRUCTING                                            基地车正在建设这个建筑时,完成度保持不断增长的过程中

PARTIALLY_CONSTRUCTED                                            部分建造完成,但基地车却半途撤离开时,完成度停滞在0%100%之间的某个百分比上

ACTIVELY_BEING_CONSTRUCTED                                 建造进度已达到100%,但该建筑尚未正式交付使用的时候,这是个非常短暂的过程,似乎只有几帧时间

CONSTRUCTION_COMPLETE                                          建造完成的建筑正式交付使用之后

SOLD                                                                                  拆除建筑过程中,即点下了拆除键,但尚未拆除完毕的这段时间

7)其他

JAMMED                                                                            常用于导弹出膛后开始冲刺时

RIGHT_TO_CENTER                                                         从右边向中间跑

CENTER_TO_RIGHT                                                         从中间向右边跑

LEFT_TO_CENTER                                                           从左边向中间跑

CENTER_TO_LEFT                                                           从中间向左边跑,这4个标签不知道有啥具体作用,原版将之用在了摩托车上

GARRISONED                                                                    被人驻扎之后,需要驻守容器的支持                                    

SECOND_LIFE                                                                   第二次生命时??不明白啥意思,难道原版还有重生概念?

PREORDER                                                                        预定,似乎是指给工厂类建筑预定生产计划并开始生产时,需要PreorderCreate模块的支持

CAPTURED                                                                        被捕获之后,可以是通过外部占领或心灵控制的方式来捕获,原版似乎只用在了一些中立科技建筑上

JETEXHAUST                                                                     平飞过程中,似乎专用于机场型战斗机在空中平飞时

JETAFTERBURNER                                                           弹射起飞时,似乎也只用于机场型战斗机借助弹射板起飞,但尚未进入最大平飞状态时的中间过程

LOADED                                                                             装有货物时,似乎只用于矿车不空(即装有箱子,哪怕只有一个)时                                                                              

POST_COLLAPSE                                                             倒塌过程中,原版只用于一些高塔在死亡后倒塌下来的过程

ENEMYNEAR                                                                     当有敌人靠近时,需要EnemyNearUpdate模块的支持

SPECIAL_DAMAGED                                                         受到特殊伤害时,没搞懂这个特殊伤害是啥意思

BACKCRUSHED                                                                 当背后受到撞击导致死亡时

FRONTCRUSHED                                                              当正面受到撞击导致死亡时,似乎需要CrushDie模块的支持

USER_1                                                                              用户自定义1

USER_2                                                                              用户自定义2

 

过渡过程的作用是连接两个不同情况的中间过程,也就是说,可以理解为变形金刚那样的“变形”,即从机甲状态过渡到车辆状态,或从车辆状态过渡到机甲状态。从这里可以看出,过渡过程是一个可双向的的过渡,而它也需要使用一定的标签来标示前后两个状态,但它所使用的标签最特殊,是玩家自行命名的,你可以给它命任何名称,只要调用得成功都行,如果调用失败,不会报错,但却会丢失过渡过程(就成了瞬间切换)。过渡标签是在ConditionState函数里用一个语句来定义并命名的,就像下面这个例子:

    ConditionState      = SNOW

      Model             = UARADR

      Animation         = UARADR.UARADR

      AnimationMode     = LOOP

      TransitionKey     = Amakeup                                          给这个状态定义一个过渡标签,并将之命名为Amakeup,供后面编写过渡过程时使用

End

 

    ConditionState      = SNOW SOLD

      Model             = None

      TransitionKey     = Abackout                                          定义另一个过渡标签,并将之命名为Abackout,供后面编写过渡过程时使用

End

 

    TransitionState     = Abackout Amakeup                             Abackout过渡到Amakeup的过程,即从SNOW状态过渡到SNOW SOLD状态的过程

      Model             = UARADRMK                                  过渡过程也调用一个W3D模型

      Animation         = UARADRMK.UARADRMK               并播放这个W3D模型里所包含的3D动画,点号前面表示W3D内部名称,后面表示3D动画名称

      AnimationMode     = ONCE                                            动画播放模式,ONCE表示只一次,此外还有其他模式,如无限循环、反向一次等等,这个后面遇到了再说

End

 

    TransitionState     = Amakeup Abackout                             Amakeup过渡到Abackout的过程,相对于上面一个过渡来说,这是它的反向过渡,这意味着3D动画有可能需要反过来播放

      Model             = UARADRMK

      Animation         = UARADRMK.UARADRMK               模型还是这个模型,动画也还是这个动画

      AnimationMode     = ONCE_BACKWARDS                    唯独不同的是,ONCE_BACKWARDS表示反向一次,即把整个3D动画反过来播放

      Flags             = START_FRAME_LAST                   当使用ONCE_BACKWARDS时,需要加上一句播放说明,START_FRAME_LAST表示将最后一帧作为开头来反向播放

End

 

所有动画控制如下:

AnimationMode = [播放模式]                                             所有播放模式默认的播放说明都是START_FRAME_FIRST,因此需要改变的话就要自己用Flags语句来申明

ONCE                                                      正向一次

ONCE_BACKWARDS                              反向一次,需要搭配Flags = START_FRAME_LAST语句使用

LOOP                                                      正向无限循环

LOOP_BACKWARDS                               反向无限循环,需要搭配Flags = START_FRAME_LAST语句使用

MANUAL                                                  手动控制,实际上并非是让玩家自行控制,而是由游戏中特定的过程来控制

 

Flags           = [播放说明]

START_FRAME_FIRST                          以第一帧为起始帧进行播放

START_FRAME_LAST                            以最后一帧为起始帧进行播放,事实上即便是正向播放,你也可以恶意地使用START_FRAME_FIRST来制造特定的反常效果

RANDOMSTART                                     随机选择一帧作为第一帧,剩下的按正常正向顺序播放

 

最简单的外观定义是基本式,也就是没有什么特别的定义,只需要写好基本定义的那几种情况即可发挥作用。它与运动模式没有任何关系,也就不会自动地反映出任何特殊运动表现,必须全靠人工根据不同的条件标签和过渡标签来区分状态,以做出微观定义,因此这种基本式往往被步兵、建筑或飞机采用。

  Draw = W3DModelDraw ModuleTag_XX

    OkToChangeModelColor  = Yes

 

    DefaultConditionState                                                           默认状态,不仅包含了ConditionState = NONE时的外观定义,而且还作为缺省定义给其他情况时使用

      Model               = STARF                                       使用哪个W3D模型文件

      Turret               = Turret01                                     以哪个模型块作为第一炮塔

      AltTurret             = Turret02                                     以哪个模型块作为第二炮塔,一个单位最多有两个炮塔,每个炮塔都可以发射主、副、第三武器,恐怕只有战列舰才用双炮塔

TurretPitch           = TurretEL01                                以哪个模型块作为第一炮塔上所有炮管的俯仰控制关节点

AltTurretPitch         = TurretEL02                                以哪个模型块作为第一炮塔上所有炮管的俯仰控制关节点

      WeaponFireFXBone    = PRIMARY MuzzleP                 用主武器开火时炮口FX的产生点对应哪个骨骼点,PRIMARY表示主武器,后一个是骨骼点名称的前缀,后面自动匹配数字序号

      WeaponRecoilBone    = PRIMARY BarrelP                    用主武器开火时可退缩的炮管为哪个模型块,这个语句使炮管在开炮时沿其自身的X轴负方向退缩

      WeaponMuzzleFlash   = PRIMARY MuzzleP                  用主武器开火时炮口闪光对应哪个骨骼点,原版经常做一些正交的平板放在炮口上充当闪光,不知道有啥意思

      WeaponLaunchBone    = PRIMARY MuzzleP                 用主武器开火时开火点位置对应哪个骨骼点

      WeaponFireFXBone    = SECONDARY MuzzleS           用副武器开火时炮口FX的产生点对应哪个骨骼点,SECONDARY表示副武器

      WeaponRecoilBone    = SECONDARY BarrelS              用副武器开火时可退缩的炮管为哪个模型块

      WeaponMuzzleFlash   = SECONDARY MuzzleS            用副武器开火时炮口闪光对应哪个骨骼点

      WeaponLaunchBone    = SECONDARY MuzzleS           用副武器开火时开火点位置对应哪个骨骼点

      WeaponFireFXBone    = TERTIARY MuzzleT                用第三武器开火时炮口FX的产生点对应哪个骨骼点,SECONDARY表示副武器

      WeaponRecoilBone    = TERTIARY BarrelT                   用第三武器开火时可退缩的炮管为哪个模型块

      WeaponMuzzleFlash   = TERTIARY MuzzleT                 用第三武器开火时炮口闪光对应哪个骨骼点

      WeaponLaunchBone    = TERTIARY MuzzleT               用第三武器开火时开火点位置对应哪个骨骼点

    End

 

    ConditionState        = DAMAGED                                    轻伤时的状态,由于上面用DefaultConditionState定义了缺省值,因此后面就不必全部重新定义,凡是没有定义的语句

      Model               = STARF_D                                   都将自动借用上面的缺省语句,相反,定义了的语句则会覆盖缺省值并发挥作用

    End

 

    ConditionState        = REALLYDAMAGED                       重伤时的状态

      Model               = STARF_E

    End

 

    ConditionState        = RUBBLE                                        残骸/尸体时的状态

      Model               = STARF_R

    End

 

  End

特别需要注意的是,任何外观模块的函数中,至少必须有DefaultConditionState(默认状态),或者ConditionState = NONE(空状态),总之两者必须有一个,而且只能有一个。从表面上看,这两个子函数的效果差不多,因为默认状态实际上在很多时候都表示“初始状态”,也就是“不具备任何标签的状态”,而这种状态正好就是空状态,所以一般情况下,你把它们混淆是没什么问题的。但是它们的作用依然有差异,因为“空”也是一个特定的状态,与其他诸如轻伤、重伤等状态的级别是平等的,自己的定义只对自己有效,而默认状态则是涵盖所有状态的最高级别,它的定义可以覆盖其他状态,因此默认状态可以给整个外观模块提供一些缺省值,以至于其他状态不需要重复地定义一些相同的语句,这样可以省不少手笔。

此外SAGE还提供一个更加省手笔的写法,称为借用法,通常用在含有组合逻辑的状态中,例如下面这个段落:

    ConditionState      = REALLYDAMAGED                          首先用正常的方法定义重伤时的外观

      Model             = UGRADR_D

      Animation         = UGRADR_D.UGRADR_D

      AnimationMode     = LOOP

      TransitionKey     = Gmakeup

    End

AliasConditionState = NIGHT REALLYDAMAGED

这里跟一个AliasConditionState语句来让NIGHT REALLYDAMAGED状态借用REALLYDAMAGED状态外观。像这种多个标签并列的参数就是我所谓的组合逻辑状态,并列的标签表示同时具备这些标签时的状态,例如这个例子里的REALLYDAMAGED表示白天+重伤,而NIGHT REALLYDAMAGED则表示夜晚+重伤。而这样的一段语句,展开之后实际上就等效于下面这个样子:

    ConditionState      = REALLYDAMAGED

      Model             = UGRADR_D

      Animation         = UGRADR_D.UGRADR_D

      AnimationMode     = LOOP

      TransitionKey     = Gmakeup

End

 

ConditionState      = NIGHT REALLYDAMAGED

      Model             = UGRADR_D

      Animation         = UGRADR_D.UGRADR_D

      AnimationMode     = LOOP

      TransitionKey     = Gmakeup

End

这就是分开写的写法,两个状态使用完全相同的语句及参数。由此可见AliasConditionState能让你节约不少篇幅。

像这样借用外观的情况,在建筑和步兵里非常常用。

 

 

SAGE在基本式的基础上又增加了一些具有特殊定义的进阶式,这些进阶式的基本定义和基本式一样,也是用不同的ConditionStateTransitionState子函数来定义,我就全部简写以表达意思,仅仅用蓝色文字来表示这种进阶式函数的特殊功能语句。

坦克通常使用W3DtankDraw函数,它的特色是可以定义履带的转动,以及当坦克处于移动过程中时,自动在车尾产生两道游戏平台默认的沙尘,目前尚不知道沙尘能否做成微观定义,让每个坦克的沙尘都不一样。

  Draw = W3DTankDraw ModuleTag_XX

    OkToChangeModelColor  = Yes

 

    DefaultConditionState

      Model               = STORM

    End

 

    ConditionState        = DAMAGED

      Model               = STORM_D

    End

 

    ConditionState        = REALLYDAMAGED

      Model               = STORM_E

    End

 

    ConditionState        = RUBBLE

      Model               = STORM_R

    End

 

    TrackMarks            = EXTnkTrack.tga                          坦克开过之后在地面上留下一条履带痕迹,这条痕迹使用哪个TGA作为贴图

    TreadAnimationRate = 2.0                                                     履带贴图的移动速度,原来履带的转动是靠移动贴图来实现的,因此专门要为坦克做一个履带贴图,这个在W3D制作里再讲

    TreadDriveSpeedFraction = 0.3                                            当本体的移动速度低于多少时,履带贴图将停止移动,不知道这里的0.30.6到底是个什么比率

    TreadPivotSpeedFraction = 0.6                                             当本体的移动速度高于多少时,履带贴图将开始旋转

  End

 

由于SAGE的物理引擎借鉴了NFS里很多运算,以至于SAGE能够做出一种TS里想都不敢想的多轮车辆,这可不仅仅是外观那么简单,而是直接体现运动方式,简直和NFS的感觉差不多,你可以让两轮或四轮后驱车辆急转弯并做出漂移动作,在地上用轮胎印记画出一个8字,同时还能看到后轮摩擦地面杨起的沙尘。因此多轮车辆一般使用W3DtruckDraw函数,它的特色是定义车轮的动作。

  Draw = W3DTruckDraw ModuleTag_XX

    OkToChangeModelColor = Yes

 

    ConditionState = NONE

      Model = AVAmbulance

    End

 

    ConditionState = REALLYDAMAGED

      Model = AVAmbulance_D

    End     

   

    ConditionState = RUBBLE

      Model = AVAmbulance_D

    End     

   

    TrackMarks = EXTireTrack.tga

    Dust = RocketBuggyDust                                                      车轮旋转时卷起的沙土,调用一个粒子系统

    DirtSpray = RocketBuggyDirtSpray                                        似乎和上面一句的作用相似,不过貌似特指沙土飞扬时候调用哪个粒子系统(恐怕是指移动过程中)

    PowerslideSpray = RocketBuggyDirtPowerSlide                   还是和上面相似,不过特指刹车时摩擦出来的沙土

    LeftFrontTireBone = Tire01                                                  左前轮对应W3D里哪个模型块

    RightFrontTireBone = Tire02                                                右前轮对应W3D里哪个模型块

    LeftRearTireBone = Tire03                                                   左后轮对应W3D里哪个模型块

    RightRearTireBone = Tire04                                                 右后轮对应W3D里哪个模型块

    TireRotationMultiplier = 0.2                                                   车轮旋转速度比率,以单位当前的移动速度为基准来决定车轮转速

    PowerslideRotationAddition = 2.5                                         刹车时车轮转速的增量,搞不懂为什么是加2.5而不是减2.5

 

SAGE以上面3种外观式为基础又衍生出了下列近阶式,基本上可以说是组合了前击中方式的特殊定义。

W3DScienceModelDraw                                                              证书式,用于一种需要获得了对应技能证书后才能看到的物体,例如原版的垃圾箱,特有RequiredScience语句

                                                                                                                使之调用一些证书,没有获得这种证书的参战方无法看到它。

W3DDependencyModelDraw                                                       加载式,用于定义类似炎黄盖特炮、炎黄广播塔之类需要加载在主体头顶上的物体,特有AttachToBoneInContainer语句

使之与主体上的某个骨骼点关联,确保其加载的位置

W3DTankTruckDraw                                                                    半轮半履带式,可以同时定义车轮和履带的转动

W3DOverlordAircraftDraw                                                           炎黄飞机式,用于定义一些带有活动粒子系统骨骼点的物体,特有ParticlesAttachedToAnimatedBones = Yes语句

使这些粒子系统能够跟随骨骼点的3D动画而运动。

W3DOverlordTruckDraw                                                              炎黄多轮车式,同上,同时也具备一般多轮车辆对车轮转动的定义

W3DOverlordTankDraw                                                               炎黄坦克式,同上,同时也具备一般坦克对履带转动的定义

W3DpoliceCarDraw                                                                      警车式,我没看出它和一般的多轮车辆有啥区别

 

下面还有一些比较专用的方式,通常用于某种特殊物体的外观定义。

光束式,所有光束激光都用这种方法来产生视觉效果。需要LaserUpdate的支持。

  Draw = W3DLaserDraw ModuleTag_XX

    Texture = EXBinaryStream32.tga                                           光束上的贴图

    NumBeams = 4                                                                     光束由多少个重叠的圆柱体构成,用于模拟激光的光晕效果

    InnerBeamWidth = 0.4                                                          内层光束(光束体)宽度

    InnerColor = R:255 G:255 B:255 A:250                                内层光束的染色效果,同样是RGB算法。最后的A似乎表示光束的透明度

    OuterBeamWidth = 1.2                                                         外层光束(光晕带)宽度

OuterColor = R:255 G:0 B:0  A:150                                    同内层光束染色效果,特别需要注意,由于内外两层是重叠的,因此相互的染色可能会发生影响

Tile = Yes                                                                              使用平铺贴图,反之则是将贴图拉伸以适合整条光束

    ScrollRate = -0.25                                                                 使贴图在光束上移动的速度,以模拟激光的动作,正值表示发射出去,负值表示吸收回来

    Segments = 20                                                                     将整条光束分割成相互独立的多少段,每段单独移动贴图,原话说,分割得越多,光束就越细腻

    ArcHeight = 30.0                                                                   光束的弯曲程度,正值表示向上弯,负值表示向下弯,但通常不使用负值

    SegmentOverlapRatio = 0.0000                                            似乎可以控制相邻分段接头处的贴图交叠效果,正值表示交叠,负值表示拉开

    TilingScalar = 0.25                                                                拉伸平铺情况,1表示不动,小于1表示收缩,大于1表示伸展

 End

 

树木式,专用用树木式来体现树木的一些特征,所有树木都用这个方式来定义

  Draw = W3DTreeDraw ModuleTag_XX

    ModelName = PTDogwod01                                                 调用哪个W3D作为树木的结构基础,仔细可以看出,树木其实是由很简单的4张正交平面加一根细圆柱体构成的

    TextureName = PTDogwod01.tga                                         表面贴图,树木基本上就全靠这个贴图来体现形状,隔远了看起来倒也不错

    DoTopple         = Yes                                                      被撞击后是否倒塌,怀疑No的话是表示竖直沉入地表,而非先倒塌然后横着沉入地表

    DoShadow         = Yes                                                    是否在地面上投射阴影

    ToppleFX         = FX_ToppleTree                                   倒塌时的FX特效

    BounceFX         = FX_OptTreeBounce                          倒塌时在地表面反弹起来的FX特效

    KillWhenFinishedToppling = Yes                                           倒塌结束后是否判为死亡

    SinkDistance     = 10                                                         下沉距离,也就是说将沉入地表以下10像素的地方然后消失

    SinkTime         = 5000                                                    下沉持续时间

  End

 

补给站式,专门定义补给站和补给堆的方式,可以体现出箱子不断不搬走,最后搬空的过程效果,需要SupplyWarehouseDockUpdate模块的支持。                                                   

  Draw = W3DSupplyDraw ModuleTag_XX

    ExtraPublicBone = SUP                                                        特殊通用骨骼点,似乎是关联着补给站上那些箱子的位置

    ConditionState = NONE

      Model = CBToxRepos

    End

    SupplyBonePrefix = SUP                                                      根据SupplyWarehouseDockUpdate里定义的箱子数量来决定隐藏一定比率箱子,若搬空则全部隐藏起来

  End

 

尾气流式,专门定义射弹体尾气流用的方式,在毒素车的射弹体里出现过,似乎效果和光束差不多。我很怀疑这个是否能做成效果最好的粒子激光。     

  Draw = W3DProjectileStreamDraw ModuleTag_XX

    Texture       = EXToxinStream.tga                                     尾气流贴图

    Width         = 1.5                                                            尾气流宽度

    TileFactor    = 2.0                                                               贴图平铺倍数

    ScrollRate    = 6.0                                                              贴图卷动速度,以模拟尾气流的喷射效果

    MaxSegments   = 14                                                           每隔多少个分段显示一次贴图效果,似乎0可以表示显示所有分段

  End

 

2、 音效编辑。好游戏总是需要优秀的听觉效果来刺激观众,因此有必要在音效方面下一定的功夫。

 

SAGE的音效比TS相对容易整理得多,因为不需要像TS那样用XCCMIXER注入AUDIO.BAG中,所以操作上来讲便宜了很多多余的步骤。

SAGE支持两种音效文件,一种是传统的8位或16PCM,也可以使用压缩过的4IMA-ADPCM,和TS一样,要求后缀名为WAV。另一种是大家求之不得的MP3,通常用于背景音乐,采样率可支持1100044000之间的任意值,位速率可支持从64256之间的一些特定值。从性价比的角度来讲,MP3肯定比WAV划算,但是我没测试过是否所有音效都能使用MP3

SAGE的音效分为单位语音、武器/环境音效、EVA语音、背景音乐4类,代码的定义法和TS大同小异,我一样举一个例子,剩下的让你们自己去看ZH的代码。

 

单位语音代码,通常存放在Data\INI\Voice.ini

AudioEvent RangerVoiceAttack

  Sounds = iranata iranatb iranatc                                                调用哪些音源,通常是WAV文件

  Control = random                                                                     播放方式,ramdom表示随机抽选一个来播放一次,单位语音通常只能random,用其他方式会显得很怪异

  Volume = 90                                                                             一般音量倍率,以音源的音量为基准,100表示100%,小于100表示减小,反之则是增大

  MinVolume = 45                                                                       最小音量倍率,同上,通常要比一般倍率的参数小

  Priority = high                                                                           优先度,可选critical(实时)、high(高)和low(低),缺省时表示中等

  Type = [类型]                                                                           播放类型,可在下面这么多种里选择搭配,当然,相互冲突的不能搭配,否则会出现怪异后果

ui                                                                                 界面型,不知道有啥作用

voice                                                                            语音型,表示单位语音,似乎没啥作用

player                                                                           单方型,只能被本方玩家听到,因此和everyone相互冲突

world                                                                            全局型,该语音不会因为摄像机远离来源而衰减音量,因此全地图上任何位置都听得到

shrouded                                                                     强制型,该语音的来源被黑雾或灰雾笼罩时,照样能发出声音

everyone                                                                     公共型,可以被所有玩家听到,因此和player相互冲突

End

 

武器/环境音效代码,通常存放在Data\INI\ SoundEffects.ini里,定义法和单位语音一模一样,某些特别的语句和参数可以在这里使用而不会显得很怪异

AudioEvent HumveeMoveStart

  Sounds      = vhumstaa vhumstab vhumstac

  Attack       =  vtoxlo1a                                                        以哪个音源作为淡入阶段

  Decay       =  vtoxlo3a                                                        以哪个音源作为淡出阶段

  Volume      = 60

  PitchShift    = -5 5                                                                 音调浮动范围,从-5+5之间升降调,缺省为0,即保持原调,这样可以使每次的音效都略有差异,显得很丰富

  Delay       = 0 500                                                                发音延迟时间,从0500毫秒之间随机取值

  VolumeShift = -10                                                                     音量变化,-10表示从发音开始到发音结束,音量将衰减10个单位(不知道是不是分贝),正值则表示增强,缺省为0,即不变

  Control     = [播放方式]                                                      播放方式,可在下面这么多种里选择搭配,当然,相互冲突的不能搭配,否则会出现怪异后果

random                                                            随机抽选并播放一次

interrupt                                                           强制中断然后播放第一个音源一次(会无视后面的音源)

loop                                                                 无至尽地循环播放第一个音源(会无视后面的音源)

all                                                                     必须将所有音源全部都播放至少一次,通常和loop搭配

  Limit        = 3                                                                      Control的参数中存在loop时,表示播放一次最多有多少个循环

  Priority      = low

  Type        = world shrouded everyone

End

 

EVA语音代码,通常存放在Data\INI\Speech.ini里。定义非常简单,仅仅调用音源,最多再设置一下类型和音量倍率即可

DialogEvent Cinx_PlaneLandStereo

  Filename = cplane03.wav                                                         调用哪个音源,从参数来看貌似可以使用MP3格式

  Volume = 100

  Type = ui                                                                                  EVA语音似乎都最多使用ui类型,通常是缺省的,不知道缺省表示什么

End

 

背景音乐代码,通常存放在Data\INI\Music.ini里,和EVA的定义法大同小异。

MusicTrack Game_CHI_03

  Filename = CHI_03.mp3

End

 

需要注意的是,SAGE的背景音乐播放方式和TS不同,TS是由平台底层的播放机功能来直接播放你定义好的这些曲目,而SAGE则需要在宏观AI里编写一系列很复杂的触发程序来播放它们,因此很多MODER发现,自己做的MOD只能替换原版音乐源,却不能自己添加。那么在后面的月光宝盒秘籍里,我将讲解如何编写宏观AI以及部分典型的任务流程。

音源的制作需要专业的音频编辑工具,MP3暂且不用考虑太多,因为一般都是直接从网上下载下来就能用,而WAV则需要处理,至少也需要转换一下格式。我推荐使用GOLDWAVE来编辑音效,这个工具使用非常简单,可以批量转换任何格式的音源,并能在转换过程中批量加入特效设置,例如批量改音量、批量增加滤波效果等等。还能完成精确的音频编辑工作,例如音效合成、剪辑。

对于使用381M决命时刻中文版为MOD基础的人来说,编辑好的音源,需要存放在\Data\Audio\Sounds\Chinese目录中。如果是以英文版为基础,则需要放到\Data\Audio\Sounds\English目录中。你也可以创建几个BIG包来分别保存它们,当然,在使用BIG保存资源的时候千万要注意路径,不能像以前使用MIX那样不管3721地随意塞进去。

 

3、 图像编辑。图像好不好,直接导致了玩家对这个游戏的第一映像好不好。要知道99 %的玩家都是小白,他们只知道看表面,根本不会去在意这个游戏的内涵到底有多深。因此你不能期望任何玩家都像资深的CNC爱好者那样来仔细品位你的作品,因此空有骨架而无外表的游戏在市场上是站不住脚的。

 

说到图像,我就想起了PhotoShop,没错,这是任何游戏都必须使用的图像编辑工具。什么,你说你做MOD就从来没用过?那不好意思,我只能说你还没入行。

以前在TS里,做一个图像都相当麻烦,因为首先需要用PhotoShop编辑PCX图片,完工之后还要用PaintShop Pro来加载调色板,然后还要用XCCMixer转换成SHP,如果是要制作多帧动画,还得用上AnimShopACDSeeFotoCanvas等等工具,累都累死人了。而现在则方便了很多,因为SAGE引擎直接就支持真彩色的图像,并支持Alpha蒙板,可以节约PhotoShop之后的所有工序。但SAGE2D图像,包括3D模型上的贴图,都只能支持TGADDS格式。在上面的教程里我们可以注意到,所有调用贴图的语句参数,后缀名都是TGA,你绝对都看不到DDS3个字,但事实上这些图像却多数是以DDS格式保存在游戏目录下,之所以还能被游戏识别,就是因为SAGEDDS图片也视为TGA对待,因此你写代码尽管全部写成TGA好了。

有人一直找机会反对我,说SAGE还是有不如TS的地方,估计就在图像方面,不知道大家有没有注意到,任何3D游戏都无法支持多帧SHP那样的动画图片,因为现在的3D引擎还不能识别GIF动画,所以绝大多数时候,2D动画方面的表现甚至还不如TS引擎那么简单自如,往往需要借助3D动画来控制2D贴图产生视觉效果,而不能直接用一张动画SHP来表现。

 

SAGE2D图像分为两种类型,一种是映射图像,另一种是贴图,前者经过申请并定义后能被其他INI调用,因此需要制作代码。后者则是图像资源,被INI3D模型调用,甚至被影射图像的定义语句调用。

定义映射图像的代码通常在MappedImages\TextureSize_512目录下,有很多个INI,事实上你也可以随意新建一个INI来保存你自己定义的映射图像。被定义过的映射图像可以作为操作栏上的图标图像、单位头像,以及游戏宏观界面上的某些图像等等。一个典型的定义如下:

MappedImage Head122_UAPOWR                                        申请一个映射图像,并为之命名,之后就可以在其他INI里调用这个名称了

  Texture = UAPOWRHead.tga                                              使用哪个TGA贴图作为其图像源

  TextureWidth = 512                                                             贴图宽度,单位为像素,这个参数必须和TGA图像源的尺寸一致,否则会发生拉伸导致变形甚至显示错误

  TextureHeight = 512                                                           贴图高度,同上

  Coords = Left:0 Top:0 Right:122 Bottom:98                        映射区域,从整张TGA的左上脚为原点开始计算,用上下左右4个顶点来选出一个小部分作为映射出来的实际图像

  Status = NONE                                                                    状态,没搞懂有啥作用,似乎很多都是NONE

End

点评:映射图像是SAGE的特色之一,而且也比较难掌握,因为EA图方便,把几十个图标全部混杂地放在一张很大的TGA上,然后用Coords语句来“挖”出各个图标生成每个映射图像的实际图像。EA自己倒是有分割工具,自动生成代码,问题是玩家没有,只能靠人工计算,怎么办呢?我想到了一个无耻的办法,那就是分开定义各个图标。

MappedImage Head122_UAPOWR

  Texture = UAPOWRHead.tga

  TextureWidth = 122

  TextureHeight = 98

  Coords = Left:0 Top:0 Right:122 Bottom:98

  Status = NONE

End

看看这样一改有啥后果。由于整张贴图的尺寸和挖的区域一样大,事实上也就是说,直接使用整张TGA的全部区域。那么你就可以把每个图标的图像资源像TS那样分开编辑了,如果图像尺寸有变化,只需要将TextureWidthTextureHeightRightBottom的值改到和TGA图像源尺寸一样大就行,根本不需要学EA那样混杂在一堆,还要慢慢地计算应该怎么挖,万一要改的话,动一张就要动全局。

 

关于TGADDS图像的编辑方法,我就不多说了,这个东西不是一两句话扯得清楚的,尤其是Alpha蒙板部分。所以我建议你最好是去买一本PhotoShop教程,先掌握了图像编辑基本方法了再说。最后做好的TGADDS图像源,需要保存到Art\Textures目录下。

 

4、 3D建模。这是3D游戏的灵魂所在,模型做得好不好,直接影响了整个游戏的大局,所以我事先建议某些急功近利的MODER,统统给我滚回去先把3DMAX学扎实了再回来看教程。

 

首先需要提的是,SAGE支持的W3D模型,是以3DMAX为基础的一种格式,具备3DMAX里的很多基本功能,但相比MAX来说并不完善,例如不支持凹凸贴图、不支持光线跟踪等等,使得做出来的模型在游戏里看起来很干瘪,像个玩具一样直白,没有任何华丽的表现。没办法,谁叫W3DEA3D游戏里的第一次尝试呢?后来EA使用了功能更近似于MAXW3X,用在CNC3里,效果就华丽了不少。

那么要想把W3D做得不像玩具,关键就在于材质和贴图技巧。你们去看看《冲击波》、《Contra》等优秀MOD里的坦克模型就知道,优秀的模型,结构并不复杂,复杂的是贴图上包含丰富的迷彩底色和上层细节装饰,甚至精致得连螺丝钉、钢板缝都看得见。关于贴图技巧和材质通道的内容,我放到后面的进阶教程里再讲,其实看完本章,你如果能做出“玩具”来,已经很不错了。

关于建模的要点,前辈已经写过帖子来讲解,我就直接以附件的形式与教程一起打包,事实上我根本不知道这部分应该如何来讲解,因为3D建模本应该属于一个游戏开发基础技能,如果连3D建模都不会,我只好怀疑你是花钱买进游戏行业来混日子的人。所以我只讲解制作过程中的一些注意事项。

在讲解之前,我建议大家尽可能地提取原版的现成资源来观察,看看人家的标准是怎么做的,千万不要想当然地去自己钻研,否则一但走错方向,就会钻进牛角尖无法自拔。

 

(1)    坐标轴向

其实我也不知道该怎么说才够详细,但是说得太严谨的话,又好像是在讲CAD,没学过机械制图的菜鸟懂不起……不如直接给一副坦克模型图来说明如何摆放模型才是正确的方向:

3DMAX的默认视窗布局如上图所示,分别是顶视、前视、左视和透视,每个视角窗口的左下脚都有红绿蓝3个箭头,分别用来指示XYZ的正方向(透视窗口中的3个箭头最容易识别)。

SAGE规定,在3DMAX的默认视窗里,顶=俯视视角,前=右侧视角,左=背后视角,同时又规定,X+为模型的正面朝向,Y+为模型的左手朝向,Z+为模型的顶面朝向。因此正确的放法,是如上图所示,将坦克的炮管口(正面)朝向X轴正方向,这和机械工业制图的习惯正好逆时针转了个90度,在实际制作模型时必须特别小心,否则做出来的坦克会像螃蟹一样“横行”霸道。

SAGE还有一些重要的微观轴向,尤其是对于一些可活动的模型块,如炮管的退缩、炮塔的转动,它们的微观轴向就显得尤为重要,如果胡乱设置的话,在游戏中会发生错误的动向或转向。必须注意的是,炮管的微观X+方向必须是从炮尾指向炮口的方向。炮塔的微观Z轴必须与世界坐标的Z轴一致。以上两点不太容易说清楚,请各位读者导入原版ZH的战神坦克模型去看看炮管和炮塔的微观轴向,自然就明了了。

 

(2)    模型的位置和尺寸

3DMAX里的XY平面相当于游戏里的“地面”,因此模型的底面必须正好落在XY平面上,否则在游戏里会出现“浮空”或“沉地”的怪现象。而模型的前后左右位置则需要从顶视图里来观察,通常坦克以底盘的前后左右4条边界线为标准,建筑以地基板的前后左右4条边界线为标准,人物以脊椎骨骼为基准来计算其中心点位置。以上图的灰熊坦克为例,炮管不属于底盘部件,虽然它长出那么多一截,但不应该参与中心点的计算,因此我们只使用车身来作为计算来源。正确的中心点可以确保车身在XY方向上满足,正向最远点的坐标与负向最远点的坐标值几乎相等。那么放到游戏中去的话,灰熊坦克基本上就在其血格范围之内,而不会偏离得太远。

中心点放好之后,还需要设置模型的尺寸,首先我们要在INI里定义一个单位的理论尺寸作为标准参考值,以它来调整模型的实际尺寸,使模型的实际尺寸尽可能接近理论尺寸但不要大于理论尺寸。而尺寸同样也是只使用底盘作为标准来进行计算,炮管是不参与计算的。假设我们定义灰熊坦克的主半径(X)为15,次半径(Y)为10的话,那么我们就要用整体缩放法在3DMAX里控制模型的底盘尺寸尽可能地逼近30X20,但不要超过30X20

 

(3)    关节点

或许一提到关节点,有点经验的读者会立刻联想到士兵模型。其实不仅仅是士兵,坦克和建筑模型模型里照样存在关节点,上图中的左视图可以看到履带中央有两个绿色的小方格,这就是关节点,当坦克在移动时,它们将控制狼烟粒子系统的发射点位置。而透视图中的炮管口上也有一个绿色小方格,这个小方格的意义最重要,它控制着开火点的位置,其微观X+方向还同时决定了射弹体的出射方向。看到这里,或许很多人要开始高兴了——确实,SAGE不需要再像TS那样茫然而又麻烦地调整FireFLH值,你只需要在适当的地方放一个关节点就能直观地控制开火点位置和方向。

当然还不能高兴得太早。关节点不光要放置在模型里,还必须注意INI里对它的调用,前面在讲外观模块时明确提到WeaponLaunchBone等语句的含义,其最后一个参数就是关节点在3DMAX里的名称。返回外观模块定义去看,你还能发现有似乎调用并不是严格和关节点同名,例如:

WeaponLaunchBon = PRIMARY MuzzleP                                                             主武器的开火点位置由一个名称为MuzzleP的关节点来控制

但在实际模型中,你却找不到MuzzleP这个关节点,只找得到MuzzleP01MuzzleP02MuzzleP03……等等带数字后缀的关节点。事实上,这也是一种特殊的、被游戏认可的“同名”规则,专业称呼为[BoneName]%02d,即INI里只调用前缀,实际关节点的命名可在前缀字段后加两位数字,那么凡是前缀和INI对应上的所有关节点都将作为开火点,于是会形成一种“每个开火点轮流开一炮”的现象。此现象在原版炎黄坦克里出现过,大家可以导入进来看看,和INI对照起来分析,看看我说得是不是如此。

要放置新的关节点,可以使用球体、方块和骨骼等实体,也可以使用点、灯光、辅助物等虚体,两者需要设置不同的输出方式。

选中一个实体或虚体,在W3D Tools脚本功能栏里可以察看它的输出方式,分为Export Transform(仅输出定位信息)和ExportGeometry(仅输出形体图像)两种方式。3DMAX的默认情况为,实体的两个选项都被钩上,表示既输出定位信息,又输出形体图像。而虚体则正好相反,两个选项都没钩,表示什么都不输出。因此如果使用实体作关节点,在输出W3D时不要忘了取消它的“Export Geometry”选项,使之不输出任何形体图像。而使用虚体作关节点时要记得钩上“Export Transform”选项,使之输出定位信息。

对于做坦克和建筑模型而言,如果你觉得这样设置很麻烦的话,我提供一个懒人专用方法:用虚体作关节点,模型做完后,全选整个模型的所有部件,统一把Export GeometryExport Transform都钩上, Geometry Option选择Normal(直接输出),这样输出的话,相当于是让所有部件都同时输出形体图像和定位信息,由于虚体本身并不存在形体图像,因此即便钩上了Export Geometry也不会输出任何东西,在游戏里就不会有异常的显示情况。

特别注意,上述这个懒人方法只适合做坦克和建筑等“整合模型”(只输出一个W3D的模型)。而对于士兵模型这种“拆分模型”(拆分为SKNSKL和动作的模型)而言,这个方法会导致巨大的定位信息冲突,会使步兵模型在游戏中显示为半静态的T字形。

 

(4)    所属色

所属色是RTS的一大特征,通常在模型的一些表面上染上不同的颜色用来表示该单位属于不同的玩家。具体做法很简单,把你希望染上所属色的部件名称改成HouseColor%02d,虽然在3DMAX里不会有任何变换,但该结构块在游戏中就会自动染上所属玩家的阵营颜色。此方法对坦克和建筑模型非常实用,但对步兵不实用,关于步兵的所属色制作,我在后面的人物制作要点里再提。

 

(5)    简模——RTS的本色

由于RTS的特殊性在于“大军团”和“多兵种”,因此一般情况下,同屏幕内容纳的多边形数必定是FPS游戏的几十到几千倍,所以我们在制作模型时,千万不能按照FPS的精模标准去制作每一个模型,经过我的实践证明,我的蓝宝1950XTX256显卡运行SAGE引擎,在ZH里同屏幕内多边形数超过10W将使游戏直接崩溃,若在5W10W之间,游戏速度会慢得不足25帧,所以你们看过原版ZH模型的话应该很清楚一个事实——通常每个模型只有几百个多边形,简陋得简直就像玩具。

与原版ZH的情况相反,历史上有一个非常著名的ZHMOD,叫《现代战争》,是我师傅QSN的杰作。这个MOD以精致和逼真著称,所有模型都是按照FPS的精模标准制作的,部分坦克模型的多边形数甚至超过了1W,这个游戏被我戏称为“只能看不能玩的军事教科书”,每一样东西你造一个出来看看外观,看看功能还可以,如果非要去玩这个游戏的话则简直是虐待自己的显卡,只要稍微多造几个坦克,直接就会要绝大多数NF系列显卡的命。

与崇尚精致和逼真的RW派作者(RealWar)相反,WC派作者(WorldCompetion)则是崇尚流畅和竞技体育,为了使游戏流畅,他们想方设法地简化模型的多边形数,很多时候为了追求流畅性,不得不干掉了一些模型上的细节表现,我个人的观点来看,这是值得的。

3DMAX有一个自带的脚本工具,多边形计数器,可以快速地计算出你的模型总共有多少个多边形。需要注意的是,3DMAX计算的多边形数,不是指物体的实际表面数,而是指三角形面数。例如长方体的一个侧面是由2个多边形组成的,而6棱柱的底面则是由6个多边形组成的,由此可以看出模型的多边形数和表面数没有固定的比例系数,但可以肯定的是,表面数越多,多边形数就必定越多。因此简化模型,实际上就是减少形体的表面数量。

    如果决定要走简模路线,那么在建模的时候就要坚持一个建模原则:尽全力使用最少的表面数来表现形体。

A、 方体:通常用来表现建筑的地板等部件,需要注意的不多,因为3DMAX在创建方体时,长宽高的分段默认就是1,总多边形数为12。若无特别的精致要求,例如倒角、圆滑等,那么长宽高的分段数要尽可能保持全1。反之如果有特别的精致要求的话,分段数能少则少,若能用2分段将就体现效果的话,就坚决不使用3分段。

B、 柱体:通常用来表现炮管等长部件,可以通过锥化或编辑网格演变成台体。这是个比较害人的形体,分段数和多边形数基本按照平方比例增减,3DMAX在创建柱体时,默认的分段情况是端面1分段、高度5分段、底面18边。总共的多边形数就是216。因此要尽可能地减少底面边数,同时高度分段只能取1。在不需要特别精致的情况下,4棱柱足够用来表现炮管。反之如果非要表现成圆柱,则12棱柱已经足够精细了。

C、锥体:和柱体的处理基本相同,事实上柱体通过网格编辑也能演变成锥体,因此这里不再冗诉。

D、球体:这是个最害人的形体,由于球体的分段数与多边形数呈三次方比例增减。3DMAX在创建球体时,默认的分段数是32分段,总共的多边形数就是960!已经远大于原版一个坦克的总多边形数了。因此无论如何要尽可能减小分段,一般来说,10分段已经足够用了,不到万不得已,切记不要使用10以上的分段数。某些时候也可以使用几何球体来代替球体绘制模型,在相同的精致程度上,几何球体的多边形数往往比球体更少,但是在编辑网格时不太容易处理,大家根据实际情况来选用吧。

E、 环体:和柱体的情况比较类似,也是平方比例增减,默认分段情况为24分段、12边,总多边形数就是576。其中分段表示底面边数,因此12分段就足够表现出圆环。边数则表示环截面的边数,通常使用4边就足够光滑了,不到万不得已不使用5边或6边。

F、 管体:这个是必须严禁使用的基本形体。事实上我们完全可以将管体做成柱体,而在贴图上画出黑洞来模拟“管口”的特殊效果。

G、 比较复杂的形体:这是需要高级建模技术才做得出来的东西,需要在各种基本形体的基础上频繁地使用网格编辑,为了减少面数,高手往往会删除原有的面,而自己重新创建新面来代替。因此我无法在这里进行讲解,你们自己去买书学3DMAX高级建模吧。

H、输出W3D时的注意事项:除非你认为你的模型实在是简陋得比ZH的玩具级别还烂,否则尽量不要钩选“Smooth Vertex Normals”,这个功能会自动修正定点和法线的光滑程度,容易在一些无关紧要的细节上平白无故地增加很多多边形数,让原版已经简化完成的模型又变成了精致模型,那我们又何必去简化呢?

 

不要忘了随时察看模型的总多边形数,为了确保游戏运行最低速度不低于30/秒,我实测了3个级别的大致简化要求,根据运行该游戏的电脑配置分别表示如下:

                     A6年前的古董电脑。即图拉丁赛阳1G或毒龙1G           MX44064显卡或R850064显卡           DDR266-256M内存。

                            多边形要求:ZH级别(玩具级别)。即坦克不超过300,建筑不超过600,士兵不超过200

                     B3年前的淘汰配置。即P4HT2.4GAMD2600+           FX5200128显卡或R9550128显卡       DDR400-512M内存

                            多边形要求:FK级别(仿真级别)。即坦克不超过1000,建筑不超过1500,士兵不超过400

                     C、主流甚至豪华配置。即CORE2.0AMD3800+            NF8400256显卡或1950XT256显卡       DDR667-1G内存

                            多边形要求:CNC3级别(工艺品级别)。即坦克不超过2000,建筑不超过4000,士兵不超过1000

                     D、如果你的配置比上面的豪华配置还高出一大截,那么你可以承受RW级别(真实级别),即现代战争那种变态的精致程度。

 

(6)    无所不能的UVW展开

没贴过图的模型结构,通常称为“裸体”,你肯定会发现,一些高手制作的模型,只看裸体根本看不出有什么特别,甚至相当简陋,但贴上图之后却显得非常逼真。事实上这就是对游戏美工的一个最高难度要求——用最简陋的结构配上最细腻的贴图,来表现出足够精致的模型,因此专业的游戏美工有一个相同的认识,即3D游戏美工,最重要、且最有技术含量的是贴图,而非结构。

贴图是3DMAX的一大基本功,但光是看书还不足以学成高级美工,而是需要花费35年时间去反复训练和提高的。可以想像,要是随便买本书来看完就可以干游戏美工工作的话,那么那么多游戏美工高手就都该饿死了。

最牛的贴图方法是UVW展开,关于这个方法,几乎99%3DMAX书本上都没有讲解,但它却是专业游戏开发中最实用的贴图方法。你可以将整个模型上各个面的图像用PS整合到一张图片上,然后贴给所有结构体,再将这些结构体的各个表面通过UVW展开,移动图片上各个合适的位置去“拼贴”,于是实际模型的表面上就会表现出具体的图像。关于UVW展开,在百度上能搜索到一些详细的教程,我收集到一个老外的金鱼视频教程作为附件,该教程详细地讲解了从0开始建模,到贴图、动画制作的全部操作过程,但由于体积巨大,因此我只能给出地址,你们自己去下载观看吧,我猜想你们在看完之后必定会汗颜——看一遍视频,胜读10年书。

http://www.086g.com/forum-cn/thread-107689-1-1.html

 

(7)    人物制作要点及W3D输出注意事项

人物是一种最特殊的模型,所有士兵模型都要用这种方式来制作。看过3DMAX动画书籍的人应该知道,人物模型中通常都含有蒙皮和骨骼这两个概念,蒙皮受到骨骼上的各个关节点的牵引而产生随动的形变,于是产生了肢体动画。这里不便于仔细讲解骨骼的制作过程,你们自己去看书。我只讲解几点制作中的注意事项。

A、 蒙皮:在制作蒙皮时,可以利用基本形体来进行网格编辑,分别制作出头、躯干、四肢、枪械武器等各个部件,然后将它们整合起来,转换成一个“可编辑网格”,作为蒙皮。当然一些3DMAX动画书籍上讲解的通常是专业方法,即建立一个长方体作基础,利用网格编辑通过复杂的手工分段、表面挤出、网格点焊接等逐步做成一个完整的人体。总之不管怎么样,能用尽量少的多边形表现出足够细腻的人体结构就行。

B、 贴图:尽可能地用PS将整个人体上所有用得到的图像都整合到一张TGA上,将它贴到蒙皮上去。贴好之后你会发现整个人体上的图像是混乱的。不要紧,只要我们对蒙皮进行UVW展开并拼贴各个表面的位置,就能将贴图和蒙皮表面对应好。

C、所属色:由于士兵的模型是蒙皮,它是一个整体,因此无法使用类似于坦克、建筑的HouseColor%02d的方法来表达所属色区域。而经常使用PS的话,不难发现32TGA是存在ALPHA通道的,这个通道通常用来区分一个TGA图像上的正常显示部分和全透明部分,即处于通道内的图像为正常显示,反之则是全透明,而通道边缘上的羽化区域则显示为半透明。因此SAGE利用TGA的这个特定来表达所属色,使士兵蒙皮上凡是出现了通道外图像的表面,统统显示为全透明。因此我们在保存士兵贴图时,一定要记得保存成32TGA,否则将不支持ALPHA通道。此外TGA的命名也有讲究,SAGE规定,只有当TGA的文件名以小写的“zhca_”开头时,贴有通道外图像的表面将显示为纯净的所属色,否则,就显示为不可见。你们去观察一下原版ZH的士兵贴图文件就明白了,所有TGA的文件名总是有个小写的zhca_开头。

D、输出潜规则:3DMAX有个不成文的规定,那就是凡是被隐藏和冻结的部件是不会产生任何输出的,因此在输出W3D时,不要忘了恢复所有部件的显示和解冻。

E、 蒙皮、骨骼、动作之间的关联:和坦克模型不同的是,士兵的蒙皮只由骨骼来控制,因此蒙皮需要和骨骼实现绑定。3DMAX可以提供两种空间扭曲用于绑定蒙皮和骨骼,分别是SKINWWSKIN,两者的用法大同小异,对于简模来说,后者更方便一些,附件里的骨骼动画制作教程里详细地讲解了如何绑定,这里就不再多说废话了。只需要严格注意以下几个要点:

(a)     蒙皮只能钩选Export Geometry,并设置Geometry OptionNormal,千万不能钩选Export Transform。因为我们只需要它的形体图像,不能让它输出定位信息,否则会和骨骼发生冲突,导致人物动作不正常

(b)     骨骼只能钩选Export Transform,千万不能钩选Export Geometry。因为我们只需要它的定位信息,不能让它输出形体图像,否则人物身上会出现一些不应该有的怪异部件

(c)     绑定时,通常可以使用Auto-Link,可以快速将蒙皮上所有定点都自动绑定到最近的关节点上,但有时候会出现一些意外,即把错误的定点绑定到错误的关节点上,导致动作怪异,因此自动绑定完之后,要手工检查一下那些最密集的定点区域,试着进入“自动关键点”模式,移动一下关节点看看是否绑定到了不该绑定的定点,如果有的话,就要进行人工处理,选择这些绑定错误的顶点,Unlink,然后Link to Bome by NameLink to Bome Selected

(d)     输出W3D时,一定要记得先输出SKL,然后才是输出SKN

在输出SKL时,要选择Skeleton输出方式。

在输出SKN时,要选择Hierarichical Model方式输出,下面还要钩选“Export Using Existing”,并选取刚才输出的SKL。如果忘了的话,会丢失SKNSKL之间的绑定,导致人物在游戏里呈现怪异动作或微动的T字形。

动作动画是比较难做的东西,因为官方那些动作多数都是用光点捕捉器或动作生成器获取到的,而我们是在手工制作,所以可以借用原版里的一些现成动作,将它们略加修改弄成新的动作。导入动作动画时,3DMAX会自动提醒你伴随导入关联的SKL,因此你需要把动作动画和SKL放到同一个路径下,一导入动作,SKL就自动进入3DMAX了。修改好之后,不要忘了给所有关节点都钩选Export Transform,输出时选择Hierarichical Animated方式输出,下面还要钩选“Export Using Existing”,并选取刚才输出的SKL。如果设置错误的话,会使SKL不受动作的控制,导致人物在游戏里发生该动作时呈现纯静态的T字形。

(e)     必须强调一点,动作动画的第0帧必须保存成基准帧,用来记录T字型基准姿势,并且不允许对它进行编辑,因此任何动作动画都只能从第1帧开始。这样我们可以在必要的时候把SKN导进来与关节点进行绑定,以检验我们做的新动作是否够自然。如果你没保留基准帧,那么绑定SKN的时候,你就找不到一个最合适的姿势,以至于容易出现绑定错误导致无法检验动作效果。

(f)      如果你实在受不了这么麻烦的输出注意事项,建议你把士兵模型当作坦克来制作,即每个动作都包含完整的蒙皮、骨骼和动作,并整合起来Hierarichical Animated方式输出成单一的W3D,不要像官方那样拆分成相互关联的SKNSKL和动作。这样做的好处在于输出设置可以偷懒,彻底避免了动作怪异、静态T字形和微动T字形的情况发生,但缺点就是最后得到的W3D含有重复的内容而占据了一些不必要的磁盘空间。

F、 辅助体: ZH玩多了,可以发现一个现象,那就是我们在点选目标时,鼠标指针必须移动到有形体的部位时才能成功选中该目标。例如中国机场的跑道尽头有一个小缺口,如果你把鼠标移动到该缺口上时,是点不中机场的。这里要解释的是,SAGE规定,既输出形体图像,又输出定位信息的表面,才能被玩家选中。因此对于士兵模型来说,SKNSKL都没有全钩Export GeometryExport Transform,因此在游戏里是无法点选该士兵的。因此官方使用了一个隐形的辅助体带代替SKN被玩家点选,因此这个辅助体必须同时钩上Export GeometryExport Transform,并且Geometry Option里要选择OBBox(辅助体),使之在游戏里不被渲染出任何图像。

G、 常见错误分析

(a)       纯静态T字形:一是忘了设置WWSKIN来绑定SKNSKL;二是忘了给所有关节点钩上Export Transform。三是输出SKN时忘了钩选“Export Using Existing xxxx_SKL”;四是在输出动作动画时,输出方式选成了Hierarichical Model,五是在输出动作动画时忘了钩选“Export Using Existing xxxx_SKL”。

(b)      微动的T字形:肯定是忘了取消SKNExport Transform,导致SKN的位置信息由自身的中心点来控制,而不受SKL的控制,因此整个SKL上只有最靠近SKN中心点的那个关节点能发挥控制作用。

(c)       怪异动作:主要是SKN的顶点和SKL的关节点关联错误。当然也可能是输出动作动画时钩选“Export Using Existing”时选用了另一个步兵的SKL。所以要处理好士兵模型很麻烦,要么就只换SKN,借用原版的SKL和动作,如果要更换SKL,就得把所有动作都重新导入,与新的SKL关联后再重新输出。

(d)      士兵不能点选:肯定是忘了放置辅助体,要不然就是把辅助体隐藏了忘了在输出W3D前恢复显示。

 

至此,基础阶段的教程就全部介绍完了,接下来留给各位作者有两条道路:

1、 知难而退:SAGE引擎太复杂了,相信大多数作者看了这么久的教程,依旧是恍恍惚惚不知所谓,也做不出什么东西来,当然这也是正常的,无论学什么东西,教程都只能给你指点方向,具体如何去领悟真谛,必须要你们自己去深入研究。所以你们如果没兴趣作深入研究的话,我建议你们还是回TS去算了。

2、 迎难而上:SAGE引擎确实复杂,但是未必就完全摸索不通,只要对自己有信心的人都应该明白为什么我发到818上的帖子叫“5个月的心血”了,要摸索透这样一个功能庞大的引擎,确实需要认真地花时间去进行走火入魔似的研究和测试,最后才能体会出各个功能模块、各条语句的作用,达到融会贯通,把教程上讲解的文字归纳为自己所能灵活运用的知识,从而制作出像《冲击波》、《五星之光》等那样有深度的好MOD。如果你准备好要迎接新的挑战,就请你继续向下面看,后面全都是高难度的进阶教程了。