nyuuzyou/wikis huggingface dataset:
LSL Script Efficiency/de

== Was ist Effizienz ==
Effizienz bedeutet, wieviel Resourcen ein bestimmtes Script benötigt um seine Aufgabe zu erfüllen. Die Ausführungsgeschwindigkeit ist häufig von der Resourcennutzung abhängig, aber nicht immer.
Eine nach Wichtigkeit grob sortierte Liste mit Dingen die beim guten scripten beachtet werden sollten:
* Nutzung vieler Scripte um etwas zu erreichen. Siehe auch: Efficient Design
* llSleep - Diese Funktion benötigt 0.2 bis 0.3 ms pro frame während das Script schläft, die Nutzung eines Timers ist viel besser.
* Häufig ausgelöste Timer (<5 sek)
* Listen - insbesondere auf Kanal 0
* Häufig wechselnde texturen (die anderen müssen diese erst herunterladen)
* Unangebrachte Nutzung von server/physikalischen Rotationen anstelle von llTargetOmega
* Event handlers die nicht benötigt werden (touch, collision, ...)
* Große Anzahl von email oder IM
* Ineffektive Algorithmen(Berechnungen) (z.B. lineare Suche)
* Unendliche Schleifen
LSL Script Efficiency/zh-Hans

__TOC__
== LSL脚本的执行效率 ==
效率是指一段特定的脚本要实现某个目标需要占用资源的多少。它一般是指脚本执行的速度，但不限于此。
以下是几点需要注意的事项，大体上按重要性排序：
* 为实现某种效果而使用大量的脚本。详见“设计高效率的脚本”
* llSleep - 当脚本休眠时，这个函数每帧大概要多消耗 0.2 到 0.3 毫秒，使用 timers 会更好。
* 频繁使用 timers (<5秒)
* Listen - 特别是对0号频道的监听。
* 频繁地改变纹理(别人不得不下载它们)
* 不恰当地用服务器/物理旋转代替 omega
* 非必要的事件处理函数 (touch, collision, ...)
* 大量的 email 或 IM
* 低效的脚本(如线性查找)
* 使用闲置循环 (在一个循环中反复请求数据)
== 设计高效率的脚本 ==
一个对象中的每个无用脚本都耗费每帧 0.001 到 0.003 的脚本时间，所以脚本越少越好。
* 如果你需要使用一组“按钮”，不要在每个元件中加入脚本，而是在主脚本中用llDetectedLinkNumber来侦测到底是哪个按钮被触发了。 
* 如果你需要改变子元件的颜色、透明度或材质，不要在每个元件中加入脚本，而是使用llSetLinkAlpha，llSetLinkColor，llSetLinkTexture，或llSetLinkPrimitiveParams。
* 永远不要在每个元件(特别是对于包含在较大的linkset中的)中加入脚本来监听0号频道(或任何其它的频道)。对于效率而言这也许是最糟糕的事情，不幸的是这是经常发生的。
* 应考虑XyzzyText来代替XyText。
最起码的，如果你发现有必要在每个元件中加入脚本，也要停下来想想是否有其它的方法用更少的脚本完成它。总会有变通的方法，这种变通在你的程序中是否可行完全取决于你。
== 微优化 ==
有众多方法可以让脚本的执行速度更快，比如用++a代替a++，然而，这种优化在将来未必仍然有用。
== 代码到底运行得有多快 ==
下面的代码会取得调用每个函数的时间，请到讨论页提出修改意见。由于任何微小的改动都会影响测量的精准，请不要在经过讨论之前修改这里的代码。请确保这些代码与它的注释都与Efficiency Tester页面保持一致。
感谢提供原始代码，感谢调整了这些代码使它更加准确，也要感谢列在本文编辑历史中的所有贡献者。
//IMPORTANT: Only perform tests in an empty region.
// To reduce contamination and be sure to wearing no attachments.
// Preferably do tests in a private sim with one on it.
// Don't move while performing the test.
// There is a margin of error so run the tests multiple times to determine it.
integer time() { // count milliseconds since the day began
 string stamp = llGetTimestamp(); // "YYYY-MM-DDThh:mm:ss.ff..fZ"
 return (integer) llGetSubString(stamp, 11, 12) * 3600000 + // hh
 (integer) llGetSubString(stamp, 14, 15) * 60000 + // mm
 llRound((float)llGetSubString(stamp, 17, -2) * 1000000.0)/1000; // ss.ff..f
}
default {
 state_entry() {
 llOwnerSay((string) llGetFreeMemory());
 //test variables
 float counter;
 //framework variables
 float i = 0;
 float j = 0;
 float max = 10000; // 2ms of work takes 20 seconds to repeat 10,000 times, plus overhead
 float t0 = time();
 do {
 //test
 counter += 1;
 
 }while (++i < max);
 float t1 = time();
 do ; while (++j < max);
 float t2 = time();//remove the time required by the framework
 float elapsed = ((t1 - t0) - (t2 - t1))/max;
 llOwnerSay("The function in the loop took a total of " + (string)elapsed + " 
milliseconds.");
 }
}
== 效率 ==
下面的数据是使用上面的代码在一个刚部署的(但不是私人的)模拟器上取得的, 这个代码单独运行在一个HUD附件上。测试进行了20次并取了平均值。
 ++a: 0.173780 ms std. dev.: 0.003393 ms
 a += 1: 0.181720 ms std. dev.: 0.013267 ms
 a++: 0.243500 ms std. dev.: 0.013816 ms
因此a++的执行时间比++a长40%(粗略估计)。
下面的数据同样是正确的，只是它没有用上面的函数，它用的是一个由稍作优化的版本。可能的话请大家用上面的函数重复测试。
 ++a: 0.364700 毫秒
 a += 1: 0.346900 毫秒
 a++: 0.413700 毫秒
这是用相同的函数在for循环中所做的测试：
 ++a: 0.358370 毫秒
 a += 1: 0.351200 毫秒
 a++: 0.424600 毫秒
llOwnerSay v. llSay v. llShout v. llWhisper (监听0号频道):
 llOwnerSay(): 4.359000 毫秒
 llWhisper(): 5.201000 毫秒
 llSay(): 5.226000 毫秒
 llShout(): 14.877000 毫秒
不同频道 (全部使用llSay()):
 -100000000: 1.226400 毫秒
 -100000: 1.254300 毫秒
 -100: 1.296100 毫秒
 -1: 1.292400 毫秒
 0: 5.226000 毫秒
 1: 1.242300 毫秒
 100: 1.249100 毫秒
 100000: 1.219700 毫秒
 100000000: 1.228700 毫秒
文本长度 (llSay() 全部使用1号频道):
 1 字节: 1.242300 毫秒
 10 字节: 1.309700 毫秒
 100 字节: 1.965600 毫秒
Category:LSL 教程 (简体中文)
LSL States

In LSL, most scripts sit idle until they receive some input, or detect some change in their environment. At any moment, the script is in some state, and will react to events or inputs according to some scheme defined by the programmer. However, a script can also contain two or more different states, and react differently to events or inputs depending on what state it is in.
One common abstract model that is used in such cases is called a Finite State Machine (see Wikipedia)].
For example, a door might be in a waiting state, and ignore all inputs except being touched. Once touched, it goes to the open state, in which it ignores being touched, but monitors which avatars pass through it. After a while, it changes to the closing state during which it closes, and then it returns to the waiting state.
States are not the only way to represent this kind of behavior, but in some cases they are a very good way.
In LSL, a state is a specified section of code within which all are specified. The main state that is required by all LSL scripts is called default; all scripts must have a default state, and every state must have at least one event.
To add another state add an entry like this:
 state my_state
 {
 state_entry()
 {
 // What should happen when we enter this state
 }
 
 // other events and code
 }
To switch from one state to another add a line like this:
 state my_state;
When this line of code is executed, it will run anything in the state_exit event, and then switch to the new state.
When switching states, all event queues are cleared, and events requiring setup are disabled such as sensor and listen. Surprisingly, timer is persisted across state changes
The state_entry event is run when the code enters that state. There is sometimes confusion in thinking that the state_entry event will run when a scripted object is rezzed from inventory. This is not the case as scripts are frozen when taken into inventory in the state they are in, and resume operation in that state when rezzed. The event first called when an object is rezzed out of inventory is on_rez.
== See also ==
For more information, see State.
LSL Style Guide/ja

LSL の効果的なプログラミングを行なうには、レイアウトと (コーディングの) 慣習をスクリプトへ適用するよう、制作者が規律正しく実践しなければなりません。
これら、スタイルガイドと呼ばれる集約的要素のガイドラインは、言語コンパイラが必要とするルールほど厳密ではありませんが、それでもなお効率的なメンテナンス性のあるコードを作成するためには必要です。最も効果的なスタイルの様相は、あなたの書くコードに首尾一貫性を持たせることです。
==一般的なガイドライン==
殆どの人々は、プログラミングの独習を始めた当初は、端的に言うと「醜い」プログラムを書きます。それらは大概、以下のような具合です:
 default {state_entry(){llSay(0,"Hello World.");}}
しかしながら、このコードは一行が一万語で書かれているプログラムの場合、読み解く（あるいは最後まで解釈する）ことが困難です。それ故、プログラマー達は括弧とインデントについて以下の二つの手法を主に用いて、コードを整形します。
手法 1:
 default {
 state_entry() {
 llSay(0, "Hello World.");
 }
 }
手法 2:
 default
 {
 state_entry()
 {
 llSay(0, "Hello World.");
 }
 }
手法1のスタイルでは行数を節約できますが、手法2のスタイルの方が初心者にとってより読みやすくなります。スクリプタは記述スタイルとして実施することにより、さらに読みやすいコードとなるでしょう。首尾一貫したインデントは、さまざまなスタイルをさらに読みやすくします。手法1におけるインデントは、スコープレベルを表現する鍵となります。
==命名規則==
Second Lifeには、多くの命名規則が存在します。ただ、最も使われるものは次に並んだものでしょう。
グローバル変数（プログラム全体を通して持ちいられる変数）は最初に小文字のgをつけるべきです。
 integer gSelected = 0;
 string gMyName = "Please set one";
定数として使用する変数は全て大文字を使用します。
 integer CHAT_CHAN = -517265;
 key OWNER_KEY = llGetOwner();
ユーザ定義関数やイベントの中で用いられる引数は、アンダーバー(_)から始めます。
 listen( integer _channel, string _name, key _id, string _message )
 {
 if ( _channel == 1 || _id == llGetOwner() )
 	llOwnerSay("Hello Avatar");
 }
==コードの分離==
多くの人達は一行で余りにも沢山の関数を呼び出そうとするでしょう。これはコードを読み難くして、極めてデバッグを困難にします。例として、このようなプログラムを挙げてみます。
list lst;
integer numDigits = 10;
default {
 touch_start(integer n) {
 integer i = 0;
 integer index = llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]);
 if (!~llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]))
 lst += llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1));
 llOwnerSay(llList2CSV(lst));
 }
}
先ほどのコードが何を行なっているかあなたに説明できる人は殆どいないでしょうが、以下のコードが何を行なっているかは殆どの人が説明できるでしょう。
list lst;
integer numDigits = 10;
default {
 touch_start(integer n) {
 integer i = 0;
 string name = llKey2Name(llDetectedKey(i));
 list nameAsList = llParseString2List(name, [" "], []);
 string firstName = llList2String(nameAsList, 0);
 string startPart = llToLower(llGetSubString(firstName, 0, numDigits - 1));
 integer index = llListFindList(lst, (list)startPart);
 if (!~index)
 lst += startPart;
 llOwnerSay(llList2CSV(lst));
 }
}
LSL には最適化コンパイラがありません。そのため、より速いコードを実現するには二つのスタイルをバランスよく使う必要があるでしょう。行をまとめてゆく最適化は、コードが動作しバグが無くなってから初めて行なうべきです。不適切な最適化は良くない結果をもたらします。最適化したコードのテストを常に、徹底的に行ないましょう。
list lst;
integer numDigits = 10;
default {
 touch_start(integer n) {
 integer i = 0;
 string startPart = llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1));
 if (!~llListFindList(lst, (list)startPart))
 lst += startPart;
 llOwnerSay(llList2CSV(lst));
 }
}
==スクリプト構成==
LSLスクリプトは、関数、ステートメント、イベントハンドラ、ステートの要素によって構成されています。LSLコンパイラはスクリプトに正確な構造化を強制します。
#定義された変数を用いる(LSL_Variablesを参照)
#定義された関数を用いる(ユーザ定義関数を参照)
#default State (stateを参照)
#定義されたステートを用いる
==エディタ==
多くのサードパーティ製エディタとLSL構文ファイルがあります。その他の情報はLSL Alternate Editorsを参照してください。
LSL Style Guide/zh-Hans

用LSL进行有效的编程,开发者需要在格式化和规范他们的脚本方面依照标准进行实践。
这个设计指南由以下这些准则组成。尽管它们不像编译器的规则那样严格，但对编写易于维护的代码仍然非常关键。编程格式最重要的一个方面是你在编写代码过程中使用某种格式的时候，要始终如一。
==通用准则==
很多自己开始编程的人写出来的程序都，说好听的话，十分难看。它们一般都被写成这样：
<lsl>
 default {state_entry(){llSay(0,"Hello World.");}}
</lsl>
然而，写一个上万字的程序的时候，能被人理解（或者至少能“看懂”）是很重要的。要做到这一点，程序员可以使用的两个主要方法是使用花括号和缩进。
方式一：
<lsl>
 default {
 state_entry() {
 llSay(0, "Hello World.");
 }
 }
</lsl>
方式二：
<lsl>
 default
 {
 state_entry()
 {
 llSay(0, "Hello World.");
 }
 }
</lsl>
方式一节省了空间，但方式二对初学者来说则更容易阅读。一但某个程序员在实践中使用了特定的格式，阅读那种格式的代码就会变得很容易。前后一致的缩进规则使得两种方式都更容易阅读。在方式一中缩进是标明层次范围的关键标示。
==命名规范==
在Second Life中，有许多命名规范，下面列出的是最常用的。
全局变量（指在整个程序中都要用到的变量）应该以小写字母g开头。例如：
<lsl>
 integer gSelected = 0;
 string gMyName = "Please set one";
</lsl>
可变常量(Variable Constants)应全部大写。例如：
<lsl>
 integer CHAT_CHAN = -517265;
 key OWNER_KEY = llGetOwner();
</lsl>
在用户自定义的函数或事件中使用的变量应以下划线开头。例如：
<lsl>
 listen( integer _channel, string _name, key _id, string _message )
 {
 if ( _channel == 1 || _id == llGetOwner() )
 	llOwnerSay("Hello Avatar");
 }
</lsl>
==让代码条理清晰==
刚开始编程的时候，很多人会在一行代码里调用许多的函数。这使代码变得难以阅读，几乎无法调试除错。下面的例子就是这样的：
<lsl>
list lst;
integer numDigits = 10;
default {
 touch_start(integer n) {
 integer i = 0;
 integer index = llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]);
 if (!~llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]))
 lst += llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1));
 llOwnerSay(llList2CSV(lst));
 }
}
</lsl>
再看下面这段代码，功能完全相同，却更简单易懂。比较起来，几乎没人能看懂上面的代码要实现什么目的，而下面的则很容易看懂。
<lsl>
list lst;
integer numDigits = 10;
default {
 touch_start(integer n) {
 integer i = 0;
 string name = llKey2Name(llDetectedKey(i));
 list nameAsList = llParseString2List(name, [" "], []);
 string firstName = llList2String(nameAsList, 0);
 string startPart = llToLower(llGetSubString(firstName, 0, numDigits - 1));
 integer index = llListFindList(lst, (list)startPart);
 if (!~index)
 lst += startPart;
 llOwnerSay(llList2CSV(lst));
 }
}
</lsl>
LSL 缺少一个能够优化代码的编译器。因此，为了得到执行速度更快的代码，有必要在以上两种编程样式中找到平衡。在以多行合并方式对代码进行优化之前，必须确保代码没有漏洞并且执行正常。不恰当的优化会导致错误的结果，要始终对优化过的代码进行彻底测试。
list lst;
integer numDigits = 10;
default {
 touch_start(integer n) {
 integer i = 0;
 string startPart = llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1));
 if (!~llListFindList(lst, (list)startPart))
 lst += startPart;
 llOwnerSay(llList2CSV(lst));
 }
}
==脚本结构==
LSL脚本由expressions, functions, statements, event handlers以及states构成。LSL编译器为脚本规定了一个明确的结构：
#User Defined Variables (参考 LSL_Variables)
#User Defined Functions (参考 User-defined_functions)
#default State (参考 State)
#User Defined States
==编辑器==
编辑LSL代码文件可以使用许多第三方开发的编辑器。
浏览 LSL Alternate Editors 可以获取详细信息。
Category:LSL 教程 (简体中文)
LSL Switch Statement

This article is a feature request
The ability to use something like the following:
 Switch (variable) 
 case condition 1:
 Do something;
 break;
 case condition 2:
 Do something;
 default:
 Do something;
Note: Isn't LSL all server-side? I don't think this can be implemented in the client. - Ihavegot Wood
:LSL is run on the server yes, but the compiler is in the client. LSO wasn't designed with switch statements in mind so some changes to the VM would be required, just wait for Mono. Strife Onizuka
This is not entirely accurate ... LSO has branch instructions (aka GOTO) which is all that is needed to implement switch constructs and the break and continue statements. Basically, it's just an issue of adding these statements to the compiler and ensuring the code generator emits the proper LSO instructions. Besides updating the grammar itself, I'd personally like to see the use of ANTLR (see ) over the current Flex/Yacc/Bison implementation. Provided that LL isn't already in the process of implementing this, I would not be adverse to doing so myself. --Num Skall 12:07, 18 April 2007 (PDT)
:The issue is that LSL is a stack based language, the act of doing a conditional jump pops the condition off the stack, unless something special was done for switch statements there would be no performance improvement over complex conditional structures. If you are willing to write the code to implement this, the LSL compiler is open source. Of course when the LSL is ported to Mono we won't have to use LSL to write scripts for SL. I'm still trying to decide if I'm going to use Managed C++ or C#. Either way I get switch statements without LL having to do anything. -- Strife Onizuka 18:51, 18 April 2007 (PDT)
:So? The issue isn't performance improvement but, rather, simplicity and readability of the LSL code. As for LSO being stack based, that's also a non-issue. My current projects are exactly like that too. Besides, having break and continue statements are the real benefit here. Think of how that would improve looping constructs. Properly done, the resulting object code efficiency will be the same. I'll get the source installed and see just how much is going to be involved. The first step will be converting to use of ANTLR to get the benefits of a full LRL rescursive-decent parser (makes code generation from the parse tree oh so much easier). It also generates the Lexical Analyzer from the same grammar file. Win-win. -- Num Skall 12:18, 20 April 2007 (PDT)
Category:Feature Requests
LSL Test Harness/ja

LSLテスト装置は、i3D社によるリンデンラボの開発したLSLスクリプトをテストするためのプラットフォームです。SecondLifeデベロッパは頻繁な更新を確実に行い確認するために使うことができます。このテスト装置は（クリエイティブコモンライセンスAttribution-ShareAlike 2.5の範囲内において）自由にダウンロードして使用可能です。
LSLテスト装置は三つ以上のインワールドオブジェクトから構成されています。きちんと適切なオブジェクトに適切なスクリプトとノートカードを置くことで、いくつかの標準の木目箱プリムからでも作ることが出来ます。
= コントローラ =
テスト装置に命令するためのコントローラのインターフェイスを準備します。チャットチャンネルにて命令を聞くことで起動するでしょう。タッチベースのコントローラを作ることも可能です。
* オブジェクトをrezもしくは作成して、Controllerと名づけます。
* Controller_Controllerを入れます。(ここからコピーペーストできます)
= コーディネータ =
コーディネータはコントローラと実際のテストユニット自身の間の接続をおこないます。
* オブジェクトをrezもしくは作成して、Coordinatorと名づけます。
* 以下のスクリプトを入れます。 (リンク先からコピーペーストで利用可能です。)
** Coordinator.Coordinator
** Coordinator_TestUnits
** Coordinator_TestUnitsReports
* 直ちにノートカード Coordinator_nc を入れて開きます。
** 装置からEメールで結果を送りたいなら、Eメール欄にEメールアドレスを入れます。
** 装置からレポートをhttpで送信したいなら、Http欄にURLを入れてください。
= テストユニット =
テストユニットがLSLテストを実際におこないます。そのため、テストを行なうための汎用スクリプトに加えて、有効なテストするコードで構成されています。必要に応じていくつものテストユニットを作ることになるでしょう。テストスクリプトの作成における足掛かりとして、コードレポジトリ（このページにあります）を含んだいくつかの例がテンプレートのように使えるでしょう。
* オブジェクトをrezもしくは作成して、何か名称（たとえば、Test Unit - Rotations）をつけます。
* スクリプト TestUnit_TestHarnessを入れます。
* ノートカード TestUnit_ncを入れます。
** ノートカードを開いて、ユニット名欄とグループ名欄を編集します。
*** ユニット名とは、あなたがつけたい特定のテスト名のことです。
*** (Mathとグループ名を定義するとして、)もし全てをMathとしてテストユニットでテストするようにしたい場合は、グループ名にテストグループを指定します。
* [GroupName]_[UnitName]と名づけられたテストスクリプトをいれます。
** テンプレートとして TestUnit_TestScript.lslが使えます。
** テストlslに入れている指定した部分の結果を報告します
* あるいは、 Test Harness Sample Testsに幾つかサンプルスクリプトがあります。
= コマンド群 =
一組のrezされたコントローラ、コーディネータと全テストユニットそれぞれに、チャット可能な距離を確保して、コントロールチャンネル(初期値1234)にて以下のコマンドを出力することができます。
* ActivateRegistration　はコーディネータのチャット範囲にある全テストユニットへの処理を実行するでしょう。
* ActivateTest　は全ての選択されたテストユニットを実行するでしょう。
* ActivateReport　は指定された形式(chat, email, http)でのレポートを出力するでしょう。
* Reset　は全てのテストユニットをリセットするでしょう。
* SetTestSelected　は指定のテストユニットを実行するでしょう。
** SetTestSelected::All 範囲内のテストユニットをさします。
** SetTestSelected::[GroupName] 全ユニットを含むグループをさします。
** SetTestSelected::[UnitName] 指定のユニットをさします。
* SetReportMethod　は三つのレポート方法から選ぶことができます。
** SetReportMethod::CHAT::channel::0　オープンチャット
** SetReportMethod::EMAIL::address::あなたのメールアドレス　
** SetReportMethod::HTTP::url::あなたのWebアドレス
* SetReportType　NORMAL, QUITE, VERBOSE, STATSからなるレポートの明確度
** SetReportType::NORMAL
* SetControlChannel 　内部連絡チャンネルの変更に使用されます。 
* SetBroadcastChannel　レポート出力用のチャットチャンネルです。(通常は0)
= テスト装置用レポジトリ =
LSLテスト装置用レポジトリです。装置の更新にあわせてwikiを更新しましょう。
Test Harness Control Buttons
Test Harness Controller
Test Harness Test Units
Test Harness PHP
LSL Test Harness/ko

LSL테스트 장치는,i3D회사에 의한 린덴 레버러토리 의 개발했다LSL스크립트를 테스트하기 위한 플랫폼입니다.SecondLife디벨로퍼는 빈번한 갱신을 확실히 실시해 확인하기 위해서 사용할 수 있습니다.이 테스트 장치는(크리에이티브 코먼 라이센스Attribution-ShareAlike 2.5의 범위내에 있어) 자유롭게 다운로드해 사용 가능합니다.
LSL테스트 장치는 세 개 이상의 인 월드 오브젝트로부터 구성되어 있습니다.제대로 적절한 오브젝트에 적절한 스크립트와 노트 카드를 두는 것으로, 몇개의 표준의 나뭇결상자 프림으로부터에서도 만들 수 있습니다.
= 콘트롤러 =
테스트 장치에 명령하기 위한 콘트롤러의 인터페이스를 준비합니다.채팅 채널에서 명령을 (듣)묻는 것으로 기동하겠지요.터치 베이스의 콘트롤러를 만드는 것도 가능합니다.
* 오브젝트를rez혹은 작성하고,Controller(이)라고 명명합니다.
* Controller_Controller(을)를 넣습니다.(여기(으)로부터 카피 페이스트 할 수 있습니다)
= 코디네이터 =
코디네이터는 콘트롤러와 실제의 테스트 유닛 자신의 사이의 접속을 행합니다.
* 오브젝트를rez혹은 작성하고,Coordinator(이)라고 명명합니다.
* 이하의 스크립트를 넣습니다. (링크처로부터 카피 페이스트로 이용 가능합니다.)
** Coordinator.Coordinator
** Coordinator_TestUnits
** Coordinator_TestUnitsReports
* 즉시 노트 카드 Coordinator_nc (을)를 넣어 엽니다.
** 장치로부터E메일로 결과를 보내고 싶으면,E메일란에E메일 주소를 넣습니다.
** 장치로부터 리포트를http그리고 송신하고 싶으면,Http란에URL(을)를 넣어 주세요.
= 테스트 유닛 =
테스트 유닛이LSL테스트를 실제로 행합니다.그 때문에, 테스트를 행하기 위한 범용 스크립트에 가세하고, 유효한 테스트하는 코드로 구성되어 있습니다.필요에 따라서 얼마든지의 테스트 유닛을 만들게 되겠지요.테스트 스크립트의 작성에 있어서의 발판으로서 코드레포지트리(이 페이지에 있습니다)를 포함한 몇개의 예를 템플릿과 같이 사용할 수 있겠지요.
* 오브젝트를rez혹은 작성하고, 무엇인가 명칭(예를 들어,Test Unit - Rotations)(을)를 붙입니다.
* 스크립트 TestUnit_TestHarness(을)를 넣습니다.
* 노트 카드 TestUnit_nc(을)를 넣습니다.
** 노트 카드를 열고, 유닛명란과 그룹명란을 편집합니다.
*** 유닛명과는, 당신이 붙이고 싶은 특정의 테스트명입니다.
*** (Math(와)과 그룹명을 정의한다고 하고,)만약 모두를Math(으)로서 테스트 유닛으로 테스트하도록(듯이) 하고 싶은 경우는, 그룹명에 테스트 그룹을 지정합니다.
* [GroupName]_[UnitName](와)과 이름 붙여진 테스트 스크립트를 넣습니다.
** 템플릿으로서 TestUnit_TestScript.lsl하지만 사용할 수 있습니다.
** 테스트lsl에 넣고 있는 지정한 부분의 결과를 보고합니다
* 혹은, Test Harness Sample Tests에 몇이나 샘플 스크립트가 있습니다.
= 커멘드군 =
1조의rez된 콘트롤러, 코디네이터와 전테스트 유닛 각각, 채팅 가능한 거리를 확보하고, 컨트롤 채널(초기치1234)에서 이하의 커멘드를 출력할 수 있습니다.
* ActivateRegistration　(은)는 코디네이터의 채팅 범위에 있는 전테스트 유닛에의 처리를 실행하겠지요.
* ActivateTest　(은)는 모든 선택된 테스트 유닛을 실행하겠지요.
* ActivateReport　(은)는 지정된 형식(chat, email, http)(으)로의 리포트를 출력하겠지요.
* Reset　(은)는 모든 테스트 유닛을 리셋트 하겠지요.
* SetTestSelected　(은)는 지정의 테스트 유닛을 실행하겠지요.
** SetTestSelected::All 범위내의 테스트 유닛을 찌릅니다.
** SetTestSelected::[GroupName] 전유닛을 포함한 그룹을 찌릅니다.
** SetTestSelected::[UnitName] 지정의 유닛을 찌릅니다.
* SetReportMethod　(은)는 세 개의 리포트 방법으로부터 선택할 수 있습니다.
** SetReportMethod::CHAT::channel::0　오픈 채팅
** SetReportMethod::EMAIL::address::당신의 메일 주소　
** SetReportMethod::HTTP::url::당신의Web주소
* SetReportType　NORMAL, QUITE, VERBOSE, STATS(으)로부터 되는 리포트의 명확도
** SetReportType::NORMAL
* SetControlChannel 　내부 연락 채널의 변경에 사용됩니다. 
* SetBroadcastChannel　리포트 출력용의 채팅 채널입니다.(통상은0)
= 테스트 장치용 레포지트리 =
LSL테스트 장치용 레포지트리입니다.장치의 갱신에 맞추어wiki(을)를 갱신합시다.
Test Harness Control Buttons
Test Harness Controller
Test Harness Test Units
Test Harness PHP
LSL Topic Style

This is the topic style guide (someone make a template maybe?).
----
=Topic Name=
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut ornare ullamcorper libero. Duis non erat at ante feugiat luctus. Fusce vel dui eget magna consectetuer volutpat. Suspendisse placerat. Duis a neque. Nunc ornare sagittis sem. Proin sed urna. In est. Curabitur quis turpis vitae risus molestie accumsan. Duis metus ligula, viverra sed, gravida quis, facilisis eu, est. Nullam imperdiet enim non massa. Phasellus nisi velit, porttitor ut, aliquam quis, aliquet sit amet, ligula. Duis sit amet sem. Integer vitae nisl. Nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean a leo. Morbi vehicula, augue vitae dapibus rutrum, massa sem varius sem, ut interdum justo elit quis quam. Curabitur condimentum lectus et nibh. Vivamus consectetuer nonummy leo.
==Summary==
Sed ut turpis. Integer aliquet pellentesque pede. Donec mi. Curabitur sed neque. Donec vel nibh ac pede sollicitudin molestie. Sed lectus turpis, volutpat a, rhoncus in, malesuada sed, arcu. Duis ornare convallis nisi. Quisque at sapien eu nibh posuere mollis. Aenean libero nulla, vulputate id, pellentesque in, vehicula vel, arcu. Cras nonummy neque sed urna. Aenean laoreet lobortis tellus. Nullam ultrices accumsan odio. Proin nisi risus, elementum a, elementum non, eleifend in, dui.
==Examples==
rhoncus in, malesuada sed, arcu:
(Morbi vehicula. Integer varius nisl ac ante porta ornare. Praesent lorem purus, laoreet nec, euismod vitae, viverra quis, elit. Nulla scelerisque, orci lacinia imperdiet tincidunt, dolor ipsum varius ipsum, eu dictum dui dui id tellus. Maecenas vulputate purus vitae ipsum. In malesuada risus eget lectus. Aliquam vitae diam. Nulla augue. Duis tempor auctor ante. Mauris aliquam tempus velit. Nulla pharetra odio eu magna. Quisque venenatis. Ut arcu eros, ullamcorper in, hendrerit id, vehicula vitae, nibh. Duis lectus. Duis laoreet egestas ligula. Aliquam erat volutpat. Etiam eleifend lectus id nibh.)
LSL Touch Position

Here we propose an extension of the detected LSL functions to determine surface information for touch events. Each of the following functions is valid only inside touch_start, touch, and touch_end events. In the case of touch events, which are triggered repeatedly while the mouse button is held down, the surface information is valid (and is updatedly correctly) as long as the mouse remains over the surface of the object (allowing psuedo GUI builds with sliders, levers, dials, etc.)
vector llDetectedTouchPos(integer number)
Returns the region coordinates of the position touched by detected object number.
integer llDetectedTouchFace(integer number)
Returns the face of the position touched by detected object number.
vector llDetectedTouchUV(integer number)
Returns the texture coordinates of the position touched by detected object number.
vector llDetectedTouchST(integer number)
Returns the surface coordinates of the position touched by detected object number.
vector llDetectedTouchNormal(integer number)
Returns the surface normal of the position touched by detected object number. (A normal is a vector perpendicular to the surface.)
vector llDetectedTouchBinormal(integer number)
Returns the surface binormal of the position touched by detected object number. (A binormal is a vector tangent to the surface pointing along the U direction of tangent space.)
=== Call for Feedback ===
=== Links ===
llDetectedLinkFace
=== Internal LL Jira ===
https://jira.lindenlab.com/browse/DEV-9985
 LSL Touch Position