这篇主要根据MeoHero这个项目简单介绍Lua的变量和数据类型。

一. 变量声明

-- 局部变量(推荐使用)
local damage = 100        -- 数字
local name = "小悟空"     -- 字符串
local is_alive = true    -- 布尔值
local point = nil        -- 空值

-- 全局变量(不推荐使用)
map_name = "LOL"         -- 不使用local的变量为全局变量

二. 基本数据类型

a) 数字(number):

-- 整数
local level = 1
local gold = 500

-- 小数
local attack = 33.5
local move_speed = 310.0

-- 负数
local direction = -180

参考代码:

--造成伤害的倍率(%)
mt.damage_rate = 100

--受到伤害的倍率(%)
mt.damaged_rate = 100

b) 字符串(string):

-- 单引号
local name = 'dragon'

-- 双引号
local title = "魔霸工作室"

-- 多行字符串
local desc = [[
这是一个
多行文本
]]

-- 字符串连接
local full_name = name .. '_' .. title  -- 使用..连接字符串

参考代码:

string1 = "dark."
string2 = "sheep"
string3 = ".vip"
-- 使用 .. 进行字符串连接
print("连接字符串",string1..string2..string3)

以上代码执行结果为:

连接字符串     dark.sheep.vip

c) 布尔值(boolean):

local is_alive = true
local is_dead = false

-- 常用于条件判断
if is_alive then
    -- 执行代码
end

参考代码:

--存活
mt._is_alive = true

d) nil(空值):

-- 未初始化的变量默认为nil
local var
print(var)  -- 输出:nil

-- 可以显式设置为nil
local player = nil

参考代码:

mt.handle = 0

三. 复杂数据类型

a) 表(table) - Lua中最重要的数据结构:

-- 数组形式的表
local skills = {'龟派气功', '如意棒', '筋斗云', '狂暴'}

-- 字典形式的表
local hero_data = {
    name = "小悟空",
    hp = 1000,
    mp = 600,
    skills = skills
}

-- 访问表
print(skills[1])           -- 访问数组元素
print(hero_data.name)      -- 访问字典元素
print(hero_data['hp'])     -- 另一种访问字典元素的方式

b) 函数(function):

-- 函数定义
local function add_buff(unit, buff_name, duration)
    -- 函数实现
end

-- 匿名函数
local callback = function(event)
    print(event)
end

-- 函数作为参数
hero:event('单位-死亡', function()
    -- 处理死亡事件
end)

参考代码:

--死亡    
--杀死单位
--    [致死伤害]
function mt:kill(killer)
    if not self:is_alive() then
        return false
    end
    
    if not killer then
        killer = self
    end

    self._is_alive = false
    self:set('生命', 0)
    
    if not self:is_dummy() then
        jass.KillUnit(self.handle)
        killer:event_notify('单位-杀死单位', killer, self)
        self:event_notify('单位-死亡', self, killer)
    end

    --打断施法
    self:cast_stop()
    --删除Buff
    if self.buffs then
        local buffs = {}
        for bff in pairs(self.buffs) do
            if not bff.keep then
                buffs[#buffs + 1] = bff
            end
        end
        for i = 1, #buffs do
            buffs[i]:remove()
        end
    end
    if self:is_illusion() then
        self:remove()
    elseif not self:is_hero() then
        self:wait_to_remove()
    end
    return true
end

四. 变量作用域

-- 全局变量
map_name = "LOL"  -- 可以在任何地方访问

-- 局部变量
local function test()
    local x = 1    -- 只在函数内部可见
    y = 2          -- 全局变量,不推荐
end

-- 块作用域
do
    local block_var = 100  -- 只在do...end块内可见
end

五. 命名规范(从项目中总结):

-- 小写字母加下划线(推荐)
local unit_type = "hero"
local move_speed = 310

-- 驼峰命名(用于类名或重要结构)
local function CreateHero()
end

-- 常量(全大写)
local MAX_LEVEL = 25
local DEFAULT_HP = 1000

重要提示:

  1. 推荐使用local声明局部变量
  2. 变量名应该清晰表达其用途
  3. 注意变量的作用域
  4. 合理使用注释说明变量的用途
  5. 遵循项目的命名规范

延伸阅读:变量使用规则(摘取自B站UP主Aaaaaya゚的文章)

  1. 可以包含字母、数字、下划线,但不能以数字开头。

    例:

    a1 = 1
    -- 1a = 1  -- 其中 1a会报错,并且无法成功赋值。
  2. 变量名区分大小写,即x与X是完全不同的两个变量。

    例:

    x = 1
    X = 2
    print(x, X)  -- 输出结果:1, 2
  3. 变量名的长度没有任何限制。

    例:

    abcdefghijklmnopqrstuvwxyz = 1
    print(abcdefghijklmnopqrstuvwxyz)  -- 输入结果:1
  4. 变量不需要去声明类型,jass里需要以类型+名称的方式来声明。

    例:

    // integer是jass里的整数类型
    Jass:integer num = 1 

    -- 无需类型即可直接声明

    Lua:num = 1 
  5. 变量可以在任何地方声明且赋值。

    lua的变量想在哪里写就在哪里写,而jass不同。
    jass里全局变量需要在globals范围内声明,局部变量必须在函数内顶部声明。

    例:

    全局变量:
    globals
    integer num
    endglobals
    局部变量:
    function init takes nothing returns nothing
    // 必须在函数内先置顶声明,否则报错无法运行
    local integer num
    num = 1  // 再赋值
    endfunction
  6. 全局变量可以不用声明便可以直接使用,但会直接返还为nil。

    例:

    print(num)  -- 输出结果:nil

    nil等于jass里的null,等于触发器里的没有单位、没有技能、没有XX。也可以理解为空。

  7. 变量可以被重新声明为新的类型。

    例:

    local num = 1
    print(num)  -- 输出结果:1
    local num = ‘王大锤’
    print(num)  -- 输出结果:王大锤

    但这样反复的重新声明为新的类型,在地图代码逐渐增多之后,会导致你根本记不清当前变量到底是什么类型,所以尽可能的避免且少用重新声明。