企业项目管理、ORK、研发管理与敏捷开发工具平台

网站首页 > 精选文章 正文

【温达】插件制作-文件的加载顺序

wudianyun 2025-09-19 04:04:36 精选文章 3 ℃

今天的winda制作比较硬核,它是WOW插件编程里非常重要的一件事情——文件的加载顺序

我们平时使用的插件, 会看到文件夹里有非常多的文件,这些就是插件的代码;

不同插件加载的先后顺序是什么?

代码是按怎样的顺序加载到内存里的?

我们能让某个插件提前加载吗?

加载插件

当我们打开战网启动客户端时,游戏就开始读取并加载 必要的配置和数据;在启动的过程中,游戏会读取WTF文件夹中的数据,这些数据保存了用户界面及插件的一些设置,游戏会优先读取它们,以确保插件能正确的加载并读取到之前保存过的配置;

也就是说,当你登录到游戏角色选择界面时插件和配置就已经确定了;这个时候插件的代码已经准备就绪,当进入游戏后代码被执行,某些功能也会在特定的事件触发后生效;

那么,不同的插件代码都要加载到游戏里,肯定会有一个确定的顺序;今天我们就来写一个简单的代码示例,来探究插件的加载顺序;

加载示例

首先清空AddOns下的所有插件只保留winda,我们创建三个文件夹A、B、X来区分不同插件;

这个时候插件并不显示,我们需要在每个插件文件夹下都创建一个同名的toc文件;接下来

在A中添加a.lua,B中添加b.lua,X中添加x.lua,并令每一个的toc文件都加载各自的lua代码

## Title: AAA
a.lua

## Title: BBB
b.lua

## Title: XXX
x.lua

为了区分不同插件的打印内容,我们用下面这一段代码,可以打印出各自的插件名称

local addonName, addon, some = ...
print("--------")
print(...)
print("当前加载的插件是:"..addonName)
for k,v in pairs(addon) do
    print(k, v)
end
print(some)
print("--------")

这样我们现在就有了四个插件,进入游戏之后看打印内容;

可以看到他们的顺序是A、B、winda、X,这是按插件的名称首字母排序的

注意这个顺序跟他们toc里的Title是无关的,只跟文件夹的名称有关

TOC元数据影响

通常情况下是这样的,但插件加载还受toc文件中元数据的影响,前面我们在不加任何元数据的情况下,插件的加载顺序是A、B、winda、X;

现在我们打开A.toc,在里面添加OptionalDeps字段,

## OptionalDeps: X

这个表示X是A的可选依赖插件,加上之后X会先于A加载;依赖的意思就是A的某些功能需要用到X的代码;

同样达到这个效果的是RequiredDeps字段,与前面OptionalDeps的区别是它是必选依赖

## RequiredDeps: X

LoadOnDemand字段可以让A在需要时才加载,当它设置为1时,进入游戏A就暂时不会加载了;

它只会在特定场景,比方说打开拍卖行才加载运行,需要插件自己写代码设置加载的情况;这种机制可以有效降低使用插件时的内存;

插件也可以设置多个依赖条件,Dependencies和LoadWith字段都可以接受多个插件作为依赖的条件;

不同的是Dependencies字段后的插件,会按照字段列出的顺序加载,即 Dependencies: X, B

## Dependencies: X, B

会按照X、 B的顺序、然后再加载A,B和X并不会根据字母顺序加载;

而LoadWith字段并不会影响加载顺序,即当A中LoadWith所示内容为B、X;插件仍然会以A、B、winda、X的顺序依次加载,只是A的功能仍旧会依赖B和X的代码

不同插件的加载顺序是非常重要的,这直接影响代码运行的先后,这一点在我们写插件时一定要特别注意!!!

XML文件

魔兽插件除了作为入口的toc文件,还有两种用于写代码的lua和xml文件,lua我们之前写过代码在这里不多做解释;

xml也是另一种代码文件,跟lua使用不同的编程语言,代码的格式不相同,但是两者可以有一样的功能;我们这里讲一下它的加载;

之前讲到toc中代码区的文件会按顺序从上到下加载,同样比方说B.toc中有,b.lua和b.xml则它们会以顺序加载;并且toc中也可以加载子文件夹中的文件,比如sub下的sub.lua

## Title: BBB

b.lua
b.xml

sub/sub.lua

xml里也可以加载别的xml和lua文件,像下面这样写,仍然是按照从上到下的顺序加载

<ui xmlns="http://www.blizzard.com/wow/ui/">
    <!-- 使用xml加载插件代码文件 -->
    <script file="b.lua"/>
    <include file="b-1.xml"/>
</ui>

xml可以运行代码,下面这一段代码可以使xml打印文字

<ui xmlns="http://www.blizzard.com/wow/ui/">
    
    <!-- 这是一个不显示的Frame,用于测试已经加载了 -->
    <Frame name="WDTestFrame" parent="UIParent">
        <Scripts>
            <OnLoad>
                print("这里是xml显示的窗口")
            </OnLoad>
        </Scripts>
    </Frame>
    
    <!-- 在xml文件里也可以加载子文件夹的lua代码文件 -->
    <script file="sub/sub.lua"/>
    
</ui>

LUA代码调用

最后讲一下不同lua代码文件间的互相调用,如X的例子;当X.toc加载了anotherx.lua和x.lua两个文件(注意是谁先谁后),anotherx里有一段文字,但是此时并没有打印:

local X = {}

X.showString = "这里是文件间调用的测试"

怎么让它在x.lua里用这一串文字并打印出来呢?

系统给我们提供了一个_G的变量,你可以把它想像成个特别巨大的箱子,它能装所有我们需要的数据

但是当我们想找这些数据,就需要给每一个数据起一个名字,像下面这样_G["X"]

_G["X"] = X

中括号里的双引号X就是它的名字,所以在x.lua中,我们直接使用X就可以用到anotherx里的数据;

由于_G是一个全局变量,所有插件都可以用它,如果有两个插件用了相同名字装了不同数据,则先用这个名字的插件数据就找不到了,这是大多数情况下插件冲突的原因。

总结

我们最后总结一下:

  1. 游戏启动时,会按字母的顺序加载所有插件;
  2. toc文件中的一些字段会改变插件加载的顺序;
  3. toc可以加载xml和lua代码,xml也可以直接写代码;
  4. 不同lua代码互相调用可以使用_G变量;

以上

下一期我们会开始讲游戏机制,这里是WoWer的空间。

我在听风,也在等你。

Tags:

最近发表
标签列表