You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Derma SpawnIcon点击事件异常求助:仅最后一个SpawnIcon的DoClick函数生效

问题原因分析

你遇到的问题核心有两个:

  • 全局变量滥用:你的代码里Frame、sheet、panel1、DScrollPanel、DPanel这些变量都没有用local声明,属于全局变量。每次调用DrawCratePrimWeapon时,这些全局变量都会被新创建的控件覆盖,导致之前的控件引用丢失,甚至层级混乱。
  • 重复创建滚动面板并覆盖:每次调用DrawCratePrimWeapon都会在panel1里新建一个DScrollPanel并设置Dock(FILL),后面的滚动面板会完全覆盖前面的,导致只有最后一个滚动面板里的SpawnIcon能被点击到,前面的都被挡住了。
修复方案

下面是修改后的完整代码,我会标注关键修复点:

修改后的 cl_hud.lua

-- 提前声明需要跨函数访问的局部变量,避免全局覆盖
local Frame, sheet, panel1, scrollPanel

function DrawCrateDERMA( textebat, mdl )
	Frame = vgui.Create( "DFrame" )
	Frame:SetTitle( "Оружейный ящик" )
	Frame:SetSize( ScrW() * 800/1920, ScrH() * 600/1080 )
	Frame:Center()
	Frame:SetDraggable( false )
	Frame:ShowCloseButton( true )
	Frame:MakePopup(true)
	Frame:SetBackgroundBlur(false)
	Frame.Paint = function( self, w, h )
		draw.RoundedBox( 5, 0, 0, w, h, Color( 25, 25, 25, 200 ) )
	end

	sheet = vgui.Create( "DPropertySheet", Frame )
	sheet:Dock( FILL )

	panel1 = vgui.Create( "DPanel", sheet )
	panel1.Paint = function( self, w, h )
		draw.RoundedBox( 100, 0, 0, 280, 120, Color( 0, 0, 0, 0) )
	end
	sheet:AddSheet( "Основное оружие", panel1, "materials/gunsicon.png" )
	sheet.Paint = function( self, w, h )
		draw.RoundedBox( 5, 0, 0, w, h, Color( 50, 50, 50, 150 ) )
	end

	-- 只创建一次滚动面板,放在panel1内部
	scrollPanel = vgui.Create( "DScrollPanel", panel1 )
	scrollPanel:Dock( FILL )
	-- 添加自动布局面板,替代手动设置坐标,让图标排列更规整
	local layout = vgui.Create( "DIconLayout", scrollPanel )
	layout:Dock( FILL )
	layout:SetSpaceX( 20 )
	layout:SetSpaceY( 20 )
	layout:SetPadding( 20 )
	scrollPanel.layout = layout -- 把布局面板挂载到滚动面板上,方便后续调用
end

function DrawCratePrimWeapon(textebat, mdl, functonclick)
	-- 从统一的布局面板创建武器容器,不再重复新建滚动面板
	local DPanel = scrollPanel.layout:Add( "DPanel" )
	DPanel:SetSize( ScrW() * 200/1920, ScrH() * 100/1080 )
	DPanel:SetBackgroundColor(Color(25,25,25,155))

	local ImgKnop = vgui.Create( "SpawnIcon", DPanel )
	ImgKnop:SetPos( 0, 0 )
	ImgKnop:SetSize( DPanel:GetWide(), DPanel:GetTall() - 25 ) -- 留出标签空间
	ImgKnop:SetModel( mdl )
	-- 支持传入自定义点击逻辑,没有则用默认打印
	ImgKnop.DoClick = functonclick or function()
		print("Clicked on weapon: " .. textebat)
	end

	local text1 = vgui.Create("DLabel", DPanel)
	text1:SetPos(0, DPanel:GetTall() - 20)
	text1:SetText(textebat)
	text1:SizeToContents()
	text1:CenterHorizontal() -- 让武器名称居中显示
end

修改后的 cl_init.lua

include("shared.lua")
function ENT:Draw()
	self:DrawModel()
end

net.Receive("poslat", function()
	DrawCrateDERMA("GAVNO","models/props_interiors/Furniture_Couch02a.mdl")
	-- 不再需要手动传坐标,布局面板会自动排列
	DrawCratePrimWeapon("228/1337","models/props_c17/furnitureStove001a.mdl")
	DrawCratePrimWeapon("22345528/1337","models/props_c17/oildrum001.mdl")
	DrawCratePrimWeapon("22328/1337","models/props_c17/lampShade001a.mdl")
end)
关键修复点说明
  1. 全局变量改为局部变量:用local声明所有控件变量,彻底避免了每次调用函数时覆盖之前的控件引用问题。
  2. 单一滚动面板+自动布局:在DrawCrateDERMA里只创建一个滚动面板,并添加DIconLayout自动管理武器图标位置,替代手动设置坐标的繁琐操作,同时解决了面板互相覆盖的问题。
  3. 控件层级梳理:所有武器面板都添加到同一个布局容器中,确保所有SpawnIcon都能正常显示并响应点击。
  4. 保留自定义点击逻辑:保留了传入functonclick参数的功能,你可以根据需求传入自定义的点击处理代码。

这样修改后,所有的SpawnIcon都会正常响应点击事件,布局也更规整,还支持滚动显示更多武器。

内容的提问来源于stack exchange,提问作者DeloreanZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:22:45