Unity 家居摆放系统设计 (一)

您所在的位置:网站首页 宿舍桌面摆放设计好看 Unity 家居摆放系统设计 (一)

Unity 家居摆放系统设计 (一)

2024-07-14 07:35| 来源: 网络整理| 查看: 265

之前看到明日方舟的宿舍挺有趣的,可以摆放大小不一的家具在一个矩形体的六面墙上。之前写了没时间弄博客现在做下记录。

本次设计点:

1、层级结构为,根节点下面有六面墙壁,每面墙在代码里会进行大小的缩放,所以这里为保持每面墙内的物体能够按照实际大小摆放,多加了一个反向缩放的原始节点层,在里面就是格子层和家具层

顶部墙面

 

 

 底部墙面

 

 

 

 

 前部墙面

 

 

 

 垂直的面加了四条线以显示边界

 

 

 

 后部墙面

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2、房间大小、格子大小、家具大小全部动态设置,效果如下面图所示:

格子正方形,房间正方形,家具长方形

 格子长方形,房间正方形,家具正方形

房间长方形,格子正方形,家具正方形

 

 3、目前一个面一个碰撞体共6个碰撞体,为了每一面都可以求出局部坐标进而求出每个格子的坐标再换算出行列;重合检测有房间内的所有家具的边界检测,和所有家具之间的重合检测。目前没时间弄,边界检查只需判断家具靠墙的一面的长宽共4个点是否越出墙的长宽即可;至于家具之前的重合检测,初步考虑用算法,将房间分割成X*Y*Z个小六面体,每个小六面体都存储有投影到六面墙上时每一面墙上对应所有已被其他家具占用的格子,这样每次家具的移动都对n个被波及到的小六面体进行数据增删以及检测重合。或者考虑用八叉树处理优化下。具体有空再试试

4、未精简优化代码:

控制器:

module("room.RoomController", Class.impl(Controller)) --构造函数 function ctor(self, cusMgr) super.ctor(self, cusMgr) end --析构函数 function dtor(self) end -- Override 重新登录 function reLogin(self) super.reLogin(self) end --游戏开始的回调 function gameStartCallBack(self) end --模块间事件监听 function listNotification(self) GameDispatcher:addEventListener(room.RoomManager.OPEN_ROOM_PANEL, self.__onOpenRoomPanelHandler, self) end --注册server发来的数据 function registerMsgHandler(self) return {} end function __onOpenRoomPanelHandler(self, args) self:__addFrameHandler() self:__openRoomScene() room.RoomManager:setMainUICameraVisible(false) if(not self.mRoomPanel)then self.mRoomPanel = room.RoomPanel.new() self.mRoomPanel:addEventListener(View.EVENT_VIEW_DESTROY, self.onDestroyRoomPanelHandler,self) end self.mRoomPanel:open() end function onDestroyRoomPanelHandler(self) self:__removeFrameHandler() self:__closeRoomScene() room.RoomManager:setMainUICameraVisible(true) self.mRoomPanel:removeEventListener(View.EVENT_VIEW_DESTROY,self.onDestroyRoomPanelHandler,self) self.mRoomPanel = nil end ---------------------------------------------------------------场景-------------------------------------------------------------------------- function __addFrameHandler(self) LoopManager:addFrame(1, 0, self, self.__frameUpdate) end function __removeFrameHandler(self) LoopManager:removeFrame(self, self.__frameUpdate) end function __frameUpdate(self) if(gs.Input:GetMouseButton(0))then local sceneCamera = room.RoomManager:getSceneCamera():GetComponent(ty.Camera) local hitInfo = gs.UnityEngineUtil.RaycastByUICamera(sceneCamera, "", 100) if(hitInfo) then local transform = hitInfo.transform if(transform)then if(string.find(transform.name, "WALL_") ~= nil)then local needUpdate = false local dirType = room.getDirType(transform.name) if(self.mCurDirType ~= dirType)then needUpdate = true local oldIndex = self.mCurIndex local oldDirType, newDirType = self.mCurDirType, dirType self.mCurDirType = dirType self:changeTileMaterial(oldDirType, nil) local thing = self.mThingDic[oldDirType][oldIndex] self.mThingDic[oldDirType][oldIndex] = nil thing.transform:SetParent(self.mThingNodeDic[newDirType].transform, false) local localPos = self.mThingNodeDic[newDirType].transform:InverseTransformPoint(hitInfo.point) local row, col = self:getRowColByPos(newDirType, localPos.x, localPos.y) local index = self:getTileIndexByRowCol(newDirType, row, col) self.mCurIndex = index if(not self.mThingDic[newDirType])then self.mThingDic[newDirType] = {} end self.mThingDic[newDirType][self.mCurIndex] = thing else local localPos = self.mThingNodeDic[self.mCurDirType].transform:InverseTransformPoint(hitInfo.point) local row, col = self:getRowColByPos(self.mCurDirType, localPos.x, localPos.y) local index = self:getTileIndexByRowCol(self.mCurDirType, row, col) if(self.mCurIndex ~= index)then needUpdate = true local oldIndex = self.mCurIndex self.mCurIndex = index local thing = self.mThingDic[self.mCurDirType][oldIndex] self.mThingDic[self.mCurDirType][oldIndex] = nil self.mThingDic[self.mCurDirType][self.mCurIndex] = thing end end -- 直接跟随鼠标坐标 if(needUpdate)then local localPos = self.mThingNodeDic[self.mCurDirType].transform:InverseTransformPoint(hitInfo.point) local thingId = room.RoomManager:getThingIdByIndex(self.mCurIndex) local thingConfigVo = room.RoomManager:getThingConfigVo(thingId) localPos.z = localPos.z + thingConfigVo:getSizeY() / 2 self.mThingDic[self.mCurDirType][self.mCurIndex].transform.localPosition = localPos self:changeTileMaterial(self.mCurDirType, self.mCurIndex) end -- 直接跟随鼠标坐标对应的格子 if(needUpdate)then local thingId = room.RoomManager:getThingIdByIndex(self.mCurIndex) local thingConfigVo = room.RoomManager:getThingConfigVo(thingId) local tileX, tileY = self:getTilePos(self.mCurDirType, self.mCurIndex) gs.TransQuick:LPos(self.mThingDic[self.mCurDirType][self.mCurIndex].transform, tileX, tileY, thingConfigVo:getSizeY() / 2) self:changeTileMaterial(self.mCurDirType, self.mCurIndex) end end end end end end function __initSceneData(self) -- 房间场景的各个物体字典 self.mWallDic = {} self.mOriginalNodeDic = {} self.mThingNodeDic = {} self.mTileNodeDic = {} -- 房间场景的所有格子字典 self.mTileIndexDic = {} -- 房间场景的所有物件字典 self.mThingDic = {} end function __openRoomScene(self) self:__initSceneData() -- 初始化 self.mRoomScene = AssetLoader.GetGO(UrlManager:getPrefabPath('ui/room/Scene_RoomRoot.prefab')) local childGods, childTrans = GoUtil.GetChildHash(self.mRoomScene) local dirTypeList = {} table.insert(dirTypeList, room.DIR_TOP) table.insert(dirTypeList, room.DIR_BOTTOM) table.insert(dirTypeList, room.DIR_FRONT) table.insert(dirTypeList, room.DIR_BEHIND) table.insert(dirTypeList, room.DIR_LEFT) table.insert(dirTypeList, room.DIR_RIGHT) -- 初始化各个节点 for i = 1, #dirTypeList do local dirType = dirTypeList[i] self.mWallDic[dirType] = self:getWallNodeName(childGods, dirType) self.mOriginalNodeDic[dirType] = self:getOriginalNodeName(childGods, dirType) self.mThingNodeDic[dirType] = self:getThingNodeName(childGods, dirType) self.mTileNodeDic[dirType] = self:getTileNodeName(childGods, dirType) end -- 场景大小设置 local roomSizeX, roomSizeY, roomSizeZ = room.RoomManager:getRoomSize() gs.TransQuick:Pos(self.mRoomScene.transform, 0, 500, roomSizeZ / 2) -- 6面墙的位置 gs.TransQuick:LPos(self.mWallDic[room.DIR_TOP].transform, 0, roomSizeY / 2, 0) gs.TransQuick:LPos(self.mWallDic[room.DIR_BOTTOM].transform, 0, -roomSizeY / 2, 0) gs.TransQuick:LPos(self.mWallDic[room.DIR_FRONT].transform, 0, 0, roomSizeZ / 2) gs.TransQuick:LPos(self.mWallDic[room.DIR_BEHIND].transform, 0, 0, -roomSizeZ / 2) gs.TransQuick:LPos(self.mWallDic[room.DIR_RIGHT].transform, roomSizeX / 2, 0, 0) gs.TransQuick:LPos(self.mWallDic[room.DIR_LEFT].transform, -roomSizeX / 2, 0, 0) -- 6面墙的大小 local sideDepth = room.RoomManager:getSideDepth() gs.TransQuick:Scale(self.mWallDic[room.DIR_TOP].transform, roomSizeX, roomSizeZ, sideDepth) gs.TransQuick:Scale(self.mWallDic[room.DIR_BOTTOM].transform, roomSizeX, roomSizeZ, sideDepth) gs.TransQuick:Scale(self.mWallDic[room.DIR_FRONT].transform, roomSizeX, roomSizeY, sideDepth) gs.TransQuick:Scale(self.mWallDic[room.DIR_BEHIND].transform, roomSizeX, roomSizeY, sideDepth) gs.TransQuick:Scale(self.mWallDic[room.DIR_RIGHT].transform, roomSizeZ, roomSizeY, sideDepth) gs.TransQuick:Scale(self.mWallDic[room.DIR_LEFT].transform, roomSizeZ, roomSizeY, sideDepth) -- 6面墙缩放后,墙内总结点反向缩放,以使总结点内的所有物体都能按照通用标准大小 gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_TOP].transform, 1 / roomSizeX, 1 / roomSizeZ, 1 / sideDepth) gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_BOTTOM].transform, 1 / roomSizeX, 1 / roomSizeZ, 1 / sideDepth) gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_FRONT].transform, 1 / roomSizeX, 1 / roomSizeY, 1 / sideDepth) gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_BEHIND].transform, 1 / roomSizeX, 1 / roomSizeY, 1 / sideDepth) gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_RIGHT].transform, 1 / roomSizeZ, 1 / roomSizeY, 1 / sideDepth) gs.TransQuick:Scale(self.mOriginalNodeDic[room.DIR_LEFT].transform, 1 / roomSizeZ, 1 / roomSizeY, 1 / sideDepth) -- 场景添加格子 for i = 1, #dirTypeList do local dirType = dirTypeList[i] self:addTileToWall(dirType) end -- local id = 0 -- for i = 1, #dirTypeList do -- id = id + 1 -- local dirType = dirTypeList[i] -- self:addThingToWall(dirType, id) -- end -- 初始加一个在底部 self.mCurDirType = room.DIR_BOTTOM self.mCurIndex = 1 self:addThingToWall(self.mCurDirType, self.mCurIndex) end function changeTileMaterial(self, dirType, index) if(index)then local tileX, tileY = self:getTilePos(dirType, index) local thingX, thingY = tileX, tileY local thingId = room.RoomManager:getThingIdByIndex(index) local thingConfigVo = room.RoomManager:getThingConfigVo(thingId) local thingSizeX, thingSizeY, thingSizeZ = thingConfigVo:getSize() -- index所在点占据的格子范围包含的最小坐标和最大坐标(加减0.001是取巧做法,基本可以减少坐标点避免刚好落在tile边界上的概率) local thingMinX = thingX - thingSizeX / 2 + 0.001 local thingMaxX = thingX + thingSizeX / 2 - 0.001 local thingMinY = thingY - thingSizeY / 2 + 0.001 local thingMaxY = thingY + thingSizeY / 2 - 0.001 -- index所在点占据的格子范围包含的最小行列和最大行列 local minCol = self:getColByPosX(dirType, thingMinX) local maxCol = self:getColByPosX(dirType, thingMaxX) local minRow = self:getRowByPosY(dirType, thingMinY) local maxRow = self:getRowByPosY(dirType, thingMaxY) -- 刷格子对应颜色 local indexDic = self.mTileIndexDic[dirType] for _index, tile in pairs(indexDic) do local _row, _col = self:getRowColByIndex(dirType, _index) if((_row >= minRow and _row = minCol and _col


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3