下载 App

街道 NPC 行为系统

07/176 浏览综合
对应主调度:scripts/game/StreetScene.lua 核心状态机:scripts/game/street/NPCBehavior.lua 相关行为插件:scripts/game/street/NPCCore.lua、NPCEconomy.lua、Education.lua、Hospital.lua、Pharmacy.lua、StrikeParade.lua、NPCDialogue.lua、NPCSavings.lua
模块定位 街道 NPC 行为系统负责把 NPC 的日常活动组织成一个状态机循环:
家 → 目标建筑 → 出来 → 回家 / 游荡
NPC 在移动过程中,不只是“走路”,还会顺便触发:
探索 消费 工作 学习 医疗 罢工 储蓄与净值变化 气泡与心声表现 这个系统本质上不是单一寻路模块,而是**“状态机 + 行为插件链”**。
插件化分层
  1. StreetScene.lua:场景调度器 StreetScene.lua 不直接实现 NPC 细节逻辑,而是负责:
初始化共享状态 S 初始化各街道子模块 每帧转发 Update 每帧转发输入与渲染 在每日结算时调度统计与同步 2. NPCBehavior.lua:NPC 状态机插件 NPCBehavior.UpdateNPC(npc, dt, currentTime) 是 NPC 行为的主循环。
它负责:
状态切换 目标建筑到达判断 建筑内停留逻辑 退出建筑后的分流 罢工状态分支 3. NPCCore.lua:移动与目标决策插件 负责:
选择目标建筑 向目标移动 卡住检测 绕路与重试 发现新建筑 出生 / 生成相关辅助逻辑 4. NPCEconomy.lua:经济行为插件 负责 NPC 到达建筑后的经济动作:
消费 娱乐 借贷 工资相关行为 5. Education.lua:学习插件 负责:
学时计算 资质解锁 学校停留时长 毕业判定 6. Hospital.lua / Pharmacy.lua:医疗插件 负责:
就医 分娩 治疗 买药 7. StrikeParade.lua:罢工插件 负责:
罢工策略判定 游行队列加入 罢工移动状态 8. NPCDialogue.lua:表现层插件 负责:
气泡文本 NPC 心声 状态反馈展示 9. NPCSavings.lua:储蓄与净值插件 负责:
储蓄 净值计算 esteem 联动 家庭财务表现 10. AssetPanel.lua、AuctionHouse.lua、BidAuction.lua、Factory.lua 这些模块不直接控制 NPC 状态机,但会作为外围行为插件参与 NPC 的经济生命周期:
AssetPanel.lua:展示资产与统计结果 AuctionHouse.lua:商品交易与上架 BidAuction.lua:竞拍交易 Factory.lua:工厂打工、工资、生产触发点 11. GlobalEvent.lua 全球事件模块作为环境修正插件,会影响 NPC 的:
工资 价格 商品修正 需求衰减 它不参与移动决策,但会改变 NPC 在到达目标后的收益和消费结果。
  1. network/Shared.lua:网络共享协议插件 Shared.lua 是客户端和服务端共用的协议层插件,不直接执行 NPC 行为,也不直接处理建筑面板逻辑。
它负责把街道系统中会跨客户端、服务端、云端流转的数据统一成稳定格式,避免各业务插件各自定义事件名、云端 key 或序列化字段。
12.1 事件名统一 Shared.EVENTS 集中定义所有 RemoteEvent 名称。
它覆盖三类事件:
类型 说明 例子 客户端请求 玩家进入区域、修改建筑、保存状态、发起交易 ENTER_REGION、BUILDING_CHANGED、SAVE_PLAYER_STATE、TRADE_STOCK 服务端响应 返回区域数据、邻区数据、排行榜、交易结果 REGION_DATA、NEIGHBOR_DATA、PLAYER_RANK_DATA、AUCTION_RESULT 子系统事件 股票、交易行、拍卖行、全球事件、树木、大宗商品 BATCH_NPC_TRADES、QUERY_AUCTIONS、PUBLISH_GLOBAL_EVENT、TRADE_COMMODITY Shared.RegisterEvents() 统一遍历 Shared.EVENTS 并注册 RemoteEvent。
插件化约束:
新增网络子系统时,先在 Shared.EVENTS 增加事件名。 客户端和服务端都引用同一个事件常量,禁止手写散落字符串。 事件名只表达协议语义,不绑定具体 UI 或 NPC 行为实现。 12.2 云端 key 统一 Shared.lua 集中生成 serverCloud 存储 key,把数据隔离维度写进 key 名称。
key 函数 数据归属 隔离维度 RegionKey(regionName) 建筑数据 区域 / 区块 TreeKey(regionName) 树木数据 区域 / 区块 NPCKey(regionName) NPC 全量快照 区域 / 区块 StockMarketKey(regionName) 股票市场 国家 StockHoldingsKey(regionName) 玩家股票持仓 玩家 + 国家 CommodityMarketKey(regionName) 大宗商品市场 国家 ChunkSummaryKey(regionName, chunkId) 区块经济摘要 国家 + 区块 PlayerRankKey() 玩家资产排行 全局 AuctionKey(country) 交易行挂单池 国家 ShipmentKey(country, chunkId) 在途货物 国家 + 区块 TradeLogKey(userId) 交易记录 / 货币库 玩家 GlobalEventKey() 全球事件 全局 BidAuctionKey() 拍卖池 全局 BidTradeLogKey(userId) 拍卖交易记录 / 货币库 玩家 插件化约束:
新增持久化数据时,必须先明确 key 的隔离维度:全局、国家、区块、玩家,或它们的组合。 业务模块不得自行拼接云端 key,统一通过 Shared.lua 的函数生成。 如果全局数据按国家隔离,对应的玩家私有数据也要按国家隔离,避免跨国串档。 12.3 建筑 / NPC 数据序列化统一 Shared.SerializeBuilding(b, isNew) 把运行时建筑对象转换成云端可存的精简 table。
它按建筑类型保存不同字段:
建筑类别 主要持久化字段 通用建筑 所有权、ownerId、类型、名称、坐标尺寸、拆迁标记、建成日、工资倍率 商铺 / 超市 / 批发市场 库存、零售价、进口库存、子类型库存、手动定价标记 工厂 生产品类、年度销量、股票名、定价模式、手动批发价、AI 选品状态 学校 / 医院 / 药房 学费、学校等级、诊疗费、接生费、药品库存、药品零售价 住宅 户型、建造状态、地皮价、租金、出售状态、家庭库存 银行 资本金、投资者、贷款、分红、NPC 存款池、存款利息结算日 社区基金 净值、份额、福利池、基金持仓、投资者、分红与救济统计 区府 金库、税率、养老金库、贷款、工程项目、环境分数、自治社区状态 Shared.SerializeNPC(npc) 把单个 NPC 转换成云端可存快照。
它保存:
NPC 数据类别 主要字段 生命周期 死亡、年龄阶段、出生日期 家庭关系 伴侣、孩子、父母、住宅 生育状态 怀孕、剩余天数、生育冷却 教育与需求 学时、需求值、需求层级 经济状态 现金、贷款、储蓄、基金、福利领取 经济认知 批发认知、进口认知、广告商品需求 医疗状态 疾病、病程、买药需求 服装 / 活动 穿着、季节、最近活动 出走系统 grievance、exodus 认知、贡献、角色 表现素材 个人故事 / 心声素材 Shared.SerializeAllNPCs(npcs) 用 { version = 1, npcs = arr } 保存 NPC 全量快照。
插件化约束:
新增建筑持久字段时,必须进入 SerializeBuilding,并在恢复侧保持字段名一致。 新增 NPC 持久字段时,必须进入 SerializeNPC,并在恢复侧保持字段名一致。 会话态字段如当前移动状态、目标点、卡住计数不进入 Shared 序列化,除非它跨会话不可重算。 业务插件只负责产生状态变化,跨端协议和云端快照统一交给 Shared.lua。 NPC 寻路系统 设计定位 当前 NPC 寻路不是 A* 网格寻路,而是:
目标点直线力驱动 + 建筑碰撞 + 卡住检测 + 侧向绕路航点 + 兜底换目标 / 传送。
这样做的原因:
街道是经营模拟场景,NPC 数量较多,需要轻量移动。 建筑是主要障碍物,复杂路径图维护成本高。 NPC 行为重点在经济与状态机,不是精确导航。 道路系统只作为速度加成和视觉/探索层,不强制所有 NPC 沿道路走。 插件化边界 插件 职责 不负责 NPCBehavior.lua 状态切换:什么时候出门、去哪、何时回家 具体绕路算法 NPCCore.lua 普通 NPC 目标选择、移动、卡住检测、绕路、探索 到达后的消费 / 学习 / 医疗结算 Delivery.lua 送货 NPC 去程、入库、回程、路线缓存 普通 NPC 日常状态机 NPCEconomy / Education / Hospital 等 到达建筑后的业务行为 直接操控路径 Shared.lua 持久化协议与序列化 保存 stuckCount / detourX/Y 等会话寻路字段 普通 NPC 寻路流程 阶段 代码入口 说明 目标选择 NPCCore.PickRandomTarget(npc) 根据医疗、饥饿、家庭采购、上学、打工、消费等优先级选择建筑 进入移动状态 NPCBehavior.UpdateNPC 的 going_to_target 分支 调用探索、卡住检测、移动、到达判定 力驱动移动 NPCCore.MoveToward(npc, x, y, dt) 根据目标方向对刚体施力,接近目标返回 true 道路加速 NPCCore.MoveToward 内部 当前像素落在 S.trail.grid[row][col] == "road" 时提高最大速度 探索记录 NPCCore.MoveToward / NPCCore.CheckDiscovery 移动时标记探索区域、脚印,定期发现附近未知建筑 卡住检测 NPCCore.HandleStuckDetection 每 1.5 秒检查位移进展,进展过小则累加 stuckCount 绕路航点 NPCCore.FindDetourWaypoint 沿垂直于移动方向的两侧尝试多个距离,选择可走且更接近目标的一侧 失败兜底 NPCBehavior.lua 前往目标时卡住 4 次换目标;回家时卡住 4 次强制传送回家 普通 NPC 关键代码 文件位置 关键代码 作用 scripts/game/street/NPCCore.lua:169 function NPCCore.PickRandomTarget(npc) 按需求、年龄、现金、认知范围选择目标建筑 scripts/game/street/NPCBehavior.lua:107 elseif npc.state == "going_to_target" then 普通 NPC 前往目标建筑的状态机分支 scripts/game/street/NPCBehavior.lua:116 NPCCore.HandleStuckDetection(npc, target.entPhysX, target.entPhysY, dt) 移动前先处理卡住 / 绕路 scripts/game/street/NPCBehavior.lua:127 NPCCore.MoveToward(npc, target.entPhysX, target.entPhysY, dt) 未绕路时朝建筑入口移动 scripts/game/street/NPCCore.lua:735 function NPCCore.MoveToward(npc, targetPhysX, targetPhysY, dt) 直线力驱动移动、道路加速、探索脚印 scripts/game/street/NPCCore.lua:788 IsPointBlockedByBuilding(px, py, margin) 判断候选绕路点是否撞进建筑矩形 scripts/game/street/NPCCore.lua:809 function NPCCore.FindDetourWaypoint(npc, targetPhysX, targetPhysY) 生成侧向绕路点 scripts/game/street/NPCCore.lua:860 function NPCCore.HandleStuckDetection(npc, targetPhysX, targetPhysY, dt) 统一卡住检测与绕路状态管理 scripts/game/street/NPCCore.lua:918 function NPCCore.CheckDiscovery(npc, dt) 移动 / 闲逛时发现未知建筑和邻区信息 scripts/game/street/NPCBehavior.lua:903 elseif npc.state == "going_home" then 回家路径使用同一套卡住检测,失败时传送回家 普通 NPC 关键字段 字段 类型 持久化 说明 targetIdx 会话态 否 当前目标建筑索引,可重新选择 knownBuildings 认知状态 视设计而定 NPC 已发现的建筑集合,影响目标选择;若要求跨会话保留,应进入 SerializeNPC stuckCount 会话态 否 连续卡住次数 stuckCheckTimer 会话态 否 卡住检测计时器 lastProgressX/Y 会话态 否 上次进展检查位置 detourX/Y 会话态 否 当前绕路航点 _wanderX/Y 会话态 否 闲逛、包工头招工、施工等临时目标点 footprintCD 表现 / 探索态 否 脚印生成冷却 普通 NPC 移动伪代码 lua
复制 -- NPCBehavior.lua: going_to_target NPCCore.CheckDiscovery(npc, dt) local detouring = NPCCore.HandleStuckDetection(npc, target.entPhysX, target.entPhysY, dt)
if npc.stuckCount >= 4 then npc.targetIdx = NPCCore.PickRandomTarget(npc) npc.stuckCount = 0 elseif not detouring then local arrived = NPCCore.MoveToward(npc, target.entPhysX, target.entPhysY, dt) if arrived then -- 容量 / 冷却检查通过后进入 inside end end lua
复制 -- NPCCore.lua: MoveToward 核心思想 local dx, dy = targetPhysX - pos.x, targetPhysY - pos.y local dist = math.sqrt(dx * dx + dy * dy) if dist < 0.05 then return true end
local force = npc.moveForce local fx = (dx / dist) * force local fy = (dy / dist) * force
-- 如果脚下是 road,提升速度上限 if S.trail.grid[row][col] == "road" then effectiveMaxSpeed = npc.maxSpeed * roadSpeedMultiplier end
if currentSpeed < effectiveMaxSpeed then npc.body:ApplyForceToCenter(Vector2(fx, fy), true) end lua
复制 -- NPCCore.lua: FindDetourWaypoint 核心思想 -- 1. 优先取当前速度方向,速度太小时回退到目标方向 -- 2. 计算垂直方向的左右两个侧向 -- 3. 依次尝试 2.0 / 3.5 / 1.2 / 5.0 米 -- 4. 候选点必须在地图 mask 内,且不能落入建筑矩形 -- 5. 两边都可走时,选择离目标更近的一边 闲逛与特殊移动 状态 移动方式 说明 wandering 随机点 + MoveToward 在附近随机选 _wanderX/Y,老人范围更大 going_to_neighbor 朝邻区方向边界点移动 到边界后隐藏,进入邻区外出模拟 contractor_recruiting 随机点 + 附近 NPC 扫描 包工头在街上移动并招工 contractor_working 施工前线附近随机点 跟随道路工程进度活动 construction_working 施工前线附近随机点 工人在道路施工前线附近活动 strike_marching leader 定速 / follower MoveToward 罢工游行沿 StrikeParade 路线列队移动 going_home 家门口目标点 + 卡住检测 多次失败后直接传送回家,避免夜晚卡死 送货 NPC 路线缓存 送货 NPC 的路线系统在 Delivery.lua 中独立实现,和普通 NPC 寻路相似但多了“路线学习”。
文件位置 关键代码 作用 scripts/game/street/Delivery.lua:20 S.routeCache = S.routeCache or {} 会话级路线缓存,key 为 fromIdx->toIdx scripts/game/street/Delivery.lua:25 Delivery.InvalidateRouteCache(bldgIdx) 建筑搬迁 / 拆除时清理相关路线 scripts/game/street/Delivery.lua:70 FindDetourWaypoint(dnpc, targetPhysX, targetPhysY) 送货 NPC 侧向绕路航点 scripts/game/street/Delivery.lua:149 HandleStuckDetection(dnpc, targetPhysX, targetPhysY, dt) 送货 NPC 卡住、绕路、传送兜底 scripts/game/street/Delivery.lua:285 local cachedRoute = S.routeCache and S.routeCache[cacheKey] 创建送货 NPC 时读取缓存路线 scripts/game/street/Delivery.lua:299 breadcrumbs = {} 首次路线记录的面包屑航点 scripts/game/street/Delivery.lua:304 cachedWaypoints = nil 有缓存时使用深拷贝航点列表 scripts/game/street/Delivery.lua:530 S.routeCache[dnpc.cacheKey] = route 首次成功送达后缓存路线 scripts/game/street/Delivery.lua:582 local waypoints = dnpc.cachedWaypoints or dnpc.breadcrumbs 回程沿缓存或面包屑倒序返回 送货 NPC 路线伪代码 lua
复制 -- Delivery.lua: 创建送货 NPC local cacheKey = tostring(fromIdx) .. "->" .. tostring(toIdx) local cachedRoute = S.routeCache and S.routeCache[cacheKey]
if cachedRoute then dnpc.cachedWaypoints = deepcopy(cachedRoute) dnpc.cachedWpIdx = 1 else dnpc.breadcrumbs = {} end lua
复制 -- Delivery.lua: 去程 if cachedWaypoints then -- 先逐个走缓存航点,再直奔终点 else -- 直奔终点,同时每移动约 1 米记录一个 breadcrumb end
if arrivedAtTarget then Building.NotifyChange("slot_" .. dnpc.toIdx, b) if not cachedWaypoints and #breadcrumbs > 0 then S.routeCache[cacheKey] = breadcrumbs end dnpc.state = "returning" end lua
复制 -- Delivery.lua: 回程 local waypoints = dnpc.cachedWaypoints or dnpc.breadcrumbs -- 从最后一个航点开始倒序走,走完后回到出发建筑 寻路系统持久化边界 数据 是否持久化 原因 NPC 当前 state / targetIdx 否 进入区块后可重新推导,属于会话行为 stuckCount / detourX/Y 否 卡住检测临时状态,跨会话保留反而会污染新路径 routeCache 否 建筑搬迁 / 拆除后容易失效,当前作为会话级优化 breadcrumbs / cachedWaypoints 否 单个送货 NPC 生命周期内使用 knownBuildings 视设计而定 如果希望 NPC 认知跨会话保留,应进入 SerializeNPC;如果认为可由探索重建,则保持会话态 建筑库存变化 是 送货到达后通过 Building.NotifyChange + Shared.SerializeBuilding 进入云端 设计注意事项 普通 NPC 没有全局路线缓存,避免所有人挤同一条路线。 送货 NPC 有路线缓存,因为同一批发市场到同一商铺路线重复度高。 绕路点必须同时检查地图 mask 和建筑矩形,不能只检查边界。 卡住检测必须有兜底:普通 NPC 换目标 / 回家传送,送货 NPC 多次失败后传送到目标。 搬迁 / 拆除建筑时必须清理送货路线缓存,否则旧航点可能穿过新建筑布局。 routeCache、detourX/Y、stuckCount 都是会话态,不应写入 Shared.lua。 状态机主线 基础状态链 状态 含义 sleeping 在家睡觉 exiting_home 从家中出门 going_to_target 前往目标建筑 inside 在建筑内停留 exiting 从建筑出来 going_home 返回家中 wandering 游荡 / 闲逛 特殊状态 状态 含义 strike_marching 罢工游行中 contractor_recruiting 包工头招工阶段 NPC“走路”主流程
  1. 睡觉 NPC 默认处于 sleeping。
到达白天出门时段后才会开始移动。
  1. 出门 进入 exiting_home 后:
NPC 被放到家门口 根据编号生成出门延迟 延迟结束后进入目标前往阶段 3. 前往目标建筑 进入 going_to_target 后:
目标由 NPCCore.PickRandomTarget(npc) 选择 NPC 朝目标建筑移动 移动途中仍可触发探索 途中会进行卡住检测 4. 到达建筑 进入 inside 后:
开始执行建筑对应业务 停留时间由建筑类型决定 到点后退出建筑 5. 出来后分流 进入 exiting 后:
可能回家 可能继续游荡 可能加入罢工游行 某些角色还可能进入扩展分支 6. 回家或游荡 NPC 最终会回到:
going_home sleeping 或 wandering 然后等待下一轮循环。
途中会触发的行为 探索 NPC 在路上可能发现新建筑或新区域。
这会影响后续目标选择和认知传播。
消费 到达商铺、超市、餐厅等建筑时,NPC 可能消费。
工作 到达工厂或服务业建筑时,NPC 可能打工并领取工资。
学习 到达学校时,NPC 会累计学时、付学费、解锁资质。
医疗 到达医院或药房时,NPC 会治疗、分娩或买药。
罢工 当策略判定为罢工时,NPC 会跳出普通移动流程,转入游行逻辑。
目标建筑与行为映射 建筑类型 触发行为 factory 打工、领工资、生产商品 school 上学、学时累计、资质解锁 shop / supermarket / restaurant 消费、服务业打工、娱乐 hospital 治疗、分娩 pharmacy 买药 districtGov 接单 / 包工头相关 wholesale 获得“便宜”认知 bank 贷款 auctionHouse / bidAuction 交易相关延伸行为 行为触发链
  1. 到达前 选择目标 移动 探索 卡住检测
  2. 到达时 记录访问 判断容量 判断冷却 触发消费 / 工作 / 学习 / 医疗 / 借贷
  3. 出来后 更新认知 更新策略 进入游行 / 回家 / 游荡 关键认知与状态字段 字段 作用 targetIdx 当前目标建筑 state 当前行为状态 stateTimer 当前状态已持续时间 stuckCount 卡住次数 stuckCheckTimer 卡住检测计时 detourX/Y 绕路中间点 wholesaleAware 是否知道批发市场便宜 lastActivity 最近一次活动类型 currentStrategy 当前策略,如 strike schoolEnterTime 入学时刻 pregnant 是否怀孕 sick 是否生病 hospitalReason 就医原因 awayInNeighbor 是否在邻区外出中 插件边界说明 StreetScene 只负责调度 StreetScene.lua 只做统一转发,不直接写死业务规则。
NPCBehavior 只负责状态机 状态切换逻辑集中在 NPCBehavior.lua,避免散落在场景层。
业务动作下沉到插件 不同动作交给不同模块:
学习交给 Education 消费交给 NPCEconomy 医疗交给 Hospital / Pharmacy 罢工交给 StrikeParade 统计展示交给 NPCDialogue / AssetPanel 财务变化交给 NPCSavings 环境修正独立于移动逻辑 GlobalEvent.lua 只提供修正值,不参与 NPC 路径决策。
持久化与会话态 类型 例子 说明 Shared 边界 持久状态 educationDays、partnerId、ownerId 跨区块 / 跨会话需要保留 Shared.SerializeNPC / Shared.SerializeBuilding 会话状态 state、targetIdx、stuckCount 进入场景后可重新推导 不进入 Shared 序列化 表现状态 气泡、心声、高亮 仅用于 UI 不进入 Shared 序列化 持久化边界:
NPC 行为插件产生的长期状态,必须汇入 Shared.SerializeNPC。 建筑业务插件产生的长期状态,必须汇入 Shared.SerializeBuilding。 云端 key 必须通过 Shared.lua 生成,不能由业务插件自行拼接。 网络事件名必须通过 Shared.EVENTS 引用,不能在客户端 / 服务端散落硬编码字符串。 一句话总结 NPC 的“走路”不是单独的移动函数,而是:
以状态机为骨架,按“家 → 目标建筑 → 出来 → 回家/游荡”循环移动,并在移动和到达过程中通过插件链触发探索、消费、工作、学习、医疗、罢工等行为。
相关文件 文件 作用 scripts/game/StreetScene.lua 场景调度器 scripts/game/street/NPCBehavior.lua NPC 状态机 scripts/game/street/NPCCore.lua 目标选择与移动 scripts/game/street/NPCEconomy.lua 消费、娱乐、借贷 scripts/game/street/Education.lua 学习与资质 scripts/game/street/Hospital.lua 医疗与分娩 scripts/game/street/Pharmacy.lua 买药 scripts/game/street/StrikeParade.lua 罢工游行 scripts/game/street/NPCDialogue.lua 气泡与心声 scripts/game/street/NPCSavings.lua 储蓄与净值 scripts/game/street/AssetPanel.lua 资产展示 scripts/game/street/AuctionHouse.lua 交易行 scripts/game/street/BidAuction.lua 拍卖 scripts/game/street/Factory.lua 工厂生产与工资 scripts/game/globe/GlobalEvent.lua 全局事件修正 scripts/network/Shared.lua 共享网络协议、云端 key、建筑/NPC 序列化 docs/模块系统/全球事件模块.md 全球事件模块文档
学校经营游戏·严格顶视场景与四立面人物素材模板 v2
下面内容可直接补充到现有模板中。最重要的修正是:学校物品与人物不能共用同一套观察角度规则。 建筑、家具、道具:严格正上方顶视。 人物:采用正交四立面方向图,不是从头顶俯视。 两者都禁止透视、等距视角和三分之四展示视角。 建议将模板升级为: 学校经营游戏·严格顶视场景与四立面人物素材模板 v2 八、模板适用范围与人物例外规则 1. 场景物品规则 以下素材继续采用前文的严格正上方顶视规则: 建筑模块 墙
官方
4 赞
学校俯视建造游戏素材模板
可以。结合前面对话里生成的门、床、摄像头、卫生间设施、课本和互动道具,建议固定一套名为: 需要先纠正一点:目前这批素材不是像素风,也不是斜 45° 等距视角。它们更接近: 严格正上方顶视、卡通手绘、黑色轮廓、柔和分层明暗、透明背景的 2D 建造游戏素材。 物体可以在画布平面内斜着摆放,但不能因此出现立体透视。例如摄像头可以旋转 30°,但仍然必须从正上方观察。 一、统一核心提示词 以后生成任何学校
官方
4 赞
穿透层修复
经验一:CSS transform 穿透层修复模式 问题本质 当容器使用 CSS transform: translateX/Y/scale 平移/缩放子树时,即使父容器有 overflow = "hidden",引擎的命中检测可能不裁剪越界区域。如果 transform 后的子树有更高的 zIndex,它会在视觉范围外拦截其他兄弟节点的指针事件。 受影响的场景 地图编辑器(右键平移/滚轮缩放后)
官方
4 赞
右键拖拽平移
一、问题本质 不是平移公式写错,而是 UrhoX UI 库指针事件派发的两个不对称陷阱叠加: 陷阱 现象 根因文件 OnPointerMove 不向父冒泡 右键按下 isPanning_=true,但 move 事件永远到不了 mapView urhox-libs/UI/Core/Widget.lua(OnPointerDown/Up 有 parent 冒泡,OnPointerMove 没有) H
官方
4 赞
【日常更新】支持2人、3人、4人对战截图
【日常更新】支持2人、3人、4人对战
优化了排行榜显示玩家昵称
3 赞
地图编辑器「墙」全链路增强
经验 1:子编辑器"连续操作" vs "一次性操作"——提交后别清空激活态 现象:放完一段墙,提示"可继续拖拽放置",但再拖没反应。 根因:CommitWall 提交后把 selectedItem=nil、tool="select",导致 IsActive() 返回 false,下次 HandlePointerDown 第一行就 return。提示语与行为矛盾。 模式:连续工具(墙、擦除)提交后只
官方
4 赞
拾取 / 丢弃物品
拾取的坑是「点击被遮挡」,丢弃的坑是「坐标反解会偏」。两者解法都是绕开复杂机制、用最直接的方式。 问题 根因 解法 走到物品旁点不动、捡不起来 物品命中层和主角标记同层、都无 zIndex,数组顺序靠后的主角标记盖在上面,点击命中的是主角而非物品 给可交互物品显式 zIndex = 20 拖拽丢东西飞到远处 用 ScreenToWorld 把鼠标像素反解成世界坐标当落点,依赖 zoom/offse
官方
4 赞
弹窗内做"搜索 + 分类 + 网格"
经验 1:弹窗内做"搜索 + 分类 + 网格",用局部刷新保住输入焦点 为什么有效:搜索框是 UI.TextField,如果每次输入都 RebuildUI 重建整棵树,焦点会丢、光标乱跳。正确做法是只把"网格容器"这一棵子树的子节点 ClearChildren + AddChild,搜索框和分类标签不动。模块级变量 objectCategory_ 跨弹窗开关不重置,天然实现"记住上次分类"。 关键
官方
槽位变更只走原子方法
经验 下标 = 视觉格子,空槽是合法状态。定长 9 槽,inventory[i]=nil 即第 i 格空着,中间允许空。任何"把物品往前挪/压缩/重排"的操作都会让"你看到的格子"和"数组真实下标"脱节 → 物品消失。渲染直映 inventory[i],数据层绝不重排。 稀疏表禁用 #。带 nil 洞的表 #inv 是未定义的(可能=0 直接读成空包,或=洞前边界)。所有遍历上界一律 Player
官方
4 赞
地图编辑器仿真 tick 重建抑制
UI 重建频率 = 事件分发的可靠性上限。 只要有一帧 SetRoot 销毁了正在处理 pointer 事件的控件,跨重建边界的 Down/Up 对就会被吞。高频仿真 tick 必须在 UI 边界按页面过滤。 关键代码(scripts/main.lua HandleUpdate) 四步走:先原地处理人员 → 聚合所有仿真 changed → 地图页强制压制 → 只放行显式/登录态变化。 -- ma
官方
4 赞