u3d插件xLua[二]例2:U3DScripting,例3:UIEvent分析

本文介绍xLua官方例子U3DScripting

一.DoString(string chunk, string chunkName, LuaTable env )

为了理解官方例子U3DScripting,必须先理解DoString第三个参数用法,DoString原型:

cs 复制代码
        public object[] DoString(string chunk, string chunkName = "chunk", LuaTable env = null)

第二个参数chunkName:和报错时打印信息相关的参数,通常传null

第三个参数env:传了后执行chunk代码时,读写变量都在env这张表中进行,不传就在全局表_G中读写,因此传了env后无法直接访问全局函数。为了可以访问全局函数,必须对env这个表设置元表

来看下面这个例子

cs 复制代码
        void Start()
        {
            LuaEnv luaenv = new LuaEnv();
            Debug.Log("-------------DoString 不传表-------------");
            luaenv.DoString("score1 = 111");
            Debug.Log("score1:" + luaenv.Global.Get<int>("score1"));
            luaenv.DoString("CS.UnityEngine.Debug.Log('不传表: CS 可用')");

            Debug.Log("-------------DoString 传空表(带原表)-------------");
            LuaTable luaTab2 = luaenv.NewTable();
            using (LuaTable metaTab = luaenv.NewTable())
            {
                metaTab.Set("__index", luaenv.Global);
                luaTab2.SetMetaTable(metaTab);
            }
            luaenv.DoString("score2 = 222", null, luaTab2);
            Debug.Log("score2:" + luaTab2.Get<int>("score2"));
            luaenv.DoString("CS.UnityEngine.Debug.Log('传空表(带原表): CS 可用')", null, luaTab2);
            luaTab2.Dispose();

            Debug.Log("-------------DoString 传空表(无原表)-------------");
            LuaTable luaTab3 = luaenv.NewTable();
            luaenv.DoString("score3 = 333", null, luaTab3);
            Debug.Log("score3:" + luaTab3.Get<int>("score3"));
            luaenv.DoString("CS.UnityEngine.Debug.Log('传空表(无原表): CS 可用')", null, luaTab3);

        }

二.example:02_U3DScripting

2.1 Demo概述

一个Cube不停旋转和颜色渐变,整体流程:

  1. C#脚本指定一份 Lua 文本(TextAsset
  2. 让Lua可访问场景里的Cube和light (xLua称为注入)
  3. 把 Unity 的 Awake/Start/Update/OnDestroy 转成调用 Lua 的 awake/start/update/ondestroy
  4. 用 Lua 当 MonoBehaviour 来写旋转和颜色渐变效果

2.2 LuaBehaviour.cs:

可以将C#代码以DoString为界,分为两部分:

DoString上面在对scriptScopeTable设置元表以及调用Set方法设置K,V值;

DoString下面部分在C#侧获取lua写的生命周期函数,并在C#侧调用

注意事项:

1.通过static让所有LuaBehaviour对象共享一个luaEnv

2.OnDestry内只调用scriptScopeTable.Dispose();不要对luaEnv调用Dispose()

cs 复制代码
internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
cs 复制代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using XLua;
using System;

namespace XLuaTest
{
    [System.Serializable]
    public class Injection
    {
        public string name;
        public GameObject value;
    }

    [LuaCallCSharp]
    public class LuaBehaviour : MonoBehaviour
    {
        public TextAsset luaScript;
        public Injection[] injections;

        internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
        internal static float lastGCTime = 0;
        internal const float GCInterval = 1;//1 second 

        private Action luaStart;
        private Action luaUpdate;
        private Action luaOnDestroy;

        private LuaTable scriptScopeTable;

        void Awake()
        {
            // 为每个脚本设置一个独立的脚本域,可一定程度上防止脚本间全局变量、函数冲突
            scriptScopeTable = luaEnv.NewTable();

            // 设置其元表的 __index, 使其能够访问全局变量
            using (LuaTable meta = luaEnv.NewTable())
            {
                meta.Set("__index", luaEnv.Global);
                scriptScopeTable.SetMetaTable(meta);
            }

            // 将所需值注入到 Lua 脚本域中
            scriptScopeTable.Set("self", this);
            foreach (var injection in injections)
            {
                scriptScopeTable.Set(injection.name, injection.value);
            }

            // 如果你希望在脚本内能够设置全局变量, 也可以直接将全局脚本域注入到当前脚本的脚本域中
            // 这样, 你就可以在 Lua 脚本中通过 Global.XXX 来访问全局变量
            // scriptScopeTable.Set("Global", luaEnv.Global);

            // 执行脚本
            luaEnv.DoString(luaScript.text, luaScript.name, scriptScopeTable);

            // 从 Lua 脚本域中获取定义的函数
            Action luaAwake = scriptScopeTable.Get<Action>("awake");
            scriptScopeTable.Get("start", out luaStart);
            scriptScopeTable.Get("update", out luaUpdate);
            scriptScopeTable.Get("ondestroy", out luaOnDestroy);

            if (luaAwake != null)
            {
                luaAwake();
            }
        }

        // Use this for initialization
        void Start()
        {
            if (luaStart != null)
            {
                luaStart();
            }
        }

        // Update is called once per frame
        void Update()
        {
            if (luaUpdate != null)
            {
                luaUpdate();
            }

            if (Time.time - LuaBehaviour.lastGCTime > GCInterval)
            {
                luaEnv.Tick();
                LuaBehaviour.lastGCTime = Time.time;
            }
        }

        void OnDestroy()
        {
            if (luaOnDestroy != null)
            {
                luaOnDestroy();
            }

            scriptScopeTable.Dispose();
            luaOnDestroy = null;
            luaUpdate = null;
            luaStart = null;
            injections = null;
        }
    }
}

2.3 LuaTestScript.lua.txt

Lua 复制代码
local speed = 10
local lightCpnt = nil

function start()
	print("lua start...")
	print("injected object", lightObject)
	lightCpnt= lightObject:GetComponent(typeof(CS.UnityEngine.Light))
end

function update()
	local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed
	self.transform:Rotate(r)
	lightCpnt.color = CS.UnityEngine.Color(CS.UnityEngine.Mathf.Sin(CS.UnityEngine.Time.time) / 2 + 0.5, 0, 0, 1)
end

function ondestroy()
    print("lua destroy")
end

三.example:03_UIEvent

该example展示LuaBehaviour在UI方面的应用,主题依然是用Lua来做MonoBehaviour。具体做法是Button下挂LuaBehaviour,指定脚本ButtonInteraction.lua,注入InputField

ButtonInteraction.lua的逻辑非常简单,注册Button监听事件,打印InputField的输入内容

Lua 复制代码
function start()
	print("lua start...")

	self:GetComponent("Button").onClick:AddListener(function()
		print("clicked, you input is '" ..input:GetComponent("InputField").text .."'")
	end)
end
相关推荐
XR技术研习社9 小时前
关于 PICO 串流测试中报错 IndexOutOfRangeException: renderPassIndex 的两个排障方法
unity·ar·xr·vr
想做后端的前端9 小时前
Unity · 性能优化:内存管理完全指南:从托管堆到跨桥开销
unity·性能优化·游戏引擎
平行云12 小时前
实时云渲染信创架构解析:从GPU池化到全栈适配的技术演进
linux·unity·docker·ue5·webgl·数字孪生·实时云渲染
玖玥拾14 小时前
Lua 基础语法(五)Unity xLua基础配置与 C# 访问 Lua
开发语言·unity·c#·lua
玖玥拾1 天前
Lua 基础语法(二)
开发语言·unity·lua
玖玥拾2 天前
Lua 基础语法(三) 元表 metatable、元方法、模拟面向对象
开发语言·unity·lua
盟道科技3 天前
Redis+Lua 实现滑动窗口限流:从固定窗口踩坑到生产可用的完整方案
redis·junit·lua
谢斯3 天前
[unity]如何在unity中添加newtonsoft-json
unity·json·游戏引擎
天人合一peng3 天前
Unity标记固定颜色及投影标记
unity
云雨巫山4 天前
Unity 游戏开发性能优化全景手册
unity·智能手机·性能优化·游戏引擎