Skriptで開発する上で、より合理的な開発をするために必要な要件です。
【結論】可能な限りloopが必要な処理は避けて、どうしても残す場合はWhere句での置換を検討する。
例えば、次のようなリスト変数{_random::*}を用意します。({_n}は任意の要素数)
loop {_n} times:
add random integer between 0 and 99999999 to {_random::*}
これに対して、値が10000000以上のもののみを残したリスト変数を作りたいとします。
loop {_random::*}
if loop-value >= 10000000:
add loop-value to {_result::*}
これで{_result::*}は10000000以上のもののみのリスト変数となりますが、これはセンスのない実装です。
今すぐWindows Defenderにブロックしてもらい、次のような構文を使いましょう。
set {_result::*} to {_random::*} where [input >= 10000000]
2つの処理時間について、比較を行いました。
特に、処理する要素数が多くなればなるほど、LoopよりもWhereを使ったほうが処理時間が短くなることがわかります。
| {_n} | 1 | 10 | 100 | 1,000 | 10,000 | 100,000 | 1,000,000 |
|---|---|---|---|---|---|---|---|
| Loopの処理時間(青) | 0s | 0s | 0.001s | 0.004s | 0.033s | 0.478s | 7.84s |
| Whereの処理時間(赤) | 0s | 0s | 0.001s | 0.002s | 0.022s | 0.256s | 4.126s |
【結論】エンティティやプレイヤーを保存したり、リスト変数のキーに設定するときは「UUID」を使う。
例えば、次のようなコードで特定のエンティティを操作できるようにします。
command /entity-save:
trigger:
set {savedEntity} to targeted entity
command /tphere:
trigger:
teleport {savedEntity} to player
よくこういったコードを書く方がいらっしゃいますが、一度SkriptHubに暗記パンを擦りまくって朝食にしたほうが良いと思われます。
このコードの問題点は「サーバーを再起動した際に変数が消える」という点です。
Skriptはエンティティ型のデータを変数に保存して再起動後に持ち越すことができません。
command /entity-save:
trigger:
set {savedEntityUUID} to (targeted entity)'s uuid
command /tphere:
trigger:
teleport getEntityByUUID({savedEntityUUID}) to player
function getEntityByUUID(uuid: string) :: entity:
return first element out of all entities where [input's uuid is {_uuid}]
UUIDで保存しておくことで、再起動後もエンティティの取得が可能になります。
また、エンティティ型で保存しておくよりも軽量(容量的な意味)になります。
例えば、次のようなコードでプレイヤーごとのデータを保存します。
on join:
set {lastLoginTime::%player%} to now
on quit:
set {lastQuitPlayer} to player
また、よくこういったコードを書く方がいらっしゃいますが、一度パソコンを閉じてキーボードをフォーク投げしたほうが良いと思われます。
このコードの問題点は「プレイヤー型を後から参照しようとしたときにオフラインプレイヤー型で処理される可能性がある」という点です。
ここで使用するプレイヤー型は、あくまでそのプレイヤーがオンラインの時だけ有効となり、オフライン時に参照しようとするとオフラインプレイヤー型で処理されます。
この時、プレイヤー型からオフラインプレイヤー型に変換する処理が走り、メインスレッドに大きな負荷がかかります。(マイクラ鯖の仕様でもある。)
on join:
set {lastLoginTime::%player's uuid%} to now
on quit:
set {lastQuitPlayer} to player's uuid
UUIDで保存しておくことで、単なる文字列として変数自体は処理することができます。
後ほど使用するときに、随時UUIDからプレイヤー型に変換すればよいことになります。