Unity热更新ToLua学习--Day Two(小白向)

一、使用Lua对GameObj进行操作
二、将游戏对象打包&解包
三、将Lua脚本文件进行打包&解包

四、热更新实践

一、使用Lua脚本对GameObj进行操作

目标:使用Lua对场景的Sphere进行控制

创建场景,Sphere,Plane
在这里插入图片描述
创建Lua脚本Controller.lua:

controller = {} 			--//创建一个类
local this  = controller	--//模拟C#中的this

--//对Unity中的类和方法进行加载
local GameObject = UnityEngine.GameObject	
local Input = UnityEngine.Input
local Rigidbody = UnityEngine.Rigidbody
local Color = UnityEngine.Color

local Sphere
local rigi
local force

--//模拟Unity中Start方法
function this.Start()
	Sphere = GameObject.Find("Sphere")
	Sphere : GetComponent("Renderer").material.color = Color(0.1,1,1)
	Sphere : AddComponent(typeof(Rigidbody))
	rigi = Sphere : GetComponent("Rigidbody")
	force = 5
end

--//模拟Unity中Update方法
function this.Update()
	local h = Input.GetAxis("Horizontal")
	local v = Input.GetAxis("Vertical")
	rigi : AddForce(Vector3(h,0,v)*force)
end

创建C#脚本Controller.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaInterface;

public class Controller : MonoBehaviour
{
    private LuaState lua = null;
    private LuaFunction luaFunc = null;		//创建一个存放Lua类里面函数的载体
    void Start()
    {
        new LuaResLoader();
        lua = new LuaState();
        lua.Start();
        LuaBinder.Bind(lua);
        lua.DoFile("Controller.lua");
        CallFunc("controller.Start");	//调用下面CallFunc函数去调用Controller.lua脚本中的Start函数
    }
    private void Update()
    {
        CallFunc("controller.Update");//调用下面的CallFunc函数
    }

    void CallFunc(string func)
    {
        luaFunc = lua.GetFunction(func);//此处的func因该为lua脚本中的table类的名字,而不是lua脚本文件名的名字
        luaFunc.Call();//开始调用Lua脚本里面的函数
    }
}

将Controller.cs挂载在Sphere上,运行Uinty,Sphere成功改变颜色,并且有了Rigidbody,也可对小球进行移动控制。
在这里插入图片描述
以上的两个脚本,Lua脚本Controller.lua模拟了unity的Start和Update函数,且这两个函数在C#脚本Controller.cs中被对应的Start和Update调用,实现了lua处理逻辑,c#调用,从而实现了更新时只更改Lua脚本,不更改C#脚本的功能,从而可以实现热更新。

二、将游戏对象打包&解包

1.重新创建一个场景AssertBundleTest,创建一个Sphere,做成预制体:
在这里插入图片描述
2.点击预制体:在右下角可以设置生成的AssertBundle的名字和后缀:假设我们要生成sphere.uinity3d:
在这里插入图片描述
3.创建打包生成AssertBundle的脚本:在Editor里创建一个脚本CreateAssetBundle.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Windows;

public class CreateAssetBundle
{
    [MenuItem("AssetBundle/Build AssetBundles")]//在菜单栏创建新选项,点击执行下面函数
    static void BuildAssetBundle()
    {
        string streamPath = Application.streamingAssetsPath;//保持包的路径
        if (Directory.Exists(streamPath))//若包路径存在,删除掉
            Directory.Delete(streamPath);
        Directory.CreateDirectory(streamPath);//创建新的包路径
        AssetDatabase.Refresh();//刷新
        BuildPipeline.BuildAssetBundles(streamPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
        //开始打包:参数1.打包路径,参数2.打包格式,参数3.打包平台
    }
}

4.编译脚本,在菜单栏中点击AssetBundle–>Build AssetBundles,会生成如下文件:
在这里插入图片描述
总共生成4个文件,我们打开文件夹看看:

在这里插入图片描述在这里插入图片描述
以上就是打包后的结果。

5.将打包的sphere.unity3d进行解包:创建C#脚本LoadAssetBundle.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows;

public class LoadAssetBundle : MonoBehaviour
{
    
    void Start()
    {
        string path = Application.streamingAssetsPath + "/sphere.unity3d";//要解包的资源路径
        AssetBundle myAssetBundle = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));//加载解包
        Object[] obj = myAssetBundle.LoadAllAssets<GameObject>();//遍历包里的所有OBJ
        foreach (var o in obj)
            Instantiate(o);//实例化
    }
}

删除掉场景中的sphere,将上面脚本挂载在相机,运行,资源被解包了:
在这里插入图片描述
解包的方式有4中:
(1).LoadFormMemory:从内存中加载
(2).LoadFormFile:从本地加载
(3).WWW:从本地或服务器加载
(4).UnityWebRequest:从服务器端加载
根据不同需求可以对选择不同的加载方式。

6.打包中的依赖关系:
我们给5中创建的sphere加一个材质,就用我的证件照吧,创建Textures文件夹,将我的图片放进去:
在这里插入图片描述
拖进Sphere,自动生成Materials,我们将Textures中的me和Materials中的me打包在一起:
在这里插入图片描述
在这里插入图片描述
名字一样就可打包在一起。
然后AssetBundle–>Build AssetBundles,生成以下文件:
在这里插入图片描述
多了me.unity3d,打开看下:
在这里插入图片描述
包含了me.png和me.mat。
再看看sphere.unity3d:
在这里插入图片描述
增加了依赖:me.unity3d。
这就是他们的依赖关系,一旦有依赖,就会在Dependencies中表示出来。

7.对有依赖关系的物体进行解包:
若我对有依赖关系的sphere直接解包,会生成以下模样,会没有材质贴图:
在这里插入图片描述
所以我要先对他的依赖进行解包,再对sphere解包:修改一下解包的脚本:LoadAssetBundle.cs:
1.加载总依赖资源包StreamingAssets
2.根据名称找到加载目标的依赖项
3.加载所有依赖项资源

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows;

public class LoadAssetBundle : MonoBehaviour
{
    
    void Start()
    {
        string path = Application.streamingAssetsPath + "/sphere.unity3d";
        AssetBundle myAssetBundle = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));
        Object[] obj = myAssetBundle.LoadAllAssets<GameObject>();
        LoadDependencies();//解包依赖项
        foreach (var o in obj)
            Instantiate(o);
    }

    void LoadDependencies()
    {
        string path = Application.streamingAssetsPath + "/StreamingAssets";//获取总依赖性资源包路径
        AssetBundle assetBundle = AssetBundle.LoadFromFile(path);//加载总依赖项资源包
        AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//获取资源包依赖信息
        string[] DependenciesName = manifest.GetAllDependencies("sphere.unity3d");//获取shhere.unitye3d的依赖项
        foreach (var name in DependenciesName)
            AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + name);//加载解包依赖项
    }
}

实现了有依赖关系的加载
在这里插入图片描述

三、将Lua脚本文件进行打包&解包

尝试将一、中的的Lua脚本Controller.lua进行打包:
再设置AssertBundle名字的时候出现这个错误
在这里插入图片描述
原因是Unity是无法识别Lua文件,需要更改下Lua文件后缀,将其改为Controller.lua.bytes
重新AssetBundle–>Build AssetBundles:已有Lua的AssetBundle生成:
在这里插入图片描述
由于Lua的后缀是bytes,所以解包的时候要进行处理:修改下LoadAssetBundle:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows;

public class LoadAssetBundle : MonoBehaviour
{
    
    void Start()
    {
        string path = Application.streamingAssetsPath + "/sphere.unity3d";

        AssetBundle myAssetBundle = AssetBundle.LoadFromFile(path);
        Object[] obj = myAssetBundle.LoadAllAssets<GameObject>();
        LoadDependencies();
        foreach (var o in obj)
            Instantiate(o);

        LoadLua();//加载Lua文件
    }

    void LoadDependencies()
    {
        string path = Application.streamingAssetsPath + "/StreamingAssets";
        AssetBundle assetBundle = AssetBundle.LoadFromFile(path);
        AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        string[] DependenciesName = manifest.GetAllDependencies("sphere.unity3d");
        foreach (var name in DependenciesName)
            AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + name);
    }
    void LoadLua()
    {
        string path = Application.streamingAssetsPath + "/lua.unity3d";
        AssetBundle assetBundle = AssetBundle.LoadFromFile(path);
        TextAsset text = assetBundle.LoadAsset("Controller.lua") as TextAsset;
        if(File.Exists(Application.dataPath + "/Lua/Controller.lua"))
        {
            File.Delete(Application.dataPath + "/Lua/Controller.lua");
        }
        File.WriteAllBytes(Application.dataPath + "/Lua/Controller.lua", text.bytes);
    }
}

将一、中的Controller.cs挂载到二、中的预制体里,将LoadAssetBundle挂载在相机,点击运行:
运行的时候,LoadAssetBundle.cs将Lua文件Controller.lua从AssetBundle中加载出来,也将挂载了Controller.cd的sphere加载出来,从而可以控制sphere行走,实现了Lua文件的解包。
在这里插入图片描述

四、热更新实践

将三、中的Lua脚本文件,预制体,材质和贴图都删掉:
在这里插入图片描述
点击开始后:

依然有小球生成,这个小球就是从AssetBundle包生成出来的,若我们将AssetBundle存放在服务器里,就可以进行热更新了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值