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
相关推荐
派葛穆11 小时前
Unity-UI 输入框功能
ui·unity·游戏引擎
玖玥拾11 小时前
Unity3D RPG 入门项目(一)开场动画/人物移动/摄像机跟随场景切换
unity·游戏引擎
2401_8949155313 小时前
GEO 搜索优化完整源码从零部署:环境配置、集群搭建全流程
开发语言·python·tcp/ip·算法·unity
WarPigs14 小时前
PC端加载安卓AB包资源显示紫色的问题
unity
scott.cgi17 小时前
Unity使用AndroidX获取,导航栏与虚拟键盘的高度
unity·androidx·keyboard·导航栏高度·虚拟键盘高度·判断键盘关闭·获取虚拟键盘高度
丁小未18 小时前
Unity车机地图Tile流式渲染系统高性能架构方案
unity·架构·ecs·dots·车机系统·车机系统架构图
LONGZETECH1 天前
工业实训仿真设计实践:电机拆装软件的 DAG 流程建模、工具精度分级与数据体系搭建
大数据·算法·unity·架构·汽车
派葛穆2 天前
Unity-UI 按钮点击弹窗功能
unity·游戏引擎
toponad2 天前
Unity Ads Bidding 现已正式加入TopOn 聚合平台
unity·topon