如何在Garry's Mod中使用Lua为实体挂载多个独立模型?
Garry's Mod/Source引擎Lua实现多模型组合SENT操作步骤
1. 基础实体框架搭建
首先创建SENT定义文件,路径为lua/entities/[自定义实体名]/init.lua,先写入基础配置:
AddCSLuaFile() ENT.Type = "anim" ENT.Base = "base_gmodentity" ENT.PrintName = "组合式设备机架" ENT.Spawnable = true ENT.AdminSpawnable = true
2. 主实体与子模型挂载逻辑
核心逻辑是用一个实体作为根节点,其余子部件通过父子绑定关联到根节点,不需要合并模型文件即可整体移动、旋转、删除。你可以根据子部件是否需要交互选择两种实现方案:
方案A:子部件需要碰撞/交互(服务器端实现)
如果需要子模型支持点击、物理碰撞,用服务器端prop_dynamic创建子实体:
function ENT:Initialize() if SERVER then -- 配置主实体基础属性,这里直接用机架作为主模型,也可以换透明的碰撞模型 self:SetModel("models/props_lab/rack.mdl") self:PhysicsInit(SOLID_VPHYSICS) self:SetMoveType(MOVETYPE_VPHYSICS) self:SetSolid(SOLID_VPHYSICS) local phys = self:GetPhysicsObject() if IsValid(phys) then phys:Wake() end -- 挂载电脑屏幕 self.Screen = ents.Create("prop_dynamic") self.Screen:SetModel("models/props_lab/monitor01.mdl") self.Screen:SetPos(self:LocalToWorld(Vector(10, 0, 50))) -- 自行调整相对主实体的偏移坐标 self.Screen:SetAngles(self:LocalToWorldAngles(Angle(0, 0, 0))) -- 自行调整相对角度 self.Screen:SetParent(self) self.Screen:Spawn() self:DeleteOnRemove(self.Screen) -- 主实体删除时自动清理子模型 -- 挂载键盘 self.Keyboard = ents.Create("prop_dynamic") self.Keyboard:SetModel("models/props_lab/keyboard01.mdl") self.Keyboard:SetPos(self:LocalToWorld(Vector(5, 0, 30))) self.Keyboard:SetAngles(self:LocalToWorldAngles(Angle(0, 0, 0))) self.Keyboard:SetParent(self) self.Keyboard:Spawn() self:DeleteOnRemove(self.Keyboard) -- 电池、其他部件直接复制上面的逻辑,改模型路径和坐标角度参数即可 end end
方案B:子部件仅做装饰(客户端实现,性能更高)
如果子模型不需要交互,纯展示用,用客户端模型更节省服务器资源:
function ENT:Initialize() -- 服务器端主实体配置和方案A一致 if SERVER then self:SetModel("models/props_lab/rack.mdl") self:PhysicsInit(SOLID_VPHYSICS) self:SetMoveType(MOVETYPE_VPHYSICS) self:SetSolid(SOLID_VPHYSICS) local phys = self:GetPhysicsObject() if IsValid(phys) then phys:Wake() end end -- 客户端创建子模型 if CLIENT then -- 挂载屏幕 self.CSScreen = ClientsideModel("models/props_lab/monitor01.mdl", RENDERGROUP_OPAQUE) self.CSScreen:SetPos(self:LocalToWorld(Vector(10, 0, 50))) self.CSScreen:SetAngles(self:LocalToWorldAngles(Angle(0, 0, 0))) self.CSScreen:SetParent(self) -- 其他子部件同理复制逻辑修改参数即可 end end -- 客户端子模型需要实时同步位置避免错位 function ENT:Think() if CLIENT then if IsValid(self.CSScreen) then self.CSScreen:SetPos(self:LocalToWorld(Vector(10, 0, 50))) self.CSScreen:SetAngles(self:LocalToWorldAngles(Angle(0, 0, 0))) end -- 其他客户端子模型同步逻辑加在这里 end end -- 实体销毁时清理客户端模型避免内存泄漏 function ENT:OnRemove() if CLIENT then if IsValid(self.CSScreen) then self.CSScreen:Remove() end -- 其他客户端子模型清理逻辑加在这里 end end
3. 坐标调试技巧
你可以在游戏内用坐标调试工具先测好每个子部件相对主实体的偏移量和角度,直接把参数填到代码里,不需要反复重启测试。
提示:子部件的父子绑定是完全同步的,移动、旋转、删除主实体时所有子模型会同步操作,和单个模型的使用体验完全一致。
内容的提问来源于stack exchange,提问作者Fako
相关产品推荐
相关产品推荐

