Xlua学习笔记

本篇笔记是记录"游戏热更新实战案例(基于xLua)"的学习笔记。
1、Xlua的环境搭建
1)导入Xlua插件
上Github上下载Xlua插件,将Xlua解压,将Asset下的所有文件拷贝到当前项目目录Asset下。拷贝与Asset同级目录下的Tools到该该项目中一样的位置。
2)unity菜单栏 File=》BuildSetting=》playsetting =》OtherSettings=》Scripting Define Symbols 输入HOTFIX_ENABLE
在这里插入图片描述
搭建功能就完成了。
3)复制相关DLL文件
在这里插入图片描述
PS:该捕鱼项目是2017的uinity版本,我用2018打开Xlua部署环境报错,用2017则无问题,原因可能是Xlua版本没有更新,大家学习的时候注意一下版本问题。

2、使用Xlua修复游戏中存在的BUG。
1)如何通过lua文件实现热更新?
首先创建一个调用脚本,挂在物体上,代码如下。这个是固定格式,相关API不明白的话可以自行查阅。


public class HotFixScript : MonoBehaviour {

    private LuaEnv luaEnv;

	void Start () {
        luaEnv = new LuaEnv();
        luaEnv.AddLoader(MyLoader);
        luaEnv.DoString("require'fish'");
	}
	
	void Update () {
		
	}

    private byte[] MyLoader(ref string filePath)
    {
        string absPath = @"C:\Users\Administrator\Desktop\XluaProjects\PlayerGamePackage\"+filePath+".lua.txt";
        return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
    }
    //在OnDestroy前调用,释放已经注册的委托
    private void OnDisable()
    {
        luaEnv.DoString("require'fishDispose'");
    }

    private void OnDestroy()
    {
        luaEnv.Dispose();
    }
}

然后在绝对路径创建lua文件。
在这里插入图片描述
然后在可能会出现问题的类上打上[Hotfix]标签
在这里插入图片描述
在需要修改的函数方法上打上[LuaCallCSharp]标签
在这里插入图片描述
执行到这里的时候就会调用Lua脚本。

功能需求以及解决方法的相关代码。
1.1点击宝箱领取的金币钻石太拥挤,分散一点

--1.1点击宝箱领取的金币钻石太拥挤,分散一点
--常用的变量可以定义一个局部变量去接收
--[[
Lua调用C#中的类要添加前缀CS.
C#中调用自身对象是this.XXX
但是lua中需要加上self.
此处想调用自身的金币, C#完整代码是this.gold,但是在lua中要写全,为self.gold。--]]
local UnityEngine = CS.UnityEngine
--标准格式,第一个参数是C#中打上标签的类(即你想修改的类,第二个参数是要修改的方法,第三个参数是自身)
--此处金币拥挤,我们只需查看代码,将相关间隔的相关代码数值增大即可。
xlua.hotfix(CS.Treasour,'CreatePrize',function(self)
	for i=0,4,1 do
		local go = UnityEngine.GameObject.Instantiate(self.gold,self.transform.position + UnityEngine.Vector3(-10+i*40,0,0),self.transform.rotation)
		go.transform.SetParent(go.transform,self.cavas)
		local go1 = UnityEngine.GameObject.Instantiate(self.diamands,self.transform.position + UnityEngine.Vector3(0,40,0)+ UnityEngine.Vector3(-10+i*40,0,0),self.transform.rotation)
		go1.transform.SetParent(go1.transform,self.cavas)
	end
end)

在这里插入图片描述
lua中代码将30改为40,即可完成这个初步的简单任务。

1.1玩家金币钻石不够时没有相关处理
这个问题处理起来有个小坑,C#代码中调用了私有变量,lua中直接调用会报错,需要加上相关代码,如下。
另外lua中调用自身的方法为XX.Func(self) 或者XX:Func()

--如果想访问私有变量需要加上下面这一行代码,此处bullectAudio是私有变量
xlua.private_accessible(CS.Gun) 
xlua.hotfix(CS.Gun,'Attack',function(self)
	if UnityEngine.Input.GetMouseButtonDown(0) then	

		if UnityEngine.EventSystems.EventSystem.current:IsPointerOverGameObject() then
			return
		end

		if self.gold<1+(self.gunLevel-1)*2 or self.gold==0 then
			return
		end

		self.bullectAudio.clip = self.bullectAudios[self.gunLevel-1]
		--self.bullectAudio.Play(self) 两种调用自身方法的形式
		self.bullectAudio:Play()
			
			if self.Butterfly then
				UnityEngine.GameObject.Instantiate(self.Bullects[self.gunLevel-1],self.attackPos.position,self.attackPos.rotation*UnityEngine.Quaternion.Euler(0,0,20))
				UnityEngine.GameObject.Instantiate(self.Bullects[self.gunLevel-1],self.attackPos.position,self.attackPos.rotation*UnityEngine.Quaternion.Euler(0,0,-20))
			end

			UnityEngine.GameObject.Instantiate(self.Bullects[self.gunLevel-1],self.attackPos.position,self.attackPos.rotation)

			if not self.canShootForFree then
				self:GoldChange(-1-(self.gunLevel-1)*2)
			end
			self.attackCD =0
			self.attack = false
		end
end)

–1.2 技能扣除钻石太多
解决方法,一样查看相关代码,然后修改
在这里插入图片描述
发现代码写在Start中,这里要注意,我们调用luaEnv的脚本要写在Awake中,补丁需要在代码前执行。写在Start顺序可能会出问题从而导致无效。

xlua.private_accessible(CS.Fire)
xlua.hotfix(CS.Fire,'Start',function(self)
	self.reduceDiamands = 8
end)

–1.2boss撞击玩家数值变动一样且不是减少是增加
依旧和之前一样,找到相关代码,用lua修改
在这里插入图片描述
但这次使用更简便的方法,不需要重写全部,而是在执行完之后再执行我们的lua代码
需要注意,util的这个文件要和当前的lua脚本在同级目录下,这个文件可以下xlua文件下种搜索到。复制过来粘贴即可。注销委托的时候格式与之前一样,依旧是xlua.hotfix(CS.Boss,‘Start’,nil)

local util = require 'util'
xlua.private_accessible(CS.Boss)
util.hotfix_ex(CS.Boss,'Start',function(self)
	self:Start()
	self.m_reduceGold = self.m_reduceGold-10;
end)

–1.3 boss撞击玩家当钻石金币不够时产生负数
这个与之前有点区别,需要传参,改动方法如下
在这里插入图片描述

util.hotfix_ex(CS.Gun,'GoldChange',function(self,number)
	self:GoldChange(number)
	if self.gold <-number then
		self.gold = 0
		return	
	end
end)

–1.4捕鱼概率修改
捕鱼代码中用到了GetComponent方法,但是lua中不支持泛型,好在C#中也支持参数为string的GetComponent方法,穿的参数改为string类型即可。

itemGo:GetComponent('Gold').bossPrize = true

–1.4游戏操作方式更改
无新的知识点,lua重写代码即可。

–2.0新增海浪
这个比较麻烦,首先需要一个预制体,其次这个预制体上还要有脚本代码。解决方法,先创建一个空的脚本,里面有几个常用的空方法,挂在预制体上,然后打包成AssetBundle文件上传至服务器,加载的时候可以先从服务器下载到本地指定位置,然后再读取。

//空的C#脚本,留给lua脚本实现
[Hotfix]
public class HotFixEmpty : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}
    private void BehaviourMethod()
    {

    }

    private void OnTriggerEnter(Collider other)
    {
        
    }

}
--2.0新增海浪
--lua脚本实现功能。
xlua.private_accessible(CS.HotFixEmpty)
xlua.hotfix(CS.HotFixEmpty,'Start',function(self)
	self:Invoke('BehaviourMethod',8)
end)

xlua.hotfix(CS.HotFixEmpty,'Update',function(self)
	self.transform:Translate(-self.transform.right*4*UnityEngine.Time.deltaTime,UnityEngine.Space.World)
end)

xlua.hotfix(CS.HotFixEmpty,'OnTriggerEnter',function(self,other)
	if other.tag~='Untagged' and other.tag~='Wall' then
	UnityEngine.Object.Destroy(other.gameObject)
	end
end)

xlua.hotfix(CS.HotFixEmpty,'BehaviourMethod',function(self)
	CS.Gun.Instance.level = CS.Gun.Instance.level + 1
	if CS.Gun.Instance.level == 4 then
		CS.Gun.Instance.level = 1
	end
	canCreateNewFish = true
	CS.Gun.Instance.changeAudio = true
	UnityEngine.Object.Destroy(self.gameObject)
end)

总结:使用Xlua时需要注意的坑。
1、普通成员方法与静态成员方法调用的区别。
静态成员方法直接XX.Function()即可。有参数直接写在括号里 XX.Function(a,b…)
普通成员方法调用格式为 XX.Function(self)有参数写在self后面 XX.Function(self,a,b)
或者XX:Function()有参数直接写在括号里XX:Function(a,b)
2、lua中不存在new,如果C#脚本中存在new,直接无视即可。
3、lua中不支持泛型,如果C#中用到了泛型,请替代为string参数,或者单独写一个方法获取值,lua调用方法获得返回值
4、过于复杂的代码建议C#实现,lua直接调用即可,虽然lua也能实现,但是比较麻烦且性能消耗不如C#,例如

[LuaCallCSharp]
    public void LoadResource(string resName,string filePath)
    {
        StartCoroutine(LoadResourceCorotine(resName, filePath));
    }

    IEnumerator LoadResourceCorotine(string resName, string filePath)
    {
        UnityWebRequest request= UnityWebRequest.GetAssetBundle(@"http://localhost/AssetBundles/" + filePath);
        yield return request.SendWebRequest();
        //AssetBundle ab = AssetBundle.LoadFromFile(@"C:\Users\Administrator\Desktop\XluaProjects\FishingJoy\AssetBundles\" + filePath);
        AssetBundle ab =(request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
        GameObject gameObject = ab.LoadAsset<GameObject>(resName);
        prefabDict.Add(resName, gameObject);
    }
xlua.hotfix(CS.CreateFish,'Start',function(self)
	self.hotFixScript:LoadResource('level3fish3','gameobject\\enemy.ab')
	self.hotFixScript:LoadResource('SeaWave','gameobject\\wave.ab')
end)

这里lua调用起来就很方便。
5、lua主要是用来修复紧急BUG,不建议做大改动,例如2.0版本开发的海浪功能,先把资源打包好上传到服务器,代码全部是lua写,开发效率较低。
如果预制体上挂有脚本,本地一定要先有脚本在解压,不然AssetBundle解压出来没有脚本则会丢失,无法完成相应的功能。

资源图片较多,文件较大,想看源码的建议移步siki学院搜索热更新

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用XLua可以在Unity中实现Lua脚本的编写,同时也可以让Lua脚本与C#代码进行交互。 以下是基本的使用步骤: 1. 下载XLua插件并导入到Unity中。 2. 在Unity中创建一个新的Lua文件,编写Lua脚本代码。 3. 在C#代码中使用XLua的API来加载并运行Lua脚本,例如: ``` using XLua; public class LuaManager : MonoBehaviour { private LuaEnv luaEnv; void Awake() { luaEnv = new LuaEnv(); luaEnv.DoString("require 'main'"); // 加载并执行Lua脚本 } void Update() { luaEnv.Tick(); // 更新Lua环境 } void OnDestroy() { luaEnv.Dispose(); // 释放Lua环境 } } ``` 在上面的例子中,`Awake()`方法中创建了一个Lua环境,然后通过`DoString()`方法加载并执行了Lua脚本。`Update()`方法中每帧都调用了`Tick()`方法来更新Lua环境,`OnDestroy()`方法中释放了Lua环境。需要注意的是,在实际的项目中,可能需要更加复杂的逻辑和管理方式来处理Lua脚本的加载和运行。 4. 在Lua脚本中使用XLua提供的API来调用C#代码或者导出Lua模块,例如: ``` -- 导出一个Lua模块 local module = {} module.foo = function() print("Hello from Lua!") end return module -- 调用C#代码 local gameObject = CS.UnityEngine.GameObject("LuaObject") local transform = gameObject.transform transform.position = CS.UnityEngine.Vector3(1, 2, 3) ``` 在上面的例子中,导出了一个名为`module`的Lua模块,并定义了其中的一个函数`foo()`。同时,也调用了C#代码的API来创建了一个新的GameObject,并修改了它的Transform组件的位置。 XLua还提供了其他的功能,例如自定义导出规则、GC优化等。在使用XLua之前,建议先了解一些基本的Lua语法和C#与Lua交互的机制,以便更好地使用XLua

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值