1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dingxiaowei-Aladdin_XLua

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Aladdin_XLua

[Unity XLua] 热更新 XLua 入门 (一) — 基础篇

Предисловие

Некоторое время назад Tencent открыл исходный код внутреннего фреймворка для горячего обновления XLua в сообществе разработчиков Unity. Это вызвало бурное обсуждение и получило поддержку многих разработчиков. Я, конечно же, с любопытством начал изучать его. Позже я также опубликую расширенную версию проекта на git, чтобы мы могли учиться и общаться вместе! Здесь я хотел бы выразить свою благодарность автору XLua за создание такого полезного фреймворка!

Связанные ссылки:

  1. [Исходный код XLua](Unity3D 热更 Lua Framework 入门实操).
  2. C#->Lua открытый инструмент. Можно преобразовать C# в lua и обладает...
  3. Статьи о введении, [https://www.oschina.net/news/80638/c-net-lua-unity3d].

Мои взгляды на XLua:

  1. Простой и удобный, легко начать работу.
  2. Высокая расширяемость, удобно добавлять пользовательские модули CS или сторонние плагины.
  3. Поддержка от крупных компаний, надёжная.
  4. Особенность: HotFix. Этот HotFix является уникальной особенностью XLua, которой нет у других фреймворков для горячего обновления lua. Принцип заключается в использовании специальных меток, а затем в логическом слое IL для изменения логики, что позволяет программе поддерживать логику кода lua для горячего обновления вместо предыдущей логики C#.

Расширение поддержки NGUI в XLua В настоящее время существует мало открытых фреймворков горячего обновления Lua, которые поддерживают NGUI. Возможно, сейчас тенденция заключается в использовании собственного UGUI. Однако некоторые разработчики, использующие NGUI, могут предпочесть продолжать использовать его. Хотя NGUI использовался в течение длительного времени, пример использования lua в XLua уже поддерживает UGUI. Здесь я дополню его, чтобы он поддерживал разработку NGUI. В будущем я добавлю больше примеров UGUI. Давайте сначала посмотрим на эффект интерфейса, который был расширен для поддержки NGUI, а затем объясним, как сделать так, чтобы XLua поддерживал сторонние плагины.

Эффект изображения:

Здесь напишите описание изображения.

Быстрый старт Прежде чем изучать что-то новое, лучше всего сначала изучить множество обучающих документов, написанных автором XLua. Они включают примеры, wiki и issu. Если у вас есть какие-либо вопросы, вы можете присоединиться к группе в конце статьи, чтобы обсудить и изучить их вместе.

1. Создание пользовательских классов C#, доступных для Lua Здесь вы можете изучить пример в Test, предоставленный автором. Он довольно подробный, но я всё равно хочу записать свой собственный процесс.

(1) Способ с использованием атрибутов XLua поддерживает использование атрибутов для маркировки, чтобы пользовательские классы были доступны для Lua. C#:

[LuaCallCSharp]
public class CSModelWithAttribute
{
    public static void SayHello1()
    {
        Debug.Log("Hello Aladdin_XLua, I am static model function");
    }
    public void SayHello2()
    {
        Debug.Log("Hello Aladdin_XLua, I am model function");
    }
    public void SayHello3(string s)
    {
        Debug.Log("Hello Aladdin_XLua, I am model function whih param:" + s);
    }

    public string SayHello4(string s)
    {
        Debug.Log("Hello Aladdin_XLua, 我是具有返回值的CS方法:" + s);
        return "你好,我获得了lua,我是C#";
    }

    public void SayHelloWithRefParam(ref string s)
    {
        Debug.Log("传入的参数是:" + s);
        s = "Hello 我是C#";
    }

    public string SayHelloWithRefParamAndReturnString(ref string s)
    {
        Debug.Log("传入的参数是:" + s);
        s = "Hello 我是C#";
        return "我是返回的字符串";
    }

    public void SayHelloWithOutParam(out string s)
    {
        s = "Hello,我是C#";
        Debug.Log("Hello Aladdin_XLua, I am model function whih out param:" + s);
    }
}

После добавления атрибута программа автоматически найдёт класс с атрибутом при запуске и добавит его в стек Lua, чтобы мы могли получить доступ к пользовательским классам и методам C# через Lua.

Lua доступ:

using UnityEngine;
using System.Collections;
using XLua;
public class SelfExampleSrc : MonoBehaviour
{
    LuaEnv luaenv = new LuaEnv();
    void Start()
    {
        luaenv.DoString(@"

            print('Lua访问特性标记的对象方法')
            local luaM2 = CS.CSModelWithAttribute
            local luaO2 = luaM2()
            luaM2:SayHello1()
            luaO2:SayHello2()
            luaO2:SayHello3('我是阿拉丁')  --每次添加一个CS方法时候都要重新Generate一下啊

            --测试字符串返回
            local value = luaO2:SayHello4('你好,我是lua')
            print(value)                              
            
            --测试ref
            local inputValue = '你好,我是lua'
            local outputValue = luaO2:SayHelloWithRefParam(inputValue)
            print(outputValue)                          --lua是通过字符串返回

            local outValue1,outValue2 = luaO2:SayHelloWithRefParamAndReturnString(inputValue)
            print(outValue1)
            print(outValue2)
            
            --测试out
            inputValue = '我是测试lua'
            outputValue = luaO2:SayHelloWithOutParam(inputValue)
            print(outputValue)
            
            local luaM3 = CS.CSModelTest
            local luaO3 = luaM3()
            luaO3.TestDelegate('lua中测试委托')


            luaO3.onClick = function(obj)
                print('hello 我是lua')
                print(obj)
            end
            luaO3.onClick('我是lua')
        ");
    }
}

(2) Метод обёртки Если мы сами пишем код C#, мы можем добавить атрибут, чтобы сделать класс доступным для Lua, что довольно удобно. Но если мы используем сторонний плагин, как быстро сделать его доступным для XLua? Мы можем использовать метод обёртки Generate, который также используется другими фреймворками Lua.

a) Классы с пространствами имён

C#:

namespace Aladdin_XLua
{
    public class CSModel
    {
        public void SayHello()
        {
            Debug.Log("Hello Aladdin_XLua");
        }
    }
}

Lua:

print('Lua доступ к именованному объекту / статический метод') local luaModel = CS.Aladdin_XLua.CSModel local luaObj = luaModel() luaObj:SayHello()


**б) Доступ к классу без пространства имён**

C#:

public class CSModelWidhoutNameSpace { public void SayHello() { Debug.Log("Hello Aladdin_XLua without Namespace"); } }


Lua:

print('Lua доступ к методу объекта без пространства имен') local luaM = CS.CSModelWidhoutNameSpace local luaO = luaM() luaO:SayHello()


«Если нет пространства имён, то после CS идёт имя класса. На самом деле CS — это ещё один уровень пространства имён, просто автор помог нам с разделением».

**3. Тип делегата**

C#

public class CSModelTest { public SelfVoidDelegate onClick; public delegate void SelfVoidDelegate(GameObject go); void OnClick() { Debug.Log("Тест"); }

public Action<string> TestDelegate = (param) =>
{
    Debug.log("TestDelegate in c#:" + param);
};

}


Делегат фактически является типом, равным классу, поэтому мы должны обрабатывать его так же, как класс. Это можно сделать с помощью добавления атрибутов или через механизм Wrap. Здесь делегат находится внутри класса, но на самом деле он может быть помещён непосредственно в пространство имён. Так работает .NET-библиотека, хотя, если посмотреть исходный код NGUI, мы увидим, что все кнопки используют этот подход для обработки событий.

Lua

local luaM3 = CS.CSModelTest local luaO3 = luaM3() luaO3.TestDelegate('lua тест делегата')

luaO3.onClick = function(obj) print('hello Я — lua') print(obj) end luaO3.onClick('Я — lua')


**4. Функции с параметрами ref и out**

Поскольку Lua — это язык со слабой типизацией, в котором нет такого разнообразия типов, как в C#, иногда возникают проблемы с обработкой параметров. В XLua есть раздел Issues, где автор отвечает на вопросы пользователей. Ниже приведён пример того, как функции с параметрами ref и out обрабатываются в Lua.

C#

public void SayHelloWithRefParam(ref string s) { Debug.Log("Переданный параметр: " + s); s = "Привет, я — C#"; }

public string SayHelloWithRefParamAndReturnString(ref string s) { Debug.Log("Переданный параметр: " + s); s = "Привет, я — C#"; return "Я — возвращаемая строка"; }

public void SayHelloWithOutParam(out string s) { s = "Привет, это — C#"; Debug.Log("Привет, Aladdin_XLua, я — функция модели с параметром out: " + s); }


Сначала я думал, что Lua вернёт изменённое значение параметра ref, переданного в функцию. Но этого не произошло. Автор подсказал мне, что Lua возвращает изменённое значение через возвращаемое значение функции. Если функция уже имеет возвращаемое значение, то последним параметром будет либо параметр ref, либо out.

Lua

-- Тестирование ref local inputValue = 'Привет, я — lua' local outputValue = luaO2:SayHelloWithRefParam(inputValue) print(outputValue) -- lua возвращает результат через строку

local outValue1, outValue2 = luaO2:SayHelloWithRefParamAndReturnString(inputValue) print(outValue1) print(outValue2)

-- Тестирование out inputValue = 'Я — тестовый lua' outputValue = luaO2:SayHelloWithOutParam(inputValue) print(outputValue)


*Примечание: в запросе отсутствует информация о том, какой именно фрагмент текста необходимо перевести. Поэтому ответ содержит перевод всего текста.* **b) Построить два пользовательских интерфейса (UI), логика интерфейса на C#, Lua вызывает методы C# в логике вызова интерфейса.**

**C#:**

using UnityEngine; using System.Collections; using XLua; public class AsyncBuy : MonoBehaviour { LuaEnv luaenv = null;

void Start()
{
    luaenv = new LuaEnv();
    luaenv.DoString("require 'async_buy'");
}

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

}

**Логика панели:**

using UnityEngine; using UnityEngine.UI; using XLua; using System.Collections.Generic; using System; using UnityEngine.Events;

public class MessagePanel : MonoBehaviour { ///

/// Показать диалоговое окно /// /// /// /// public static void ShowAlertPanel(string message, string title, Action onFinished = null) { Debug.Log("Показать диалоговое окно"); var rootPanel = GameObject.Find("Panel").transform; var alertPanel = rootPanel.Find("AlertPanel"); if (alertPanel == null) { alertPanel = (Instantiate(Resources.Load("AlertPanel")) as GameObject).transform; alertPanel.gameObject.name = "AlertPanel"; alertPanel.SetParent(rootPanel); alertPanel.localPosition = Vector3.zero; alertPanel.localScale = Vector3.one; } alertPanel.Find("Title").GetComponent().text = title; alertPanel.Find("Content").GetComponent().text = message; alertPanel.gameObject.SetActive(true); if (onFinished != null) { var buyBtn = alertPanel.Find("BtnBuy").gameObject; buyBtn.SetActive(true); var button = buyBtn.GetComponent(); UIEventListener.Get(buyBtn).onClick = go => { onFinished(); alertPanel.gameObject.SetActive(false); }; } }

/// <summary>
/// Показать подтверждающее окно
/// </summary>
/// <param name="message"></param>
/// <param name="title"></param>
/// <param name="onFinished"></param>
public static void ShowConfirmPanel(string message, string title, Action<bool> onFinished = null)
{
    var rootPanel = GameObject.Find("Panel").transform;
    var confirmPanel = rootPanel.Find("ConfirmPanel");
    if (confirmPanel == null)
    {
        confirmPanel = (Instantiate(Resources.Load("ConfirmPanel")) as GameObject).transform;
        confirmPanel.gameObject.name = "ConfirmPanel";
        confirmPanel.SetParent(rootPanel);
        confirmPanel.localPosition = Vector3.zero;
        confirmPanel.localScale = Vector3.one;
    }
    confirmPanel.Find("Title").GetComponent<UILabel>().text = title;
    confirmPanel.Find("Content").GetComponent<UILabel>().text = message;
    confirmPanel.gameObject.SetActive(true);
    if (onFinished != null)
    {
        var confirmBtn = confirmPanel.Find("BtnBuy").GetComponent<UIButton>();
        var cancelBtn = confirmPanel.Find("CancelBuy").GetComponent<UIButton>();

        UIEventListener.Get(confirmBtn.gameObject).onClick = go =>
        {
            onFinished(true);
            confirmPanel.gameObject.SetActive(false);
        };

        UIEventListener.Get(cancelBtn.gameObject).onClick = go =>
        {
            confirmPanel.gameObject.SetActive(false);
        };
    }
}

}

**Lua:**
lua-файл можно поместить в соответствующие ресурсы.
async_buy.lua
``` **Перевод кода на русский язык:**

async_recharge -------------------------async_recharge----------------------------- local function async_recharge(num, cb) --模拟的异步充值 print('request server...') cb(true, num) end

local recharge = util.async_to_sync(async_recharge) -------------------------async_recharge end---------------------------- local buy = function() message_panel.alert("余额提醒", "您余额不足,请充值!") if message_panel.confirm("确认充值10元吗?", "确认框" ) then local r1, r2 = recharge(10) print('recharge result', r1, r2) message_panel.alert("提示", "充值成功!") else print('cancel') message_panel.alert("提示", "取消充值!") end end

CS.UIEventListener.Get(CS.UnityEngine.GameObject.Find("BtnBuy").gameObject).onClick = util.coroutine_call(buy)


**Перевод message_panel.lua:**

local util = require 'xlua.util'

local sync_alert = util.async_to_sync(CS.MessagePanel.ShowAlertPanel) local sync_confirm = util.async_to_sync(CS.MessagePanel.ShowConfirmPanel)

--构造alert和confirm函数 return { alert = function(title, message) if not message then title, message = message, title end sync_alert(message,title) end;

confirm = function(title, message)
    local ret = sync_confirm(title,message)
    return ret == true
end;

}


Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Описание недоступно Развернуть Свернуть
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/dingxiaowei-Aladdin_XLua.git
git@api.gitlife.ru:oschina-mirror/dingxiaowei-Aladdin_XLua.git
oschina-mirror
dingxiaowei-Aladdin_XLua
dingxiaowei-Aladdin_XLua
master