大家好,这里是唯。
这是唯的小白Lua教学最后一期。之所以说这是最后一期,是因为学完这期,你就应该具备了编写Lua脚本的能力和思想。虽然,很多功能的实现,你可能还有障碍,不会写,这很正常。但是写东西的时候要考虑什么,注意什么,其实我已经该说的,都说了。还是那句话,其实我的LuaScriptTemplate已经帮小白跳过了这个问题,做好了处理,不过总有人喜欢自己造轮子,我也不反对,自己做的总是比别人给的好,不吃嗟来之食,好品格。
最后这期是小白Lua教学最难的一期。说难是因为,它的思想很简单,但是代码对于初学编程的人而言很抽象,我会尽量说明得简单一些。当然,你也可以不思考,照搬锁的模板,只是这对于你后期的脚本编写没有好处。
好了,话不多,我们开始。
LuaScript官网:https://docs.alcedogroup.com/
注意: 锁是并发环境下用于确保线程安全的概念。以下内容称为锁,只是为了方便小白理解,和编程里的互斥锁之类的概念是不一样的。本教程的锁的本质只是个标记量flag,并不是真正编程意义上的锁。
一、什么是锁
锁,就和现实生活里的锁一个意思。在循环跑的Lua脚本里,比如一个动作如果动作帧很长,如果不加锁的话,那么,只要还在它的动作帧内,你的判断条件成立,就会一直执行这个操作。比如你可能只是想在某个动作期间给它加1个特效,但是如果你不加锁,只要还在这个动作有效期间,它就会不断的加特效,这是很可怕的。
为了解决这个问题,就需要引入锁机制——运行的时候把它锁住,让它只运行一次。
我们约定,用0和1代表一把锁的开和关,用一个有名字的整型变量来代表一把锁。
这里,还有一个难点,就是保存和读取变量的值,因为我们下一次得读取锁的值是0还是1来确定它是锁住了还是打开了,我们用Lua的这两个函数来处理:
二、一次性锁
一次性锁指的就是,只运行一次就不再触发。
示例:LuaScript控制台呼出代码
我们分析一下这段代码。
最初的时候,名叫init的变量未赋值,整数变量的默认值是0。因此,锁一开始是打开的,如图:
Lua_Variable_ReadIntVariable('init') == 0,相当于:
如果锁没有被锁上,那么我们呼出Lua控制台,并且把锁锁上。这就是这段代码的逻辑。把锁锁上的代码是这一句:
Lua_Variable_SaveIntVariable('init', 1),相当于:
那么,现在我们可以理解了。当下一次要执行if的时候,因为锁已经锁上了,读取到的变量值是1,因此不会再执行重复的操作。
像这样,锁上了,就不再打开的锁,我把它称为一次性锁。
三、可重用锁
显然,这样的一次性锁并不能满足充分满足我们的实际需求。试想一开始那个问题,比如,我们想在逆袈裟的时候,触发一次见切成功的特效。那么这里就涉及到了一个问题:如果用一次性锁,下次就触发不了见切成功特效了,因为锁一旦锁上就不在打开,即变量的值恒为1。
为了解决这个问题,我们引入可重用锁,我把锁上后还可以打开,再锁上的锁称为可重用锁。
怎么解决这个问题呢?我们的思路是这样:
1、初始的时候,锁是打开的(lock = 0)
2、当动作是逆袈裟(49262)的时候(相当于条件满足),我们把锁锁上。加一个0.01秒的计时器(这是为了保证安全)。当检测到计时器,我们执行添加见切成功特效(2004,0)1次。
3、当动作不是逆袈裟的时候(相当于条件不满足),我们重新把锁打开。这样,就实现了在循环执行的脚本里,每次检测到逆袈裟(49262),只添加1次特效。
代码如下:
原理示意图:
(1)初始态
Lua_Variable_ReadIntVariable('lock') == 0
and Game_Player_GetPlayerActionId() == 49262
(2)锁住
Lua_Variable_SaveIntVariable('lock',1)
(3)开锁
Lua_Variable_SaveIntVariable('lock',0)
仔细观察,你可以发现,进入下一轮循环的时候,锁又被打开了,以此实现可重用,所以我称它为可重用锁。
最后附一份判定相对完善的Lua脚本代码示例;
好了,再提一个注意点:如果不了解变量的作用域,那么,各式各样的变量名字,请不要重复。如果重复了:
1、会对你自己的代码造成冲突和混乱,造成功能矛盾冲突。
2、可能别人和你用一样的变量名,会造成不同的脚本同时运行的时候,它们之间产生矛盾和冲突。
好的,恭喜你!至此,你已经完成了全部的Lua小白教学。那么,我们下次再见。