Previous thread,如果你们都好奇的话。
背景信息:Four Dragon是Fallout 4的C#包装器,允许使用C#脚本修改游戏,并允许在相同的C#中使用Papyrus(Skyrim和Fallout 4的脚本语言)函数脚本。潜力!可能性!
我编写了一个运行Papyrus函数GetPlayerGrabbedRef()和SetMotionType的脚本,用于使游戏中的对象冻结到位。感谢Metro Smurf,脚本更容易阅读。
然而,有一个相当......明显的问题。脚本注册F6和F7键,但是当按下F6并调用GetPlayerGrabbedRef()函数时,当玩家没有抓取引用(可移动的游戏内对象)时,输出以下异常,导致游戏迅速退出:
FATAL ERROR Unhandled exception while executing FyTyTest.FreezeObject Void OnStaticTick()
现在,我已经完成了如何处理未处理异常的一些阅读,允许程序(在这种情况下为Fallout 4游戏)继续操作,而不通过try
和catch
函数关闭,但我没有任何成功;异常仍然发生,导致游戏在单击“确定”时退出。
唉,输出的各种.log文件没有问题;好像一切都运转正常。
以下是该剧本的最新版本:
using System;
using System.Collections.Generic;
using Fallout;
public class FreezeObject : ScriptObject
{
public FreezeObject() { }
bool bGotObject = false;
ObjectReference ItemReference;
ObjectReference EmptyReference;
int itemValue;
public override void OnStaticTick()
{
base.OnStaticTick();
bool isF6 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F6);
bool isF7 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F7);
if(isF6)
{
try
{
ItemReference = Game.GetPlayerGrabbedRef();
itemValue = ItemReference.GetGoldValue();
if(ItemReference = EmptyReference)
{
// nothing else to do if we have a null reference
return;
}
}
catch
{
ItemReference = EmptyReference;
itemValue = -1;
return;
}
if (itemValue > -1)
{
bGotObject = true;
}
// nothing else to do; the next block is for F7
return;
}
if(isF7 && bGotObject && ItemReference != EmptyReference && itemValue > -1)
{
ItemReference.SetMotionType(2, true);
bGotObject = false;
}
}
}
所以。如何阻止未处理的异常导致游戏崩溃?或者这是不可能的?
编辑:按照Corey的建议,我将try...catch
函数放在所有函数代码周围......没有骰子;异常仍然出现,一旦异常消息关闭就关闭游戏。
这是新脚本:
using System;
using System.Collections.Generic;
using Fallout;
public class FreezeObject : ScriptObject
{
public FreezeObject() { }
bool bGotObject = false;
ObjectReference ItemReference;
ObjectReference EmptyReference;
int itemValue;
public override void OnStaticTick()
{try
{
base.OnStaticTick();
bool isF6 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F6);
bool isF7 = Fallout.Keyboard.IsKeyJustUp(System.Windows.Forms.Keys.F7);
if(isF6)
{
ItemReference = Game.GetPlayerGrabbedRef();
itemValue = ItemReference.GetGoldValue();
if(ItemReference == EmptyReference)
{
// nothing else to do if we have a null reference
return;
}
if (itemValue > -1)
{
bGotObject = true;
}
// nothing else to do; the next block is for F7
return;
}
if(isF7 && bGotObject && ItemReference != EmptyReference && itemValue > -1)
{
ItemReference.SetMotionType(2, true);
bGotObject = false;
}
}
catch
{
}
}
}
答案 0 :(得分:0)
Four Dragon拥有自己的AppDomain,用于加载和执行用户脚本。我没有很多机会使用自定义主机,所以我不确定,但我相信主机可以控制异常处理行为。假设我是对的,我猜这是造成你奇怪的异常处理问题的原因。
您最好的办法是解决异常的实际原因。在您的代码中,在您尝试访问对象上的方法之后,您将检查空引用。你可能想试试这个:
if(isF6)
{
ItemReference = Game.GetPlayerGrabbedRef();
if(ItemReference != null && ItemReference.HandleExists())
{
itemValue = ItemReference.GetFormID();
if (itemValue != 0)
{
bGotObject = true;
}
}
// nothing else to do; the next block is for F7
return;
}
我将GetGoldValue()
来电更改为GetFormID()
,因为您正在使用它来确定您是否拥有有效的ObjectReference
。
如果您仍有问题,我会尝试存储表单ID并使用 Game.GetForm(formid)
重新获取F7块中的对象引用。您依赖于假设对象引用在调用OnStaticTick
之间保持有效,这可能不一定是这种情况。 (仍在挖掘Four Dragon的实施,所以我仍然不确定)
编辑:忽略 - 对象引用显然在事件之间保持有效。