【Lua in Unity】详解与和C#互相调用示例

目录

Lua在Unity中的主要作用

如何创建

Lua与C#互相调用

C#和Lua的使用场景区分

完整示例


Lua在Unity中的主要作用

游戏逻辑编写:Lua可以作为一种脚本语言,用于游戏中的逻辑编写,例如定义游戏角色的行为、AI逻辑,处理游戏的战斗逻辑和流程控制,等等。可以将Lua代码通过Unity的API来实现与引擎的交互。这样做的好处是,可以将游戏逻辑与引擎代码分离,加快开发速度,同时更容易修改和调试。

配置数据管理:Lua也可以作为一种配置语言,用于管理游戏数据,例如定义游戏中的各种参数、表格、配置表等等。通过编写Lua脚本,在游戏运行时读取这些Lua脚本并解析配置数据,可以让游戏开发者更方便地进行游戏数据管理,也提高了游戏的扩展性和可维护性。

如何创建

创建C#脚本,调用特定库就是Lua了

Lua与C#互相调用

Lua调用C#:

using LuaInterface;
public class TestClass {
  public int TestMethod(int a, int b) {
    return a + b;
  }
}

public class LuaTest {
  LuaState lua; // Lua状态机
  LuaFunction func; // Lua函数

  void Start() {
    lua = new LuaState();
    lua.DoString("require('test')"); // 加载Lua脚本
    func = lua.GetFunction("testFunc"); // 获取Lua函数
    int result = func.Call(1, 2)[0].Int; // 调用Lua函数
    print(result);
  }
}

C#脚本中的TestClass是让Lua脚本中调用的类,它包含一个TestMethod方法。在Lua脚本中,通过require函数加载test.lua文件,并获取其中的testFunc函数。然后,通过func.Call(1, 2)方法来调用testFunc函数,传入的参数是1和2,并获取返回值中的第一个值并转成整数类型。

C#调用Lua:

using LuaInterface;
public class LuaTest {
  LuaState lua; // Lua状态机

  void Start() {
    lua = new LuaState();
    lua.DoFile("test.lua"); // 加载Lua脚本
    lua.DoString("testFunc(1, 2)"); // 调用Lua函数
  }

  void Update() {
    lua.CheckFunction("update"); // 检查是否存在update函数
    lua.Push(this); // 将class实例压入栈中
    lua.Push(Time.deltaTime); // 将时间增量压入栈中
    lua.Call(2, 0); // 调用update函数,传入2个参数,取回0个返回值
  }
}

Unity提供了LuaState.DoString或LuaState.DoFile方法来实现C#代码调用Lua代码

通过lua.DoFile("test.lua")加载Lua脚本,并通过lua.DoString("testFunc(1, 2)")调用testFunc函数,传入的参数是1和2。在Update中,检查是否存在update函数,然后将C#中的类实例压入栈中,再将Unity中的Time.deltaTime压入栈中,并通过lua.Call(2, 0)方法调用update函数,传入2个参数(类实例和时间增量),取回0个返回值。

C#和Lua的使用场景区分

C#主要用于游戏核心逻辑和性能敏感的模块。

游戏的主循环和逻辑处理;

状态机、AI等游戏核心逻辑实现;

射线检测等性能敏感操作;

物理引擎、碰撞检测等底层操作。

Lua主要用于游戏可配置化、可扩展性和部分业务逻辑实现。

UI的布局和逻辑实现;

游戏属性、敌人行为等可配置化;

游戏任务系统、任务对话等剧情逻辑实现;

游戏的扩展功能实现,例如MOD、插件等。

完整示例

内容:Lua创建对象池,然后C#调用

创建一个空的GameObject,添加LuaBehaviour组件,添加lua脚本。

local objectPool = {}

-- 对象池中的对象
local objects = {}

-- 最大对象数量
local maxObjects = 10

-- 初始化对象池
function objectPool.init(max)
    maxObjects = max or maxObjects
end

-- 从对象池中获取一个对象
function objectPool.getObject()
    if #objects <= 0 then
        return nil
    else
        local obj = table.remove(objects)
        obj:SetActive(true)
        return obj
    end
end

-- 将一个对象放回对象池中
function objectPool.putObject(obj)
    obj:SetActive(false)
    if #objects >= maxObjects then
        GameObject.Destroy(obj)
    else
        table.insert(objects, obj)
    end
end

return objectPool

C#脚本:

在C#中调用Lua中的对象池,需要使用LuaState对象。

using UnityEngine;
using LuaInterface;
using System.Collections;

public class ObjectPoolTest : MonoBehaviour {

    private LuaState lua;
    private LuaFunction getObjectFunc;
    private LuaFunction putObjectFunc;

    void Start () {
        lua = new LuaState();
        lua.Start();
        lua.DoFile("ObjectPool.lua");

        // 获取对象池中的函数
        LuaTable objectPool = lua.GetTable("ObjectPool");
        getObjectFunc = objectPool["getObject"] as LuaFunction;
        putObjectFunc = objectPool["putObject"] as LuaFunction;

        // 初始化对象池
        objectPool.GetLuaFunction("init").Call(5);
    }

    void Update () {
        // 从对象池中获取对象
        GameObject obj = getObjectFunc.Call()[0] as GameObject;

        // 如果对象不为空,则重置位置并将对象放回对象池中
        if (obj != null) {
            obj.transform.position = Vector3.zero;
            putObjectFunc.Call(obj);
        }
    }

    void OnDestroy() {
        lua.Dispose();
        getObjectFunc.Dispose();
        putObjectFunc.Dispose();
    }
}

Unity中添加一个Cube,将其放置在场景中,添加一个BoxCollider组件,并在ObjectPoolTest脚本中将其作为对象池中的对象来使用。 

猜你喜欢

转载自blog.csdn.net/makyocute/article/details/131133159