CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
进阶实战游戏功能996引擎

Lua+元方法__unm:一元负号的自定义本质

2026-09-29 16:46 作者:996 技术组 996引擎Lua教程传奇脚本进阶实战游戏功能996引擎

【语法算法】

元方法 __unm 的触发就这一行:

lua
setmetatable(t, { __unm = function(t) return setmetatable({ val = -t.val }, getmetatable(t)) end })

对带 __unm 的表做一元负号操作 -t 时,Lua 调用 __unm——一元负号的自定义全部机制就这一行。可这一行的前后各有一个细节:前面是"一元运算只有一个操作数",后面是"返回值可以是任何类型"。今天拆开。

一、注册、触发、返回三段

__unm 的三段。注册:元表的 __unm 字段赋一个函数——这个函数只接收一个参数——就是触发负号操作的那个表自身。触发:-t 触发 __unm(t)——一元运算只有一个操作数——不像 __add 有左右两个操作数——__unm 的语义就是"取反"。返回:__un 可以返回任何类型的值——返回同类型的表就是"取反后的新对象"——返回数字就是"取反后的数值"——返回什么由语义决定。三段连起来:__unm 玩的是"一元运算的自定义"——一元运算只有一个操作数,没有左右之分,语义最简单但实现最容易出错。

mermaid
graph TD
    A["-t"] --> B{"t有__unm?"}
    B -->|是| C["调用__unm(t)"]
    C --> D["返回取反结果"]
    B -->|否| E["尝试转数字取负"]
    E --> F["转不了就报错"]

二、一元负号的正确写法

lua
local Vector = {}
Vector.__index = Vector

function Vector.new(x, y)
    return setmetatable({ x = x, y = y }, Vector)
end

Vector.__unm = function(v)
    return Vector.new(-v.x, -v.y)
end

local v1 = Vector.new(3, 4)
local v2 = -v1
print(v2.x, v2.y)  -- -3, -4

__unm 返回一个新的 Vector 对象——不修改原始对象——一元运算的纯函数性就体现在"不修改输入,只返回输出"。

三、一元和二元的分界与纯函数的纪律

一元和二元的分界线就一条:操作数的个数——__unm 一个操作数、__add 两个操作数——Lua 通过元方法名区分一元和二元——不会混淆。纯函数的纪律是 __unm 的核心:不修改原始对象——返回新对象而不是修改旧对象——副作用为零——这样的 __unm 才是安全的。最后一条纪律:__unm 的返回值类型不必和输入相同——可以对一个表取负返回一个数字——但这样做的语义很奇怪——返回同类型是最佳实践,除非有充分的理由返回不同类型。

作者履历与出处

本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。

← 返回文章地图返回研学路径

幂尔框架 · 实战干货 · 接口调用

LATEST ARTICLES

全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →

进阶实战游戏功能

斩残血纹:它血越少,你刀越重

【游戏功能】 数值组出过一次结算事故:斩残纹上线首日,满血的怪挨了最重的刀——按设计它该是最轻的那一刀。排查下来是加成算错了…

2026-10-01 20:55 996 技术组
进阶实战游戏功能

逆纹缓刀:重刀化三拍,分批慢慢疼

【游戏功能】 defQ=Math.min(30,defQ+6) ——先拆这一行。逆纹把重刀分期,每一拍记一笔挂账,但挂账不能…

2026-10-01 20:55 996 技术组
进阶实战游戏功能

双生跳纹:纹不随尸灭,跳去下一只

【游戏功能】 上一版留了个只在你自己的房间里能复现的怪事:双生纹在怪倒下的那一帧偶尔整个消失——不跳、不报错、日志干净。翻了…

2026-10-01 20:55 996 技术组
进阶实战游戏功能

嫁祸奇纹:它这一爪,落在同伴头上

【游戏功能】 先抛一个坑:两只怪为什么只打你?它们的同伴就站在旁边,刀却一爪一爪全落你身上——仇恨锁死在玩家身上,怪和怪之间…

2026-10-01 20:55 996 技术组
进阶实战游戏功能

醉纹赌刀:一刀一掷,三十点看天

【游戏功能】 前阵子出过一场投诉事故:一个玩家连着七刀全是最小值,气得在世界频道喊"这纹出老千"。运营翻了账,七刀的点数真真…

2026-10-01 20:55 996 技术组
进阶实战游戏功能

反噬血纹:刀重六成,血在一滴滴还

【游戏功能】 P.hp=Math.max(5,P.hp-3) ——先拆这一行。反噬纹每秒要从血条里抽三点,但抽到见底会把人抽…

2026-10-01 20:55 996 技术组