我正在编辑【Emmylua】代码,遇到了 【LuaException: Projects/AAAShare/ShiYans/XiaHeMoYaWoGouFengBiShu/Mission/UI/UIXiShouPaiXun/ui_xishoupaixun.lua:609: attempt to index a nil value (field '?')】
,请帮我检查并改正错误点。我的原始代码如下:
【----@class UIXiShouPaiXun:UIBaseView2
local UIXiShouPaiXun = BaseClass("UIXiShouPaiXun", UIBaseView2)
function UIXiShouPaiXun:ShuffleArray(t)
if not t then
return {}
end
for i = #t, 2, -1 do
local j = math.random(i)
t[i], t[j] = t[j], t[i]
end
return t
end
-- 创建完调用
function UIXiShouPaiXun:LoadCallBack()
-- override
--UINameTable init start
--上面的七个位置
---@type UnityEngine.GameObject
self.upimg1 = self:FindObj("upimg1")
---@type UnityEngine.GameObject
self.upimg2 = self:FindObj("upimg2")
---@type UnityEngine.GameObject
self.upimg3 = self:FindObj("upimg3")
---@type UnityEngine.GameObject
self.upimg4 = self:FindObj("upimg4")
---@type UnityEngine.GameObject
self.upimg5 = self:FindObj("upimg5")
---@type UnityEngine.GameObject
self.upimg6 = self:FindObj("upimg6")
---@type UnityEngine.GameObject
self.upimg7 = self:FindObj("upimg7")
--下面的七个位置
---@type UnityEngine.GameObject
self.downimg1 = self:FindObj("downimg1")
---@type UnityEngine.GameObject
self.downimg2 = self:FindObj("downimg2")
---@type UnityEngine.GameObject
self.downimg3 = self:FindObj("downimg3")
---@type UnityEngine.GameObject
self.downimg4 = self:FindObj("downimg4")
---@type UnityEngine.GameObject
self.downimg5 = self:FindObj("downimg5")
---@type UnityEngine.GameObject
self.downimg6 = self:FindObj("downimg6")
---@type UnityEngine.GameObject
self.downimg7 = self:FindObj("downimg7")
--七张图片
---@type UnityEngine.GameObject
self.xiShouImg1 = self:FindObj("xiShouImg1")
---@type UnityEngine.GameObject
self.xiShouImg2 = self:FindObj("xiShouImg2")
---@type UnityEngine.GameObject
self.xiShouImg3 = self:FindObj("xiShouImg3")
---@type UnityEngine.GameObject
self.xiShouImg4 = self:FindObj("xiShouImg4")
---@type UnityEngine.GameObject
self.xiShouImg5 = self:FindObj("xiShouImg5")
---@type UnityEngine.GameObject
self.xiShouImg6 = self:FindObj("xiShouImg6")
---@type UnityEngine.GameObject
self.xiShouImg7 = self:FindObj("xiShouImg7")
--提交按钮
---@type UnityEngine.GameObject
self.btn_TiJiao = self:FindObj("btn_TiJiao")
--正确答案显示按钮
---@type UnityEngine.GameObject
self.btn_zhengQue = self:FindObj("btn_zhengQue")
---@type UnityEngine.GameObject
self.btn_NextStep = self:FindObj("btn_zhengQue")
---@type UnityEngine.Canvas
self.CanvasUp = self:FindObj("CanvasUp"):GetComponent(typeof(CS.UnityEngine.Canvas))
---@type UnityEngine.UI.Image
self.CorrectMark = self:FindObj("CorrectMark"):GetComponent(typeof(CS.UnityEngine.UI.Image))
---@type UnityEngine.UI.Image
self.WrongMark = self:FindObj("WrongMark"):GetComponent(typeof(CS.UnityEngine.UI.Image))
---@type UnityEngine.UI.Image
self.righttMark1 = self:FindObj("righttMark1")
---@type UnityEngine.UI.Image
self.righttMark2 = self:FindObj("righttMark2")
---@type UnityEngine.UI.Image
self.righttMark3 = self:FindObj("righttMark3")
---@type UnityEngine.UI.Image
self.righttMark4 = self:FindObj("righttMark4")
---@type UnityEngine.UI.Image
self.righttMark5 = self:FindObj("righttMark5")
---@type UnityEngine.UI.Image
self.righttMark6 = self:FindObj("righttMark6")
---@type UnityEngine.UI.Image
self.righttMark7 = self:FindObj("righttMark7")
--UINameTable init end
--UIVariableTable init start
--UIVariableTable init end
--self.testGo1 = MissionManager.Instance:GetGameObject("XXX")
---@type UnityEngine.GameObject[]
self.upPositions = {
self.upimg1,
self.upimg2,
self.upimg3,
self.upimg4,
self.upimg5,
self.upimg6,
self.upimg7
}
---@type UnityEngine.GameObject[]
self.downPositions = {
self.downimg1,
self.downimg2,
self.downimg3,
self.downimg4,
self.downimg5,
self.downimg6,
self.downimg7
}
---@type UnityEngine.GameObject[]
self.images = {
self.xiShouImg1,
self.xiShouImg2,
self.xiShouImg3,
self.xiShouImg4,
self.xiShouImg5,
self.xiShouImg6,
self.xiShouImg7
}
---@type UnityEngine.UI.Image[]
self.rightMarks = {}
self.rightMarks[1] = self.righttMark1:GetComponent(typeof(CS.UnityEngine.UI.Image))
self.rightMarks[2] = self.righttMark2:GetComponent(typeof(CS.UnityEngine.UI.Image))
self.rightMarks[3] = self.righttMark3:GetComponent(typeof(CS.UnityEngine.UI.Image))
self.rightMarks[4] = self.righttMark4:GetComponent(typeof(CS.UnityEngine.UI.Image))
self.rightMarks[5] = self.righttMark5:GetComponent(typeof(CS.UnityEngine.UI.Image))
self.rightMarks[6] = self.righttMark6:GetComponent(typeof(CS.UnityEngine.UI.Image))
self.rightMarks[7] = self.righttMark7:GetComponent(typeof(CS.UnityEngine.UI.Image))
-- 初始化变量
self.imageStepMap = {} -- 图片到步骤的映射
self.positionToImage = {} -- 位置到图片的映射
self.imageToPosition = {} -- 图片到位置的映射
self.dragStartPositions = {} -- 拖拽起始位置
-- 设置图片的步骤映射 (1-7)
for i, img in ipairs(self.images) do
self.imageStepMap[img] = i
end
-- 初始化按钮状态
self:XianYin(self.btn_TiJiao, 0)
self:XianYin(self.btn_zhengQue, 0)
self:XianYin(self.btn_NextStep, 0)
-- 初始化拖拽功能
self:InitDrag()
-- 随机排列下方图片
self:ShuffleDownImages()
-- 记录画布平面的Z位置
self.canvasZ = self.transform.position.z
end
-- 销毁前调用
function UIXiShouPaiXun:ReleaseCallBack()
-- override
--UINameTable delete start
self.upimg1 = nil
self.upimg2 = nil
self.upimg3 = nil
self.upimg4 = nil
self.upimg5 = nil
self.upimg6 = nil
self.upimg7 = nil
self.downimg1 = nil
self.downimg2 = nil
self.downimg3 = nil
self.downimg4 = nil
self.downimg5 = nil
self.downimg6 = nil
self.downimg7 = nil
self.xiShouImg1 = nil
self.xiShouImg2 = nil
self.xiShouImg3 = nil
self.xiShouImg4 = nil
self.xiShouImg5 = nil
self.xiShouImg6 = nil
self.xiShouImg7 = nil
self.btn_TiJiao = nil
self.btn_zhengQue = nil
self.CanvasUp = nil
self.CorrectMark = nil
self.WrongMark = nil
self.righttMark1 = nil
self.righttMark2 = nil
self.righttMark3 = nil
self.righttMark4 = nil
self.righttMark5 = nil
self.righttMark6 = nil
self.righttMark7 = nil
--UINameTable delete end
--UIVariableTable delete start
--UIVariableTable delete end
self.upPositions = nil
self.downPositions = nil
self.images = nil
self.rightMarks = nil
self.imageStepMap = nil
self.positionToImage = nil
self.imageToPosition = nil
self.dragStartPositions = nil
self.canvasZ = nil
end
-- 打开后调用
function UIXiShouPaiXun:OpenCallBack()
-- override
--UIEventTable init start
--点提交按钮的事件
self.onClickTiJiaoEvent = BindTool.Bind(self, self.OnClickTiJiao)
self:ListenEvent("TiJiao", self.onClickTiJiaoEvent)
--点正确答案按钮的事件
self.onClickZhengQueDaAnEvent = BindTool.Bind(self, self.OnClickZhengQueDaAn)
self:ListenEvent("ZhengQueDaAn", self.onClickZhengQueDaAnEvent)
--UIEventTable init end
for _, masks in ipairs(self.rightMarks) do
self:XianYin(masks.gameObject, 0)
end
end
-- 关闭前调用
function UIXiShouPaiXun:CloseCallBack()
-- override
--UIEventTable delete start
self:ClearEvent("TiJiao")
self.onClickTiJiaoEvent = nil
self:ClearEvent("ZhengQueDaAn")
self.onClickZhengQueDaAnEvent = nil
MissionManager.Instance:UnbindCustomBtn("下一步")
--UIEventTable delete end
end
-- 刷新,使用Flush来触发此方法。
function UIXiShouPaiXun:OnFlush(param_list)
-- override
end
-- 集中注册信息
function UIXiShouPaiXun:OnAddListener()
-- override
end
-- 集中注销消息
function UIXiShouPaiXun:OnRemoveListener()
-- override
end
---@param key string
---@param saver Nirvana.MissionSystem.Save.Saver
function UIXiShouPaiXun:Back(key, saver)
--回退
--saver:ResetGameObject(key, self.testGo1)
end
---@param key string
---@param saver Nirvana.MissionSystem.Save.Saver
function UIXiShouPaiXun:Save(key, saver, ...)
--保存
--saver:SaveGameObject(key, self.testGo1)
end
function UIXiShouPaiXun:SetParam(...)
-- override
-- 执行此方法的时候,请保证UI已经打开。
end
function UIXiShouPaiXun:Start(...)
-- override
-- 开始
-- eg 1:直接完成
-- FWGlobalEventSystem:Fire(ShiYanEventType.OPERATE_OVER, self:GetName())
-- eg 2:申请交互
-- FWGlobalEventSystem:Fire(ShiYanEventType.TRY_INTERACT, self:GetName())
end
function UIXiShouPaiXun:Imm(...)
-- override
-- 直接完成
FWGlobalEventSystem:Fire(ShiYanEventType.OPERATE_OVER, self:GetName())
end
function UIXiShouPaiXun:Stop()
-- override
-- 停止
end
function UIXiShouPaiXun:Continue()
-- override
-- eg 2:交互回调
--FWGlobalEventSystem:Fire(ShiYanEventType.OPERATE_OVER, self:GetName(),0,1)
return false
end
function UIXiShouPaiXun:Guide(...)
-- override
return false
end
function UIXiShouPaiXun:XianYin(object, a)
if object then
-- 添加空值检查
object:SetActive(a == 1)
end
end
function UIXiShouPaiXun:InitDrag()
for _, img in ipairs(self.images) do
self:AddDragEvents(img)
end
end
function UIXiShouPaiXun:AddDragEvents(img)
-- 获取或添加EventTrigger组件
local eventTrigger = img:GetComponent(typeof(CS.UnityEngine.EventSystems.EventTrigger))
if eventTrigger == nil then
eventTrigger = img:AddComponent(typeof(CS.UnityEngine.EventSystems.EventTrigger))
else
-- 清除现有事件
eventTrigger.triggers:Clear()
end
-- 开始拖拽事件
local beginEntry = CS.UnityEngine.EventSystems.EventTrigger.Entry()
beginEntry.eventID = CS.UnityEngine.EventSystems.EventTriggerType.BeginDrag
beginEntry.callback:AddListener(function()
self:OnBeginDrag(img)
end)
eventTrigger.triggers:Add(beginEntry)
-- 拖拽中事件
local dragEntry = CS.UnityEngine.EventSystems.EventTrigger.Entry()
dragEntry.eventID = CS.UnityEngine.EventSystems.EventTriggerType.Drag
dragEntry.callback:AddListener(function()
self:OnDrag(img)
end)
eventTrigger.triggers:Add(dragEntry)
-- 结束拖拽事件
local endEntry = CS.UnityEngine.EventSystems.EventTrigger.Entry()
endEntry.eventID = CS.UnityEngine.EventSystems.EventTriggerType.EndDrag
endEntry.callback:AddListener(function()
self:OnEndDrag(img)
end)
eventTrigger.triggers:Add(endEntry)
end
-- 随机排列下方图片
function UIXiShouPaiXun:ShuffleDownImages()
-- 重置所有映射关系
self.positionToImage = {}
self.imageToPosition = {}
local t = { 1, 2, 3, 4, 5, 6, 7 }
-- 创建1-7的随机顺序
local randomOrder = self:ShuffleArray(t)
-- 将图片放置到随机位置
for i, img in ipairs(self.images) do
local pos = self.downPositions[randomOrder[i]]
img.transform:SetParent(pos.transform)
img.transform.localPosition = Vector3.zero
img.transform:SetAsLastSibling() -- 确保显示在最上层
end
end
-- 开始拖拽处理
function UIXiShouPaiXun:OnBeginDrag(img)
-- 记录当前拖拽的图片
self.draggingImage = img
-- 记录拖拽前的父对象和位置
self.dragStartParent = img.transform.parent
self.dragStartPosition = img.transform.localPosition
-- 记录原始Z坐标
self.originalZ = img.transform.position.z
-- 提升层级到最上层
img.transform:SetParent(self.transform)
img.transform:SetAsLastSibling()
end
-- 拖拽中处理(跟随鼠标移动)
function UIXiShouPaiXun:OnDrag(img)
-- 获取鼠标位置
local mousePos = CS.UnityEngine.Input.mousePosition
-- 获取画布相机
local camera = self.CanvasUp.worldCamera
if camera == nil then
camera = CS.UnityEngine.Camera.main
end
-- 确保有相机
if camera then
-- 计算从相机到画布平面的距离
local distance = math.abs(camera.transform.position.z - self.canvasZ)
-- 将屏幕坐标转换为世界坐标
local worldPos = camera:ScreenToWorldPoint(
CS.UnityEngine.Vector3(mousePos.x, mousePos.y, distance)
)
-- 保持原始Z坐标
worldPos = CS.UnityEngine.Vector3(worldPos.x, worldPos.y, self.originalZ)
img.transform.position = worldPos
end
end
-- 结束拖拽处理
function UIXiShouPaiXun:OnEndDrag(img)
local hitPosition = nil
-- 检查上方位置
for _, pos in ipairs(self.upPositions) do
if self:IsPointInRect(pos, img) then
hitPosition = pos
break
end
end
-- 检查下方位置
if not hitPosition then
for _, pos in ipairs(self.downPositions) do
if self:IsPointInRect(pos, img) then
hitPosition = pos
break
end
end
end
if hitPosition then
self:PlaceImageToPosition(img, hitPosition)
else
-- 返回原始位置
img.transform:SetParent(self.dragStartParent)
img.transform.localPosition = self.dragStartPosition
end
self.draggingImage = nil
self:CheckAllPlaced()
end
function UIXiShouPaiXun:IsPointInRect(position, img)
if not position or not img then
return false
end
local rectTransform = position:GetComponent(typeof(CS.UnityEngine.RectTransform))
if not rectTransform then
return false
end
local camera = self.CanvasUp.worldCamera
if not camera then
camera = CS.UnityEngine.Camera.main
if not camera then
-- 如果还是没有相机,返回false
return false
end
end
local imgRectTransform = img:GetComponent(typeof(CS.UnityEngine.RectTransform))
if not imgRectTransform then
return false
end
local imgCenter = imgRectTransform.position
local screenPos = camera:WorldToScreenPoint(imgCenter)
-- 确保坐标有效(避免相机在物体后方的情况)
if screenPos.z <= 0 then
return false
end
local screenPos2 = CS.UnityEngine.Vector2(screenPos.x, screenPos.y)
return CS.UnityEngine.RectTransformUtility.RectangleContainsScreenPoint(
rectTransform,
screenPos2,
camera
)
end
-- 将图片放置到指定位置
function UIXiShouPaiXun:PlaceImageToPosition(img, position)
-- 如果位置已有图片,交换位置
if self.positionToImage[position] then
local otherImg = self.positionToImage[position]
self:SwapImages(img, otherImg)
else
-- 更新映射关系
if self.imageToPosition[img] then
self.positionToImage[self.imageToPosition[img]] = nil
end
self.positionToImage[position] = img
self.imageToPosition[img] = position
-- 设置新父对象和位置
img.transform:SetParent(position.transform)
img.transform.localPosition = Vector3.zero
-- 关键:设置为第一个子节点(底层)
img.transform:SetAsFirstSibling()
end
end
-- 交换两个图片的位置
function UIXiShouPaiXun:SwapImages(img1, img2)
local pos1 = self.imageToPosition[img1]
local pos2 = self.imageToPosition[img2]
-- 更新映射关系
self.positionToImage[pos1] = img2
self.positionToImage[pos2] = img1
self.imageToPosition[img1] = pos2
self.imageToPosition[img2] = pos1
-- 交换父对象
img1.transform:SetParent(pos2.transform)
img1.transform.localPosition = Vector3.zero
img1.transform:SetAsFirstSibling()
img2.transform:SetParent(pos1.transform)
img2.transform.localPosition = Vector3.zero
img2.transform:SetAsFirstSibling()
end
-- 检查所有上方位置是否都已放置图片
function UIXiShouPaiXun:CheckAllPlaced()
local allPlaced = true
-- 遍历所有上方位置
for _, pos in ipairs(self.upPositions) do
if not self.positionToImage[pos] then
allPlaced = false
break
end
end
-- 根据检查结果更新提交按钮状态
if self.btn_TiJiao then
self.btn_TiJiao:SetActive(allPlaced)
end
end
-- 点击提交按钮事件处理
function UIXiShouPaiXun:OnClickTiJiao()
-- 禁用所有拖拽功能
for _, img in ipairs(self.images) do
if img then
local eventTrigger = img:GetComponent(typeof(CS.UnityEngine.EventSystems.EventTrigger))
if eventTrigger then
eventTrigger.enabled = false
end
end
end
-- 检查每个位置是否正确
local allCorrect = true
for i, pos in ipairs(self.upPositions) do
local img = self.positionToImage[pos]
if img and self.imageStepMap[img] == i then
-- 位置正确,显示正确标记
self:ShowMark(img, true, i)
else
-- 位置错误,显示错误标记
self:ShowMark(img, false)
allCorrect = false
end
end
-- 更新按钮状态
if self.btn_TiJiao then
self.btn_TiJiao:SetActive(false)
end
if allCorrect then
-- 全部正确,显示下一步按钮
self:ShowNextStepButton()
else
-- 存在错误,显示正确答案按钮
if self.btn_zhengQue then
self.btn_zhengQue:SetActive(true)
end
end
end
-- 在图片上显示正确/错误标记
function UIXiShouPaiXun:ShowMark(img, isCorrect, num)
if not img then
return
end
-- 根据正确性选择标记名称
self.rightMarks[num].sprite = isCorrect and self.CorrectMark.sprite or self.WrongMark.sprite
if mark then
self:XianYin(self.rightMarks[num].gameObject, 1)
end
end
-- 隐藏所有图片上的标记
function UIXiShouPaiXun:HideAllMarks()
for i, img in ipairs(self.images) do
if img then
---- 查找正确标记
--local correctMark = img.transform:Find("CorrectMark")
--if correctMark then
-- correctMark.gameObject:SetActive(false)
--end
--
---- 查找错误标记
--local wrongMark = img.transform:Find("WrongMark")
--if wrongMark then
-- wrongMark.gameObject:SetActive(false)
--end
self:XianYin(self.rightMarks[i].gameObject, 0)
end
end
end
-- 点击"正确答案"按钮事件处理
function UIXiShouPaiXun:OnClickZhengQueDaAn()
-- 隐藏下方位置
for _, pos in ipairs(self.downPositions) do
if pos then
pos:SetActive(false)
end
end
-- 隐藏所有标记
self:HideAllMarks()
-- 将图片移动到正确位置
for i, pos in ipairs(self.upPositions) do
if pos then
local correctImg = self.images[i] -- 获取对应步骤的图片
if correctImg then
correctImg.transform:SetParent(pos.transform)
correctImg.transform.localPosition = Vector3.zero
end
end
end
---- 更新按钮状态
--if self.btn_zhengQue then
-- self.btn_zhengQue:SetActive(false)
--end
self:XianYin(self.btn_zhengQue.gameObject, 0)
-- 显示下一步按钮
self:ShowNextStepButton()
end
function UIXiShouPaiXun:ShowNextStepButton()
if self.btn_NextStep then
self.btn_NextStep:SetActive(true)
end
MissionManager.Instance:BindCustomBtn("下一步", function()
self:OnClickNextStep()
end)
end
-- 点击下一步按钮事件处理
function UIXiShouPaiXun:OnClickNextStep()
-- 触发完成事件
FWGlobalEventSystem:Fire(ShiYanEventType.OPERATE_OVER, self:GetName())
end
return UIXiShouPaiXun;】