【原创】【智库教程】原版风格座舱完!全!制!作!教!程!

坎喵站长
· 于2018年1月2日发布

引言

本教程将从零开始教授如何制作一个完整的指令舱,包含从建模到导入的全部过程。

本教程由智库鸽笼出品,感谢Icecovery Studio对本教程的大力支持!智库原创,未经许可,严禁任何组织和个人转载。

以下是部分完成品预览图

null

特性:IVA! 法线贴图!自发光!自发光!自发光!

本教程包含从建模到导入的全部过程

此座舱已经制作完成,期间产生了接近200张截图,将在数日之内陆续发完,请各位耐心等待

在阅读本教程前,您需确保你至少有少量的建模基础,少量的绘图技术(PS/Paint.net),少量的Unity操作水平,少量的英文阅读能力以及少量的智商

本教程使用到的工具以及软件:

3DSMAX2017,Paint.net(这是个软件,相当于精简版的PS),Unity 2017.1.0.f3,Chrome,Notepad++


第一章-建模

首先我们先打开3dsmax,新建一个max工程文件命名为CommandPod保存在文件夹Pod下,创建一个24边的(24边是原版的通用边数)圆柱体重命名为pod,设置其半径到0.625m,在绿色箭头处把此对象的颜色设置成黑色,并且打开精简材质编辑器在蓝色箭头处将材质ID设置成0,然后在红色箭头处将材质赋予给这个对象

添加一个编辑多边形修改器,选中顶面,打开缩放变换输入窗口,在偏移:世界底下的框框中输入50,这样子顶面的直径会变成0.625m

将顶面移动至一个合适的高度,构成基本形状,这里我使这玩意的高度为1m

选中24条边,连接边,使两条连接,如下图所示

选择面向前方的四个边,挤出一定数值

将上方的四个顶点目标焊接到另外四个顶点处,构成下图的模样

进行一定的调整

选中如下四个面,插入一定的值,这里将会是我们的窗口

进行插入-挤出-缩放的操作,做出下图所示的舱门

选中下图所示的一堆面,然后给予一个45度的自动平滑

将窗口分离为对象Window(需要注意的是,这里不分开也是可以的,我们后面将用一个材质球实现窗口反射和表面哑光的效果)

给予一个不同颜色的材质以便区分(需要注意的是,这里如果不分开它们,也可以选定面,然后给单独的面赋予材质)

将底面插入并拉下一定的值

重复上一步数次,得到一个隔热底的形状

给隔热底部分给予一个单独的平滑组

在顶部插入,挤出,插入,挤出以下形状

将不同的部分给予不同的平滑组后得到下图所示的几何体

至此,座舱外表已经建模完成

建立一个与座舱完全重合的几何体

底下做一个简单的形状,大致与隔热底重合

将这个几何体移到一边并给予原谅色,重命名为Collider,这个几何体将是我们用于生成碰撞网的mesh,此处可以使用16边圆柱更好,但是我们选择32边的

将几何体Pod复制一份,并重命名为IVA

将顶底多余的面删除后在边界模式选择封口

将舱门移动进去

给整体一个大约95%的缩放

选中全部的面后,点击翻转,将所有的面翻转向内

右键几何体,对象属性中勾选背面消隐

将窗户封口并连接好点后再次分离,此时分离为几何体IVAwindow,注意在此时选择多边形时应勾选忽略背面选项

新建一个Box并且拉成以下形状

另外一个box拉成以下形状

对第二个box挤出一条支撑臂,然后删去两个box不可见的面后,在几何体IVA附加两个box

把几何体IVA顶部拉下来一点后挤出一定的形状

此处类似与制作隔热底的步骤,制作出一个舱门并且给予平滑组

对每个不同的部分分别都给予平滑组

至此所有的建模工作已经完成了

我们现在有了如下五个几何体


第二章-分解UV

选中几何体Pod和几何体Window,对它们添加一个UVW展开修改器

按下"打开UV编辑器"按钮,弹出编辑UVW窗口,我使用两块屏幕来方便分解UV的流程

我们切换到边模式,然后选择右侧的剥模式,UV将自动剥开成如下的样子

我们在模型视图中一条一条的选择要切开的边,右边会相应的一点一点剥开模型的UV

将上面的环剥下以后

将顶部剥成如下图所示的样子

我们退出剥模式,选择面模式,选择整个隔热底

在如下所示的位置打开展开法线贴图窗口

选择顶/底贴图

点击确定后隔热底被铺平

我们将隔热底移动到一边,然后把模型侧边的两瓣移动到一起

缝合它们

切换到点模式,将底下无法缝合的顶点对其到一起

将窗户也缝合好

我们可以打开棋盘格贴图映射,然后摆放好所有拆开来的UV,尽量使每一个空隙都被用到,每一个位置的方格的差不多大小,使方格尽量不扭曲变形,摆放好以后如下图所示

将IVA和IVAwindow也拆好,如下图所示

选择工具-渲染UVW模板

此处我建议渲染两张,一张为默认设置,勾选可见边,接缝边为绿色,另外一张不勾选可见边,接缝边为黑色

之后点击渲染UV模板按钮,以以下配置保存

对于IVA的UV进行同样操作

之后我们便得到了如下图所示的四张图片,至此,UV分解的工作也结束了


第三章-绘制贴图

我们打开Paint.net,(如果你想用PS也可以,楼主的ps日常抽风故选用更加简单的方法,而且Paint.net也是一款非常好用的dds查看/编辑器,可以在getpaint.net免费下载到(强行安利一波

打开IVA_uv2.png

油漆桶,填充模式改成全局,容限50%,在边上多点几下(PS中可以直接用’描边’完成)

给中间的部分上色

给其余的部分也先暂时上纯色,之后保存,保存设置选择32位

拖动该png文件到max中的几何体Pod上,可以看到已经没毛病了

将Pod_uv1.png拖放至paint.net中,选择添加图层

这样子我们就可以看到模型的边了

我们新建一个图层,沿着pod下缘画一条线

对这个图层进行高斯模糊处理

时刻注意保证模糊后擦除影响到其它部分的地方,导出时注意隐藏最上方的线框图层,以后不再提醒

在max中可以立即看到效果

我们合并刚刚那个图层,并且在新图层用笔刷画上一些奇奇怪怪的东西

图层不透明度改一下

max中可看到的效果如下

在箭头所指的几个地方也加上效果

如图

这里用方块所示的渐变工具也加一点特技

这里同理,顺便搞上一个从原版Mark1-2的贴图上扒下来的舱门

在Max中

画几条这种东西在侧边和隔热底上

把这个图层单独导出

记得加上白色的底

前往http://cpetry.github.io/NormalMap-Online/这个网站

在最右边的框框中拖入刚刚保存的图片,以以下设置生成一张法线贴图

现在我们的贴图

给窗户加一点特技

Max中

选中这一堆

复制到一个黑底的新贴图上

处理成以下模样

现在我们有的贴图

加上两个RCS喷口

和上面一样的方法,画一点钉子什么的

一样生成一张贴图

把两张贴图融合一下

不要忘了漫反射贴图

用淡淡的刷子搞脏一点

把窗户部分单独拿出来,然后移动到另一个图层

将除了窗户外的所有图层透明的设成1%

Max中

以同样的道理,画好IVA的贴图

像这样

当然我们也是有自发光贴图的(自发光!自发光!自发光!


第四章-导出

我们回到max,选中五个对象,然后点击导出-导出选定对象(直接点导出也可以,不过这是个好习惯,防止导出一些不必要的辅助对象

导出设置如下,确定单位是m


第五章-导入

我们打开Unity,新建一个场景(我这里不是新建的

然后安装好Parttool(我在这里使用的是「智库神器™」,然而这个东西和Parttool在下面会讲到的功能上相差无几,故不特别讲述,以下我们简称它为pt

注意:任何求发「智库神器™」的行为是不会得到回答的,智库神器属于智库内部自行研发的保密产品,将不会外传

新建场景和安装Parttool的过程不再细说

拖入我们导出的fbx文件,和五张贴图

将fbx文件拖入场景,并且坐标归零

点击这里更改模型的材质

因为我们有自发光贴图,而且有反光效果,所以我们将模型的材质球切换至KSP-Emissive-Bumped Specular

把贴图拖到正确的位置上,记得fix法线贴图

讲箭头处的三个东西设置好

效果如图,可以看出材质的区别和法线贴图的效果了

IVA同理,只不过我们由于没有法线贴图,故选择KSP-Emissive-Diffuse,并将箭头处设置成默认白色

之前画在玻璃上的污渍是不透明的

我们在这新建一个材质

选择KSP-Alpha-Translucent

现在是透明的了

我们把之前的碰撞网模型移到原点处与模型重合

删除Mesh Renderer和Collider这两个东西,任何加一个Mesh Collider,点选Convex

路径

我们新建一个叫做CommandPodRoot的空对象,

移动到我们想要的重心处,然后把它移动到全部物体的父对象位置

创建一个空对象命名为RCSjet,移动到合适的位置,绿色箭头朝着推力方向

另一边也一样

创建一个空对象命名为Ladder,方向以及大小在图中显示了,记得选择is Trigger

然后添加两个Tag,分别叫Ladder和Airlock,一个大小写都不能错

顺便在User Layer 21 加上Part Triggers

然后将Ladder这样配置

创建一个空对象叫Airlock,位置以及信息如图所示

这就是我们目前有的东西了,CommandPodRoot的方向应该是与模型成这样子的关系但是整体绕绿轴旋转180度,这里是我的一个错误我在后面修复了这个问题。

在CommandPodRoot加一个KSP Part Tools

必须导出至GameData(以下简称GD)下的路径

这里我们导出了DDS,但是原版的pt是没有这个功能的,可以选择PNG导出方便修改

然后我们就有了如下几个东西——三张贴图(漫反射,自发光,法线),一个.mu文件——然后我们新建一个txt文件重命名为Part.cfg


第六章-CFG

然后呢我们就可以愉快的来写这个cfg文件了,

首先我们先写一个框架

(没错就是这样子熟悉的…)

是的。

(响指)

Duang!

写好了

好吧这一次我会贴出源代码

PART
{
    // this is a sample config file, for determining a good file format for defining part parameters
    // comment line - ignored by cfg parser
    // empty lines, or lines without a ‘=’ sign are also ignored
    // all other lines are split at the ‘=’ sign, and the left operand is used to know what parameter we are setting
    // diferent parameters require data in different formats (see docs), and each module has it’s own parameters (again, see docs)
    // each assignment must be in a single line. Lines without assignments will be ignored. (You CAN turn on word wrap, though)
    // each keyword here relates to an existing variable in the assigned module. If the keyword isn’t found, it is ignored.
    // conversely, if a keyword is left unassigned (as in not in the file), it will be initialized with it’s default value
    // This is done automatically, so any public variable defined in the loaded module can be accessed this way (provided it’s value can be parsed)
 
 
    // — general parameters —
    name = TestCommandPod
    module = Part
    author = Icecovery
 
    // — asset parameters —
    mesh = model.mu
    scale = 1
    rescaleFactor = 1
 
    // — node definitions —
    // definition format is Position X, Position Y, Position Z, Up X, Up Y, Up Z, [node size], [crossfeed, def=1 i.e. true], [rigid attach, def=0 i.e. false]
    node_stack_bottom = 0.0, -0.3, 0.0, 0.0, -1.0, 0.0, 1
    node_stack_top = 0.0, 0.7, 0.0, 0.0, 1.0, 0.0, 0
    bulkheadProfiles = size1, size0
    CoPOffset = 0.0, 0.5, 0.0
    CoLOffset = 0.0, -0.35, 0.0
    CenterOfBuoyancy = 0.0, 0.5, 0.0
    CenterOfDisplacement = 0.0, -0.3, 0.0
    buoyancy = 1.5
    buoyancyUseSine = False
 
    // — editor parameters —
    TechRequired = start
    entryCost = 0
    cost = 600
    category = Pods
    subcategory = 0
    title = Test Command Pod
    manufacturer = Icecovery Stuio
    description = This is a test command pod.
 
    // attachment rules: stack, srfAttach, allowStack, allowSrfAttach, allowCollision
    attachRules = 1,0,1,1,0
    
    bodyLiftOnlyUnattachedLift = True
    bodyLiftOnlyAttachName = bottom
 
    // — standard part parameters —
    mass = 0.8
 
    dragModelType = default
    maximum_drag = 0.2
    minimum_drag = 0.15
    angularDrag = 2
    crashTolerance = 14
    maxTemp = 1200
    skinMaxTemp = 2200
 
    skinInternalConductionMult = 0.625
    heatConductivity = 0.1 // 5/6ths default
 
    vesselType = Ship
 
    // — internal setup —
    CrewCapacity = 1
    
    INTERNAL
    {
     name = TestCommandPodIVA
    }
 
    MODULE
    {
        name = ModuleCommand
        minimumCrew = 1    
    }
    RESOURCE
    {
        name = ElectricCharge
        amount = 200
        maxAmount = 200
    }
 
    MODULE
    {
        name = ModuleReactionWheel
        
        PitchTorque = 5
        YawTorque = 5
        RollTorque = 5
        
        RESOURCE
        {
            name = ElectricCharge
            rate = 0.24
        }
    }
    MODULE
    {
        name = ModuleColorChanger
        shaderProperty = _EmissiveColor
        animRate = 0.8
        animState = false
        useRate = true
        toggleInEditor = true
        toggleInFlight = true
        toggleInFlight = true
        unfocusedRange = 5
        toggleName = Toggle Lights
        eventOnName = Lights On
        eventOffName = Lights Off
        toggleAction = True
        defaultActionGroup = Light
        redCurve
        {
            key = 0 0 0 3
            key = 1 1 0 0
        }
        greenCurve
        {
            key = 0 0 0 1
            key = 1 1 1 0
        }
        blueCurve
        {
            key = 0 0 0 0
            key = 1 0.7 1.5 0
        }
        alphaCurve
        {
            key = 0 1
        }
    }
    MODULE
    {
        name = ModuleScienceExperiment    
        
        experimentID = crewReport
        
        experimentActionName = Crew Report
        resetActionName = Discard Crew Report
        reviewActionName = Review Report
        
        useStaging = False    
        useActionGroups = True
        hideUIwhenUnavailable = True    
        rerunnable = True
        
        xmitDataScalar = 1.0
        
        usageReqMaskInternal = 5
        usageReqMaskExternal = -1
    }
    MODULE
    {
        name = ModuleScienceContainer
        
        reviewActionName = Review Stored Data
        storeActionName = Store Experiments
        evaOnlyStorage = True
        storageRange = 1.3
    }
 
    RESOURCE
    {
        name = MonoPropellant
        amount = 10
        maxAmount = 10
    }
 
 
    MODULE
    {
        name = ModuleConductionMultiplier
        modifiedConductionFactor = 0.003
        convectionFluxThreshold = 3000
    }
 
    MODULE
    {
        name = ModuleDataTransmitter
        antennaType = INTERNAL
        packetInterval = 1.0
        packetSize = 2
        packetResourceCost = 12.0
        requiredResource = ElectricCharge
        antennaPower = 5000
        optimumRange = 2500
        packetFloor = .1
        packetCeiling = 5
    }
    
    MODULE
    {
        name = ModuleLiftingSurface
        useInternalDragModel = False
        deflectionLiftCoeff = 0.35
        liftingSurfaceCurve = CapsuleBottom
        disableBodyLift = False
        omnidirectional = False
        perpendicularOnly = True
        transformDir = Y
        transformSign = -1
        nodeEnabled = True
        attachNodeName = bottom
    }
    EFFECTS
    {
        running
        {
            AUDIO_MULTI_POOL
            {
                channel = Ship
                transformName = RCSjet
                clip = sound_rocket_mini
                volume = 0.0 0.0
                volume = 0.1 0.0
                volume = 0.5 0.025
                volume = 1.0 0.1
                pitch = 0.0 0.75
                pitch = 1.0 1.5
                loop = true
            }
            MODEL_MULTI_PARTICLE
            {
                modelName = Squad/FX/Monoprop_small
                transformName = RCSjet
                emission = 0.0 0.0
                emission = 0.1 0.0
                emission = 1.0 1.0
                speed = 0.0 0.8
                speed = 1.0 1.0
                localRotation = -90, 0, 0
            }
        }        
    }
    MODULE
    {
        name = ModuleRCSFX
        stagingEnabled = False
        thrusterTransformName = RCSjet
        thrusterPower = 1
        resourceName = MonoPropellant
        resourceFlowMode = STAGE_PRIORITY_FLOW
        runningEffectName = running
        atmosphereCurve
        {
            key = 0 240
            key = 1 100
            key = 4 0.001
        }
    }
}

(嗯洋洋洒洒258行

(具体就不详述了,自己去体会吧

然后接下来我们来把节点的位置搞好

如上两个数值用一个空对象在unity中测出

填好

这里我暂时留空,我们还没有做IVA

这三个地方填写RCSjet(希望你还记得为什么

差不多就这样了先


第七章-测试

这一章还用说什么?

打开游戏就是了

如果一切都正常你可以在Pod类找到这玩意

如果没找到就去找找哪里做错了

如果找不出来就再找一次

再找不出来就先洗把脸再找

再找不出来再来问

这是目前的效果

RCS工作正常,玻璃的反射也没毛病

自发光没毛病

没毛病

没毛病

还是没毛病

还是非常的原版风格的

对比


第八章-IVA

这里将会是比较神奇的一个章节了

首先我们先创建一个CommandIVARoot,方向是这样子的,然后把模型旋转成这样子

加一个光源我们做的自发光的灯的地方

以及其它两个灯

现在是这样子的

然后我们创建两个临时的碰撞网在这里,与这个板子的表面重合,它们将会帮助我们更快的定位等一下要弄的小道具们

加入一个摄像机,在如下的位置,切换到Game窗口可以查看,记得把右边方块中的值改成最小,将会更加接近于在游戏中的样子

这里也有一个,看向窗外的

创建两个碰撞网,记得标记为Trigger

在你想要点击然后切换到摄像机的地方

接下来我们创建一个空对象命名为Prop

然后我们打开pt,到Prop选项卡,然后这里就是我们所有的Prop了

需要注意的是,如果你没有安装RPM或者ASET或者NF的Prop包或者之类的Mod,这里将只会显示原版自带的Prop,装了以后重新扫描GD即可出现新的

这里我们首先先放一个导航球(NavBall)

搜索NavBall(我不确定原版pt有没有搜索功能,没有就顺着找吧

出来以后移动到仪表盘正上方,之前我们的碰撞网此时有了作用,我们点击一下图示的两个按键

它就会自动贴在正确的位置上,只需要稍稍移动就行了

然后我们放一个座位,这里我们接下来都会使用NF的 Prop包里的东西

房号以后在这个座位下创建一个空对象Seat,这里是我们的绿人要坐的地方,然后移动它到IVA下

如下图所示

然后我们以此类推布置好我们的仪表盘

然后加一点小东西来装饰,这些东西都可以在NF的Prop包里找到

还是很温馨的对吧

喝着摩卡咖啡玩着Thinkpad又一边开火箭,感觉非常好呢(

然后我们把这几个和相机有关的东西移动出来

给他们加上如下图所示地方新建的Layer 16,命名为Kerbals,同时在Layer 20 写上Internal Space

给所有IVA下的对象加上Internal Space这个Layer

这个时候它会一体式是否也要改变子对象的Layer,我们选择是

然后给给相机们加上Kerbals这个Layer,然后移动回去

然后我们把这玩意先记得移动出来

然后我们导出IVA下的东西们

到以下路径

新建一个叫做IVA的.cfg文件

内容如下

以下是代码

INTERNAL
{
    name = TestCommandPodIVA
    MODULE
    {
        name = InternalCameraTargetHelper
    }
    MODULE
    {
        name = InternalSeat
        seatTransformName = Seat
        allowCrewHelmet = false
    }
    MODULE
    {
        name = InternalCameraSwitch
        colliderTransformName = CamTrigger1
        cameraTransformName = Camera1
    }
    MODULE
    {
        name = InternalCameraSwitch
        colliderTransformName = CamTrigger2
        cameraTransformName = Camera2
    }
}

接下来我们刷新一下pt

然后我们在IVA这个选项卡中搜索(它也许叫做Internal Space)TestCommandPodIVA 这个名称

然后我们就生成了一个合成的IVA部件

把Prop复制一份,放到这个部件下,然后坐标归零,然后这些东西应该就会像下图一样到正确的地方了

然后我我们选择这个合成的part,选择Save to Config

然后我们重新打开IVA.cfg就可以看到这些小道具的信息都已经被填写好了,非常方便省时

然后我们回到Part.cfg,在INTERNAL下写好IVA的名称

然后这里我们就修复了上面提到的我犯的错误,转了180度


第九章-装十三

接下来当然就是装13了啊,打开游戏爽就是了

以下是一大堆截图

几把蛋坐在新玩具里笑得很开心


第十章-进阶

好的这里的确还有一些神奇的东西属于进阶部分,这些东西很简单,但是可以实现很不错的效果

首先我们复制一个外模,也就是几何体Pod,与IVA重合,然后给它一个神奇的材质,这个材质叫做DepthMask, 值得注意的是这个材质不在KSP分类下。

然后我们就可以把该对象移动到IVA这个父级下,然后重新导出一次,这样子在游戏中就可以实现点开右下方绿人边上的小绿点以后,只有窗口可以看到里面,或者我们还可以在边上开几个洞什么的,甚至是门上也可以开洞。这个效果可以在原版的很多Pod上看到。

这里也就是为什么我说实际上我们不需要分开window但是我还是分开了的原因了。

更多进阶内容(比如过热动画之类的我会在以后慢慢的补上,敬请期待

后记

这样子整个教程就都结束了,现在在Word看有145页,5700多个字,11371个字符,也写了很久的。

希望对大家有帮助,喜欢的话点个喜欢点个赞,B站投点币Patreon捐点钱。

B站ID: Icecovery

Patreon页面:https://www.patreon.com/Icecovery

最后祝大家都可以做出自己满意又精致的MOD。

然后就没有了。

最后更新:2022年11月17日
赞助商广告