Unity C# Xlua와의 상호 작용 Lua 호출 C# LuaCallcsharp
10348 단어 XLua
LuaCallCSharp
비고: Lua Call C# 코드를 만들 때 C#에서 생성된 코드는 기본적으로 [Lua Call Csharp]를 태그해야 합니다.라벨에 대한 이해는 뒷글에서 상세하게 설명할 것이다.
1. 새 C# 객체
C#에 다음과 같은 개체를 생성했습니다.GameObject go = new GameObject();
그럼 루아는 어떻게 썼을까요?다음과 같습니다.local go = CS.UnityEngine.GameObject()
지식점: 우선 Lua에 new 키워드가 없기 때문에 새 대상을 만들 때 new를 생략하면 됩니다. 그 다음에 모든 C#와 관련된 것은 접두사'CS'를 붙여야 합니다.구조 함수, 정적 구성원 속성, 방법 포함.동시에 명명 공간namespace를 추가하는 것을 잊지 마세요.그래서 C#의 GameObject 클래스는 Lua에서 CS입니다.UnityEngine.GameObject.
class에 여러 개의 구조 함수가 있을 때 xlua에서도 재부팅을 지원합니다. 예를 들어 GameObject는string 매개 변수를 가진 재부팅이 GameObject의 이름을 지정하는 데 사용되며, 대응하는 Lua는 다음과 같습니다.local go = CS.UnityEngine.GameObject('helloworld')
2. C# 정적 속성, 메서드 액세스
위에서 알 수 있듯이 Lua에서 GameObject를 호출하는 클래스는 CS입니다.UnityEngine.GameObject, Find (string) 와 같은 GameObject의 정적 방법을 사용하려면 다음과 같이 하십시오.local go = CS.UnityEngine.GameObject.Find('helloworld')
정적 속성에 액세스하는 것도 마찬가지입니다. 예를 들면 다음과 같습니다.CS.UnityEngine.Time.deltaTime
--
CS.UnityEngine.Time.timeScale = 0.5
권장: 자주 액세스해야 하는 클래스는 먼저 로컬 변수로 참조한 후 액세스할 수 있으므로 코드의 양을 줄이고 다음과 같은 성능을 향상시킬 수 있습니다.local GameObject = CS.UnityEngine.GameObject
--
GameObject.Find('helloworld')
GameObject.FindGameObjectsWithTag("tag")
3. C# 구성원 속성, 메서드 액세스
C#과 마찬가지로 구성원 등록 정보에 액세스하려면 클래스의 인스턴스를 통해 액세스해야 합니다.
C#에 다음과 같은 클래스가 정의되어 있다고 가정합니다.namespace MyExamples {
[LuaCallCSharp]
public class Test {
public int index;
public int Add(int a, int b) {
return a + b;
}
}
}
이에 대응하는 Lua는 다음과 같습니다.local Test = CS.MyExamples.Test;
local test = Test();
test.index = 66;
print('test.index---'..test.index);
print('test.Add---'..test.Add(test,1,2));
print('test:Add---'..test:Add(3,4));
주의해야 할 것은 만약 사용한다면.구성원 방법을 호출하려면 첫 번째 파라미터가 이 대상을 전달해야 하기 때문에 방문(사칭 문법당)을 사용하는 것을 권장합니다.
4. 상위 클래스 속성, 메서드에 액세스
XLua는 기본 클래스를 통해 기본 클래스에 접근하는 정적 속성, 정적 방법, (파생 클래스의 실례를 통해) 기본 클래스에 접근하는 구성원 속성, 구성원 방법을 지원합니다.
5. 매개 변수의 입력 출력 속성 (out,ref)
매개 변수 처리 규칙: Lua가 C# 방법을 호출할 때 C# 방법의 매개 변수는 왼쪽에서 오른쪽으로 계산됩니다. 일반적인 매개 변수는 입력 인삼을 계산하고ref 수식은 입력 인삼을 계산하며 out 수식은 계산하지 않습니다.
반환값 처리 규칙: Lua가 C# 방법의 반환값을 받아들일 때 C# 방법의 반환값(있을 경우)은 반환값을 계산하고, (형삼 중의)ref는 반환값을 계산하며, out는 반환값을 계산하며, 왼쪽에서 오른쪽으로lua에 대응하는 다중 반환값을 계산한다.
구체적으로 무슨 뜻입니까?코드를 직접 올리다.C# 에서 다음과 같은 방법이 있습니다.namespace MyExamples {
[LuaCallCSharp]
public class A {
public static int Method(int a, ref int b, out int c, Action funA, out Action funB) {
Debug.Log("Method-----a:" + a + "----b:" + b);
c = 10;
funA();
funB = () => { Debug.Log("exe---funB"); };
return 5;
}
}
}
위의 규칙에 따라 아래 Lua를 사용하여 처리할 수 있습니다.--
--
local ret, ret_b, ret_c, ret_funB = CS.MyExamples.A.Method(1,2,function()
print('exe----funA');
end);
print('CS.MyExamples.A.Method return---', ret, ret_b, ret_c, ret_funB);
ret_funB();
주의: 여기에서 우리는 루아의 function을 C#의 Action 매개 변수에 전달합니다. 이것은 지난번에 말한 루아 함수를 c# 의뢰에 비추는 것과 같습니다. 따라서 우리는 Action을 CSharp Call Lua의 화이트 리스트에 추가해야 합니다. 탭 화이트 리스트에 대해서는 후속 글에서 설명할 것입니다.이와 유사한 것은 Func<> 등의 의뢰(그렇지 않으면 Lua Exception: c# exception: System. Invalid Cast Exception: This type must add to Csharp Call Lua: System. Action)
6. 재부팅 방법
C#와 마찬가지로 접근 방법이 다른 실참으로 함수를 다시 불러올 수 있다. 예를 들어testSon:Log(3);
testSon:Log('qwe');
주의: XLua는 리셋 함수 호출만 어느 정도 지원합니다. 왜냐하면 Lua의 유형은 C#의 풍부함보다 훨씬 못하기 때문입니다. 예를 들어 C#의 int,float,double 등은 모두 Lua의number에 대응하기 때문입니다.C#에 이러한 유형의 재부팅이 있으면 Lua는 구별할 수 없으며 둘 중 하나만 호출할 수 있습니다(코드의 앞줄 생성).
7. 매개 변수에 기본값이 있는 방법, 가변 매개 변수 방법
매개변수에 기본값이 있는 메서드의 경우 C#과 마찬가지로 인삼보다 적은 인삼을 주면 기본값으로 보정됩니다.
가변 매개변수의 경우 코드는 다음과 같습니다.public class A {
public static void MethodC(string s, params int[] arr) {
foreach(int i in arr) {
Debug.Log("MethodC----" + i);
}
}
}
의 lua 에 대해 다음을 수행합니다.CS.MyExamples.A.MethodC('s',1,2,3);
8. 열거 유형
매거 값은 매거 유형의 정적 속성과 같다.우리 C#에 다음과 같은 열거가 있다고 가정하면namespace MyExamples {
public enum ETest {
T1,
T2,
T3
}
}
그러면 루아에서 CS를 사용합니다.MyExamples.ETest.T1이면 됩니다.
또한 코드 생성에 열거 클래스가 추가되면 (즉 [LuaCallcsharp] 탭 추가) 열거 클래스는 를 지원합니다CastFrom 메서드는 정수 또는 문자열에서 열거 값으로 변환할 수 있습니다.CS.MyExamples.A.MethodD(CS.MyExamples.ETest.T1);
CS.MyExamples.A.MethodD(CS.MyExamples.ETest.__CastFrom(1));
CS.MyExamples.A.MethodD(CS.MyExamples.ETest.__CastFrom('T3'));
9.delegate 사용(호출 + -)
C#에 대한 delegate 호출: 일반 lua 함수 호출과 동일
예를 들어, C#에서 다음과 같은 delegate를 정의했습니다.[LuaCallCSharp]
public class TestSon : Test {
public delegate int IntDelegate(int a);
public IntDelegate intDelegate = (a) => {
Debug.Log("C#--intDelegate----a:" + a);
return a;
};
}
해당 Lua 액세스:testSon.intDelegate(10);
+ 조작부호: C#의 + 조작부호에 대응하여 두 개의 호출을 하나의 호출체인으로 연결하고 오른쪽 조작수는 같은 종류의 C# delegate 또는 lua 함수일 수 있다.
- 조작부호: +와 반대로 호출체인에서 delegate를 제거합니다.
ps:delegate 속성은 lua function으로 값을 지정할 수 있습니다.local function lua_delegate(a)
print('lua_delegate :', a)
end
testSon.intDelegate = lua_delegate + testSon.intDelegate --combine, C#delegate ,
testSon.intDelegate(100)
testSon.intDelegate = testSon.intDelegate - lua_delegate --remove
testSon.intDelegate(1000)
제5조와 유사합니다: CSharp Call Lua 화이트 리스트에 IntDelegate를 추가해야 합니다.
10. 이벤트 사용
예를 들어 우리는 아래의 이벤트를 정의했다public class TestSon : Test {
public event IntDelegate intEvent;
public void ExeEvent(int a) {
intEvent(a);
}
}
Lua에서 다음과 같은 방식으로 처리하고 접근할 수 있습니다local function lua_eventCallback1(a)
print('lua_eventCallback1 :', a)
end
local function lua_eventCallback2(a)
print('lua_eventCallback2 :', a)
end
--
testSon:intEvent('+', lua_eventCallback1);
testSon:intEvent('+', lua_eventCallback2);
testSon:ExeEvent(100);
--
testSon:intEvent('-', lua_eventCallback1);
testSon:ExeEvent(1000);
testSon:intEvent('-', lua_eventCallback2);
11.C#의 복잡한 유형 및 테이블 자동 변환
구조 함수가 없는 C#의 복잡한 유형은 Lua에서 하나의 테이블로 대체할 수 있다. 이 테이블은 복잡한 유형에 대응하는public 필드에 해당하는 필드가 있으면 함수 매개 변수 전달, 속성 값 부여 등을 지원한다.(C#Lua를 호출할 때와 유사)
예를 들어 우리는 다음과 같은 struct(class도 마찬가지)가 있다.public struct BoxA {
int x;
int y;
}
public struct BoxB {
BoxA boxA;
string name;
}
그런 다음 Struct를 사용하는 방법은 C#에 있습니다.public static void MethodE(BoxB box) {
Debug.Log("MethodE----name:" + box.name + "----x:" + box.boxA.x);
}
그러면 lua에서 다음과 같이 호출할 수 있습니다.CS.MyExamples.A.MethodE({boxA={x=1,y=2},name='box'});
12. 가져오는 유형(C#의 typeof)
예를 들어 루아에서 클래스의 Type 정보를 얻으려면 typeof () 를 사용하면 구성 요소를 추가할 때 자주 사용됩니다. 다음과 같습니다.go:AddComponent(typeof(CS.UnityEngine.ParticleSystem));
13. "강" 전환 유형
lua에는 유형이 없기 때문에 강한 유형의 언어의'강전'은 없지만 약간 비슷한 것이 있다. XLua에게 지정한 생성 코드로 대상을 호출해야 한다고 알려주는 것이다.예를 들어 제3자 라이브러리가 외부에 노출되었을 때 하나의interface나 추상적인 클래스는 실현 클래스가 숨겨져 있기 때문에 우리는 실현 클래스에 대해 코드의 생성을 할 수 없다.이 실행 클래스는 XLua에서 생성되지 않은 코드로 식별되어 반사로 접근할 것입니다. 이 호출이 빈번하면 성능에 영향을 미칠 수 있습니다. 이 인터페이스나 추상 클래스를 생성 코드에 추가한 다음 이 생성 코드로 접근할 수 있도록 지정할 수 있습니다.
XLua는 T캐스트(table, T)의 API를 강전으로 제공합니다. 이 Table를 T가 가리키는 형식으로 변환합니다. CSharp Call Lua가 설명한 인터페이스, 기본 구조 함수가 있는class나 struct, Dictionary, List 등입니다.
예를 들어 우리는 C#에서 다음과 같이 정의했다//
[LuaCallCSharp]
public interface ICalc {
int add(int a, int b);
}
// ,
class CalcClass : ICalc {
public int add(int a, int b) {
return a + b;
}
public int id = 100;
}
public class Test {
// api
public ICalc GetCalc() {
return new CalcClass();
}
}
Lua에서는 다음과 같은 작업을 수행할 수 있습니다.local calc = test:GetCalc();
print('calc------Add:',calc:Add(1,2));
위에서 언급한 이런 방식은 바로 앞에서 언급한 시사 방식으로 성능이 비교적 떨어진다.따라서 성능 향상을 위해 다음과 같은 단계를 강화할 수 있습니다.cast(calc, typeof(CS.MyExamples.ICalc));
print('calc---case---add:',calc:Add(3,4));
-- , interface , ICalc id , id ( ) nil
assert(calc.id == nil);
-- qwer
assert(calc.qwer == nil);
ps: lua assert () API, 파라미터가false 또는nil일 때 프로그램을 중단하고 이상을 던집니다.
14. 확장 방법 Extension methods
C#에 확장 방법이 정의되어 있으며 Lua에서는 일반 구성원을 방문하는 방법과 같이 사용할 수 있습니다. 다음은 앞의 Test 클래스에 확장 방법을 추가합니다.
참고: 확장 방법은 [LuaCallcsharp] 탭을 붙여야 액세스할 수 있습니다.[LuaCallCSharp]
public static class ExtraTest {
public static void ExtraLog(this Test test, string s) {
Debug.Log("ExtraTest----ExtraLog---" + s);
}
}
그런 다음 lua에서 이전 Test 클래스의 인스턴스를 사용하여 액세스할 수 있습니다.test:ExtraLog('122334');
15. 일반화(템플릿) 방법
Lua에서는 범용을 직접 지원하지 않습니다. 확장 방법을 통해 봉인한 다음 확장 방법을 사용해야 합니다.예를 들어, C#에는 다음과 같은 정의가 있습니다.public class Test {
public void GenericMethod() {
Debug.Log("GenericMethod");
}
}
루아에서 우리는 C#처럼 직접 테스트를 사용할 수 없다.GenericMethod() 이렇게 호출하려면 다음과 같이 레이어를 수동으로 패키지해야 합니다.public static class ExtraTest {
public static void GenericMethodWithString(this Test test) {
test.GenericMethod();
}
}
그리고 루아로 호출합니다:test:GenericMethodWithString();
GameObject go = new GameObject();
local go = CS.UnityEngine.GameObject()
local go = CS.UnityEngine.GameObject('helloworld')
local go = CS.UnityEngine.GameObject.Find('helloworld')
CS.UnityEngine.Time.deltaTime
--
CS.UnityEngine.Time.timeScale = 0.5
local GameObject = CS.UnityEngine.GameObject
--
GameObject.Find('helloworld')
GameObject.FindGameObjectsWithTag("tag")
namespace MyExamples {
[LuaCallCSharp]
public class Test {
public int index;
public int Add(int a, int b) {
return a + b;
}
}
}
local Test = CS.MyExamples.Test;
local test = Test();
test.index = 66;
print('test.index---'..test.index);
print('test.Add---'..test.Add(test,1,2));
print('test:Add---'..test:Add(3,4));
namespace MyExamples {
[LuaCallCSharp]
public class A {
public static int Method(int a, ref int b, out int c, Action funA, out Action funB) {
Debug.Log("Method-----a:" + a + "----b:" + b);
c = 10;
funA();
funB = () => { Debug.Log("exe---funB"); };
return 5;
}
}
}
--
--
local ret, ret_b, ret_c, ret_funB = CS.MyExamples.A.Method(1,2,function()
print('exe----funA');
end);
print('CS.MyExamples.A.Method return---', ret, ret_b, ret_c, ret_funB);
ret_funB();
testSon:Log(3);
testSon:Log('qwe');
public class A {
public static void MethodC(string s, params int[] arr) {
foreach(int i in arr) {
Debug.Log("MethodC----" + i);
}
}
}
CS.MyExamples.A.MethodC('s',1,2,3);
namespace MyExamples {
public enum ETest {
T1,
T2,
T3
}
}
CS.MyExamples.A.MethodD(CS.MyExamples.ETest.T1);
CS.MyExamples.A.MethodD(CS.MyExamples.ETest.__CastFrom(1));
CS.MyExamples.A.MethodD(CS.MyExamples.ETest.__CastFrom('T3'));
[LuaCallCSharp]
public class TestSon : Test {
public delegate int IntDelegate(int a);
public IntDelegate intDelegate = (a) => {
Debug.Log("C#--intDelegate----a:" + a);
return a;
};
}
testSon.intDelegate(10);
local function lua_delegate(a)
print('lua_delegate :', a)
end
testSon.intDelegate = lua_delegate + testSon.intDelegate --combine, C#delegate ,
testSon.intDelegate(100)
testSon.intDelegate = testSon.intDelegate - lua_delegate --remove
testSon.intDelegate(1000)
public class TestSon : Test {
public event IntDelegate intEvent;
public void ExeEvent(int a) {
intEvent(a);
}
}
local function lua_eventCallback1(a)
print('lua_eventCallback1 :', a)
end
local function lua_eventCallback2(a)
print('lua_eventCallback2 :', a)
end
--
testSon:intEvent('+', lua_eventCallback1);
testSon:intEvent('+', lua_eventCallback2);
testSon:ExeEvent(100);
--
testSon:intEvent('-', lua_eventCallback1);
testSon:ExeEvent(1000);
testSon:intEvent('-', lua_eventCallback2);
public struct BoxA {
int x;
int y;
}
public struct BoxB {
BoxA boxA;
string name;
}
public static void MethodE(BoxB box) {
Debug.Log("MethodE----name:" + box.name + "----x:" + box.boxA.x);
}
CS.MyExamples.A.MethodE({boxA={x=1,y=2},name='box'});
go:AddComponent(typeof(CS.UnityEngine.ParticleSystem));
//
[LuaCallCSharp]
public interface ICalc {
int add(int a, int b);
}
// ,
class CalcClass : ICalc {
public int add(int a, int b) {
return a + b;
}
public int id = 100;
}
public class Test {
// api
public ICalc GetCalc() {
return new CalcClass();
}
}
local calc = test:GetCalc();
print('calc------Add:',calc:Add(1,2));
cast(calc, typeof(CS.MyExamples.ICalc));
print('calc---case---add:',calc:Add(3,4));
-- , interface , ICalc id , id ( ) nil
assert(calc.id == nil);
-- qwer
assert(calc.qwer == nil);
[LuaCallCSharp]
public static class ExtraTest {
public static void ExtraLog(this Test test, string s) {
Debug.Log("ExtraTest----ExtraLog---" + s);
}
}
test:ExtraLog('122334');
public class Test {
public void GenericMethod() {
Debug.Log("GenericMethod");
}
}
public static class ExtraTest {
public static void GenericMethodWithString(this Test test) {
test.GenericMethod();
}
}
test:GenericMethodWithString();