#### Prefab(来源:Longfei, - 勿言 -) {{:06mod教程区:新手入门:prefab架构.webp?400|}} **Prefab基础结构** ```lua --------------------------------------- 加载资源表 ----------------------------------- local assets = { Asset("ANIM", "anim/lotus_umbrella.zip"), Asset("ANIM", "anim/swap_lotus_umbrella.zip"), Asset("ATLAS", "images/inventoryimages/lotus_umbrella.xml"), } --------------------------------------- end 加载资源表 ----------------------------------- --------------------------------------- 描述函数 ----------------------------------- ... 一些定义在外部的函数 local function fn() -- 描述函数 local inst = CreateEntity() -- 创建实体 ... 对inst添加各种各样的组件,并对每个组件进行一些设置 return inst end --------------------------------------- end 描述函数 ----------------------------------- return Prefab("common/inventory/lotus_umbrella", fn, assets) -- 第一个参数就是Prefab名,系统只会识别最后一个斜杠后面的名字,fn代表描述函数,assets代表加载资源表 ``` - Transform:主要控制实体的位置、方向和缩放大小 - 位置 - `inst.Transform:GetWorldPosition()`:返回实体当前所在的世界坐标x,y,z 另一种写法:`inst:GetPosition():Get()` - `inst.Transform:SetPosition(x, y, z)`:设置当前实体的位置 - 方向 可以再[-180°, 180°]之间进行旋转 - `inst.Transform:GetRotation()`:获取方向 - `inst.Transform:SetRotation(degree)`:设置方向 - 缩放 默认x,y,z的初始缩放设置值为1,1,1 - `inst.Transform:GetScale()`:获取缩放 - `inst.Transform:SetScale(x, y, z)`:设置缩放 - Face 设置实体在面向不同角度时,播放同一个动画,会显示不同形态 `inst.Transform:SetNoFaced()`:设置无面,始终只有一个动画形态 `inst.Transform:SetTwoFaced()`:2面,只有下、右 `inst.Transform:SetFourFaced()`:4面,上下左右 `inst.Transform:SetSixFaced()`:6面,上下左右+左下、右上 `inst.Transform:SetEightFaced()`:8面,上下左右+四个斜向 - AnimState:动画组件,控制Prefab的材质(Build),动画集合(Bank)和动画播放(Animation) - `Build`:材质(对应Spriter项目文件的名字) - `Bank`:动画集(对应Spriter里面多个动画的上级) - `Symbol`:每个动画由多个部分组成,每个部分就是`Symbol` - 设置 - `inst.AnimState:SetBuild("bird_cage")`:设置Build - `inst.AnimState:SetBank("birdcage")`:设置Bank - `inst.AnimState:SetLayer(LAYER_WORLD)`:设置层级(会影响多个物体重叠时层次顺序) - `inst.AnimState:SetOrientation(ANIM_ORIENTATION.OnGround)`:设置朝向 - `inst.AnimState:SetSortOrder(3)`:设置排序顺序,在层级相同时有影响 - 动画播放 - `inst.AnimState:PlayAnimation("idle")`:在动画集里面播放指定动画 - `inst.AnimState:PushAnimation("idle")`:推送动画到动画播放队列中,Prefab会按队列中各动画的先后推送顺序依次播放,与PlayAnimation的区别是,Push会等待队列动画播放结束,而Play是直接打断播放队列,立刻播放设定的动画 - 局部修改 - `inst.AnimState:OverrideSymbol("swap_object", "file_name", "symbol_name")`:用其它动画的某个Symbol来覆盖当前Prefab的Symbol `swap_object`:当前Symbol名 `file_name`:覆盖用的动画文件名(无后缀) `symbol_name`:覆盖用的Symbol名 - `inst.AnimState:Show("ARM_carry")`:显示Prefab的某个Symbol - `inst.AnimState:Hide("ARM_normal")`:隐藏Prefab的某个Symbol - 相关事件 `animover`:在当前动画播放结束后触发 `animqueueover`:在所有的播放队列都结束后触发 `inst:ListenForEvent("animover",function(inst) inst:Remove() end)`:让特效在动画结束后被移除 ```lua ------典型用法 inst.AnimState:SetBank("bank名") inst.AnimState:SetBuild("build名") inst.AnimState:PlayAnimation("idle") inst.AnimState:SetOrientation(ANIM_ORIENTATION.OnGround) -- 设置Prefab平放在地上 inst.AnimState:SetLayer(LAYER_BACKGROUND) -- 设置图层位置,会影响到重叠动画的表现,贴在地s上的图层会位于一般Prefab图层之下。比如人物会遮盖农场的动画。 inst.AnimState:SetSortOrder(3) -- 设置排序顺序,使用官方常用的3就行了。 ------装备/卸载物品 --【手持装备】-- -- 装备回调 local function onequip(inst, owner) owner.AnimState:OverrideSymbol("swap_object", "swap_build", "swap_symbol") -- owner.AnimState:Show("ARM_carry") owner.AnimState:Hide("ARM_normal") end -- 卸载回调 local function onunequip(inst, owner) owner.AnimState:Hide("ARM_carry") owner.AnimState:Show("ARM_normal") end --【身体装备】 -- 装备回调 local function onequip(inst, owner) owner.AnimState:OverrideSymbol("swap_body", "swap_build", "swap_symbol") end -- 卸载回调 local function onunequip(inst, owner) owner.AnimState:ClearOverrideSymbol("swap_body") end --【头部装备】 -- 装备回调 local function onequip(inst, owner) owner.AnimState:OverrideSymbol("swap_hat", "swap_build", "swap_symbol") owner.AnimState:Show("HAT") owner.AnimState:Show("HAT_HAIR") owner.AnimState:Hide("HAIR_NOHAT") owner.AnimState:Hide("HAIR") end -- 卸载回调 local function onunequip(inst, owner) owner.AnimState:Hide("HAT") owner.AnimState:Hide("HAT_HAIR") owner.AnimState:Show("HAIR_NOHAT") owner.AnimState:Show("HAIR") end ------连续播放(砍树为例) ---播放第一个动画,然后把剩下的动画推送到动画队列里 inst.AnimState:PlayAnimation("chop_pre") -- 播放前摇动画 inst.AnimState:PushAnimation("chop") -- 推送砍树动画 ------特效动画(播放完动画后移除Prefab) --在动画播放完成后,Prefab会自动推送一个animover事件。只要监听该事件,在播放完后直接移除Prefab即可 inst:ListenForEvent("animover", function() inst:Remove() end) ``` - Phiysics:物理组件,能够使得实体拥有物理属性(详见`scripts/standardcomponents.lua`) (下面代码不可在同一个Prafab中使用,需要写在网络代码上方) - `MakeInventoryPhysics(inst)`:物品栏物品 特点:可以通过`inst.Physics:SetVel(x,y,z)`来提供初速度,并且遵循重力、摩擦、碰撞等物理规律 - `MakeCharacterPhysics(inst, mass, rad)`:**人物角色**(人物,行走的生物) - `mass`:质量 - `rad`:碰撞半径 特点:无视摩擦力,无法越过障碍物(小型:浆果丛,一般:池塘、围墙) - `MakeFlyingCharacterPhysics(inst, mass, rad)`:**飞行生物**(蚊子,蜜蜂) 特点:类似人物角色,但可以越过像池塘、浆果丛这样的障碍物 - `MakeTinyFlyingCharacterPhysics(inst, mass, rad)`:**极小飞行生物**(蝴蝶) 特点:类似飞行生物,但不会和飞行生物发生碰撞(很多蝴蝶可以在同一个位置重叠,而蜜蜂不行) - `MakeGiantCharacterPhysics(inst, mass, rad)`:**巨型生物**(各大BOSS) 特点:类似人物角色,但会越过浆果丛等小型障碍物 - `MakeFlyingGiantCharacterPhysics(inst, mass, rad)`:**飞行巨型生物**(龙蝇,蜂后) 特点:类似巨型生物,但可以越过池塘这样的一般障碍物 - `MakeGhostPhysics(inst, mass, rad)`:**幽灵**(阿比盖尔,蝙蝠,格罗姆,幽灵,玩家的灵魂) 特点:类似人物角色,但无视障碍物 - `MakeObstaclePhysics(inst, rad, height)`:**障碍物**(围墙,各种建筑,猪王等等) 特点:无 - `MakeObstaclePhysics(inst, rad, height)`:**小型障碍物**(浆果丛,尸骨) 特点:无 - `MakeHeavyObstaclePhysics(inst, rad, height)`:**重型障碍物**(各种可以背的石块) 特点:类似障碍物,需要结合组件**heavyobstaclephysics**使用 - `MakeSmallHeavyObstaclePhysics(inst, rad, height)`:**小型重型障碍物**(knighthead,bishophead,rooknose) 特点:类似小型障碍物,需要结合组件**heavyobstaclephysics**使用 - `RemovePhysicsColliders(inst)`:无视碰撞,移除所有碰撞效果,自由穿梭 - `inst.Physics:Stop()`:停止运动,将实体的速度设为0 - `inst.Physics:SetMotorVel(x,y,z)`:为实体设置运动速度,驱使Prefab移动,x,y,z为各个轴向的速度。该方法只对人物、生物类型有效 *(此处的坐标系为相对坐标系,x轴正向为Prefab当前面向方向,y轴向上,z轴方向由x,y用右手系法则确定。直观地说,大多数时候我们只需要让Prefab按照当前方向前进,那么只需要设置第一个参数的值为目标速度,y,z均取0)* - `inst.Physics:GetMotorVel()`:获取实体的当前速度 - `inst.Physics:SetVel(x,y,z)`:为实体设置初始速度,驱使Prefab移动,x,y,z为各个轴向的速度。该方法只对物品栏物品类型有效。 *(*与`SetMotorVel`不同,此方法的坐标系与世界地图的坐标系一致。 此速度只是初始速度,物品栏物品的运动会受到重力、摩擦力、弹力等影响*)* - `MakeInventoryFloatable(inst, "med", 0.1)`:给prefab设置漂浮属性 - `MakeHauntableLaunchAndIgninte(inst)`:给prefab设置作祟属性 - Light:光照组件,添加该组件可使得Prefab成为一个光源 `inst.entity:AddLight()`:安装组件 `inst.Light:Enable(bool)`:启用/禁用,bool为true,启用,发光。bool为false,禁用,不发光 `inst.Light:SetRadius(radius)`:设置光照半径(三维) `inst.Light:GetRadius()`:获取光照半径 `inst.Light:SetIntensity(percent)`:设置光强 `inst.Light:GetIntensity()`:获取光强 `inst.Light:SetFalloff(percent)`:设置衰减,描述光线随着光源距离而变暗的动态变化 `inst.Light:GetFalloff()`:获取衰减 `inst.Light:GetCalculatedRadius()`:获取光照实际半径 `inst.Light:SetColour(red,green,blue)`:设置光照颜色 `inst.Light:GetColour()`:获取光照颜色 - Network:网络组件,添加与否决定了一个Prefab在主机上生成时,是否会被客户端“看”到 `inst.entity:AddNetwork()`:添加网络组件 - MapEntity:地图实体组件,使用该组件可以为Prefab在小地图上创建一个图标 - SoundEmitter:声音组件,控制Prefab的声音集合和播放 - 描述 可以写在其他位置,也可以写在专门的Lua文件里,只需要用`modimport("prefab_desc")`导入即可(路径从mod根目录开始) - 名字 `STRINGS.NAMES.prefab名全大写 = "荷叶伞"` - 人物描述 人物在检查Prefab时,说出的一段描述性文字 `STRINGS.CHARACTERS.人物Prefab名全大写.DESCRIBE.物体Prefab名全大写`:人物专属描述 `STRINGS.CHARACTERS.GENERIC.DESCRIBE.物体Prefab名`:通用描述 - 物品制作栏描述 `STRINGS.RECIPE_DESC.物体Prefab名全大写 = 描述字符串` - Recipe - 可制作*(详见`scripts/recipe.lua`)* - `name`:Prefab名 - `ingredients`:成分表 - `tab`:物品栏分类 - `level`:科技等级 - `placer`:建筑物放置物,也就是制造建筑时显示的那个图像(实质上也是个Prefab) - `min_spacing`:最小间隔 - `nounlock`:是否可以离开制作台制作--远古物品只能在制作台上制作。nil则可以离开制作台 - `numtogive`:制作数量,若填nil则为制作1个。 - `builder_tag`:制作者需要拥有的Tag(标签),填nil则所有人都可以做 - `atlas`:制作栏图片文档路径 - `image`:制作栏图片文件名,当名字与Prefab名相同时,可省略。 - `testfn`:自定义检测函数,需要满足该函数才能制作物品,不常用。 ```lua ---一般物品示例,写在Modmain.lua即可 AddRecipe( "lotus_umbrella", --- Prefab名 (必填) { Ingredient("cutgrass", 1), ---成分表 (必填) Ingredient("twigs", 1) }, RECIPETABS.SURVIVAL, --- 物品栏分类 (必填),RECIPETABS和TECH见/scripts/constants.lua TECH.NONE, --- 科技登记 (必填) nil, --- 建筑物放置物 nil, --- 最小间隔 nil, --- 是否可以离开制作台制作 nil, --- 制作数量,nil则为1 nil, --- 制作者需要拥有的Tag,nil则所有人都可以 "images/inventoryimages/lotus_umbrella.xml", --- 制作栏图片文档路径 nil, --- 制作栏图片文件名,当名字与Prefab名相同时,可省略 nil, --- 自定义检测函数,需要满足该函数才能制作物品,不常用 ) ``` - 建筑物制作 需要先生成一个Prefab放置物(约定命名为***Prefab名_placer***,然后在添加Recipe时设置这个放置物Prefab `MakePlacer(name, bank, build, anim, onground, snap, metersnap, scale, fixedcameraoffset, facing, postinit_fn)`:设置放置物 - `name`:放置物的Prefab名,一般约定为***原Prefab名_placer*** - `bank`:放置物的Bank - `build`:放置物的Build - `anim`:放置物用于播放的动画,一般约定为***idle*** - `onground`:取值为***true***或***false***,是否设置为紧贴地面。请参考前面AnimState的内容 - `snap`:取值为***true***或***false***,这个参数目前无用,设置为nil即可 - `metersnap`:取值为***true***或***false***,与围墙有关,一般建筑物用不上,设置为nil即可。 - `scale`:缩放大小 - `fixedcameraoffset`:固定偏移 - `facing`:设置有几个面,参考AnimState的内容 - `postinit_fn`:特殊处理 ```lua MakePlacer("lotus_pond_placer", "lotus_pond", "lotus_pond", "idle", true) inst.AnimState:SetOrientation(ANIM_ORIENTATION.OnGround) inst.AnimState:SetLayer(LAYER_BACKGROUND) inst.AnimState:SetSortOrder(3) ``` - 放置建筑物 ```lua AddRecipe("lotus_pond", {Ingredient("shovel", 2), Ingredient("cutstone", 2),Ingredient("poop", 6)}, RECIPETABS.FARM, TECH.SCIENCE_TWO, "lotus_pond_placer", 5, nil, nil, nil,"images/map_icons/lotus_pond.xml") ``` - 相关函数 - `AddPrefabPostInit(prefab, fn)`:在prefab实例化的时候,调用fn函数,并传入prefab的实例 ```lua -- 修改长矛攻击力 -- 放在modmain.lua即可 -- 对Component的修改要在主机上 local function modispear(inst) if not TheWorld.ismastersim then return inst end inst.components.weapon:SetDamage(50) end AddPrefabPostInit("spear", modispear) ``` - `AddPrefaPostInitAny(fn)`:对所有prefab进行修改