チュートリアル

スクリプトログの取り方

パピルスのログの取り方

Papyrusのスクリプトログの取り方を説明します。基本的にmod制作者向けの情報です。普段からログを取る必要はありません。ログを取ると負荷がかかります。

Papyrusはエラーや警告、デバッグのメッセージをログで受け取ることができます。

注意事項

  • スクリプトはクラッシュの原因になりにくいです。同期が取れなくて大量のエラーが出てるときだけです。それもスクリプト以外の複合要因であることも多く、CTDの解明にログはあまり役に立ちません。
  • クラッシュの原因はログには一切記載されません。したがって最後に出てるエラーがクラッシュの原因ではありません。ログはあくまでもデバッグ用途に使用します。
  • エラーの出てるmodが悪いとも限りません。

スクリプトログの取り方

以下のファイルを開きます。(MO2の場合はMO2のiniエディターで開く)

ドキュメント\My Games\Skyrim\Skyrim.ini

以下の項目の数値を1に書き換えて保存します。これらの項目がなければ追記します。

[Papyrus]
bEnableLogging=1
bEnableTrace=1
bLoadDebugInformation=1

スカイリムを起動すると以下のログファイルが生成されます。メモ帳以外のテキストエディタで開いてください。後述のLogExpertの使用をおすすめします。

ドキュメント\My Games\Skyrim\Logs\Script\Papyrus.0.log

LogExpert

Log Expertは常にログ内容更新してくれるのでリアルタイムで監視できます。ログのリアルタイム監視にはこれを使いましょう。

準備

  1. LogExpert-1.6.13.zip」をダウンロードして展開します。
  2. 「Log Export」を起動します。
  3. File->Openから以下のログファイルを開きます。
    ドキュメント\My Games\Skyrim\Logs\Script\Papyrus.0.log

「Follow tail」にチェックまたはスクロールを一番下にすると自動で最後尾行を追尾します。

LogExpert常に最下部を表示

Optionから「Always On Top」を有効にすると、LogExpertを常に手前に表示したままにできます。

LogExpoertを常に手前に表示する

デバッグ用の関数をスクリプトにつける

デバッグに使う場合は、スクリプトにデバッグの関数を書き込む必要があります。

スクリプトのデバッグしたい部分にdebug.trace(“”)を書き、コンパイルします。
“”外に+を加えることで関数で取得した値を付け加えることができます。

debug.trace("Player Health:" + Game.GetPlayer().GetAV("Health"))

エラーの種類

エラー文は文頭の文字で判別してください。

error: エラーです。エラー内容がここに書かれます。

warning: 警告です。セーブのテーブルとプラグインでデータが一致しないときなどに出ます。大抵は処理が無視されるので問題ありません。

stack: 単発で出る分には特に危険ではありません。これが繰り返し大量に出る場合は危険です。

文頭に何もなし エラーではなくデバッグ用のテキストです。特にDLCはデバック用テキストが多いのでエラーと勘違いしないでください。

ログの最初にある大量のエラー

主にmodを外した時やmodの更新時にセーブに残るデータ(グローバル変数、静的変数、プロパティの類)です。エラーは無視されるので気にしないでください。セーブのクリーニングである程度は消せます。

VM

VMはVirtual Machineの略で仮想マシーンです。以下はゲーム保存時やゲーム終了時に必ず出ます。エラーではありませんので大丈夫です。

VM is freezing...
VM is frozen

エラーの読み方

典型的な問題のあるスタックエラーの例を見ます。

[dragonactorscript < (00032AC2)>]OnLocationChange() calling WI.RegisterDragonAttack(None)
Error: Cannot call HasKeyword() on a None object, aborting function call
stack:
    [WI (00035D64)].wifunctionsscript.RegisterDragonAttack() - "Wifunctionsscript.psc" Line 480
    [ (00032AC2)].dragonactorscript.OnLocationChange() - "dragonActorSCRIPT.psc" Line 113
[06/17/2016 - 12:09:22AM] warning: Assigning None to a non-object variable named "::temp33"
stack:
    [WI (00035D64)].wifunctionsscript.RegisterDragonAttack() - "Wifunctionsscript.psc" Line 480
    [ (00032AC2)].dragonactorscript.OnLocationChange() - "dragonActorSCRIPT.psc" Line 113
[dragonactorscript < (00032AC2)>]OnLocationChange() calling WI.RegisterDragonAttack([Location< (0001927F)>])
[dragonactorscript < (00032AC2)>]OnLocationChange() calling WI.RegisterDragonAttack(None)
Error: Cannot call HasKeyword() on a None object, aborting function call
stack:
    [WI (00035D64)].wifunctionsscript.RegisterDragonAttack() - "Wifunctionsscript.psc" Line 480
    [ (00032AC2)].dragonactorscript.OnLocationChange() - "dragonActorSCRIPT.psc" Line 113
warning: Assigning None to a non-object variable named "::temp33"
stack:
    [WI (00035D64)].wifunctionsscript.RegisterDragonAttack() - "Wifunctionsscript.psc" Line 480
    [ (00032AC2)].dragonactorscript.OnLocationChange() - "dragonActorSCRIPT.psc" Line 113

Error:の部分はHasKeyword()の関数を使ったのにオブジェクトがNone(ない)ので「関数は無視しスタックしました」という意味です。これに近い種類の警告が大量に続いてますのでCTDになりやすい状況です。

“Wifunctionsscript.psc” Line 480Wifunctionsscript.pscというスクリプトの480行目付近にRegisterDragonAttack()があるので、そこで対象を取得できないようです。

“dragonActorSCRIPT.psc” Line 113
dragonActorSCRIPT.pscというスクリプトの113行目付近のOnLocationChange() で対象が取れないようです。

Wifunctionsscript.pscRegisterDragonAttack()を見てみます。

if LocationOfDragonAttack.HasKeyword(WIDragonAttacked)
ここの条件判定で対象を取れないのがスタックエラーの原因になっているようです。

もし、対象がない(None)場合だったらスキップするように条件式を変えます。

if LocationOfDragonAttack != None && LocationOfDragonAttack.HasKeyword(WIDragonAttacked)

に書き換えて保存します。

CKの上部メニューにある「GamePlay」→「PapyrusScriptManager」を起動します。WIfunctionsscriptを探し、右クリックして「Compile」を選びます。

以上で直せました。

別の対処方法

dragonACTORScript.pscなので、ドラゴンに関係するスクリプトだと推測できます。None Objectはオブジェクト(この場合はドラゴン)が取得できない状態なので、近場にいるドラゴンかドラゴンの死骸を探します。

コンソールを開き、ドラゴンをクリックします。以下の2つのコマンドをそれぞれ入力します。

disable
enable

これでリセットされて、直る場合があります。他にも~Quest.pscみたいなクエストに関連しそうな名前なら以下のコンソールコマンドでリセットできます。xxxはクエストのFormID名です。

stopquest xxx
startquest xxx

注意

何らかの要因でオブジェクトが消失してしまって、エラーが出る場合はこれらの対処法で問題ありません。しかし、対象のオブジェクトがあるにも関わらずエラーになってる場合は画面と同期が取れてない状況下であって、必ずしもスクリプトとは限りません。FPS低下などの何かの負荷がボトルネックになってる可能性もあります。

その他のエラー

Papyrusのエラー一覧はこちら

https://www.creationkit.com/index.php?title=Papyrus_Runtime_Errors