这有效......
if ( tileType == "water" or
( otherObj and otherObj:GetType() == "IceBlock" )) then
self:SetNoClip( true )
else
self:SetNoClip( false )
end
- 这些不......
self:SetNoClip( tileType == "water" or
( otherObj and otherObj:GetType() == "IceBlock" ))
//----------------------------------------------------------
local noClip = ( tileType == "water" or
( otherObj and otherObj:GetType == "IceBlock" ))
self:SetNoClip( noClip )
otherObj
测试只评估otherObj是否为nil
。给出的变量在前一行中检索。我运行应用程序时遇到的错误是:
unprotected error to call in Lua API(script path...: Did not pass boolean to SetNoClip).
SetNoClip是应用程序中的一个函数,它通过lua_toboolean
获取推送到lua堆栈的参数。
那么为什么第一次工作以及第二次和第三次返回错误?
编辑:
SetNoClip 有这个定义。
int GameObject::LuaSetNoClip( lua_State *L ) {
if ( !lua_isboolean( L, -1 )) {
LogLuaErr( "Did not pass boolean to SetNoClip for GameObject: " + m_type );
return luaL_error( L, "Did not pass boolean to SetNoClip" );
}
m_noClip = lua_toboolean( L, -1 );
return 0;
}
问题是lua_isboolean
没有进行任何隐式类型转换(但lua_toboolean
没有)并且只会对文字布尔值返回true。因此,如果它看到nil,它将返回没有传递布尔值。我刚刚删除了布尔文字的错误检查,因为人们(包括我)通常依赖于不是布尔文字的参数被正确地视为布尔值。
答案 0 :(得分:1)
and
运算符返回第一个参数,如果该值被认为是非真值,则返回第二个参数。
or
运算符返回其第一个参数(如果它被认为是真的),而第二个参数则返回。
因此,A or (B and C)
理论上可以返回以下任何一项:
A
如果A
的值为真,则B
如果B
的值为false,A
被视为false C
如果以上都不是请注意,A
,B
和C
不需要是实际的布尔值 - 只能将解释为的内容作为布尔值。由于nil
被视为假值,因此第二种情况可能是您正在发生的,而传递给SetNoClip
的参数是nil
而不是true
或{{ 1}}。
解决这个问题的一个选择是明确地与nil进行比较,而不仅仅是使用对象:
false
因为( otherObj ~= nil and otherObj:GetType() == "IceBlock" )
运算符保证返回布尔值。
答案 1 :(得分:1)
如您所见,任何对象都可以在Lua中使用布尔解释。因此,您对LuaSetNoClip 的实现不符合精神和范围。如果你希望只传递一个布尔对象,则练习Lua 。您应该直接使用lua_toboolean
。
我认为你可以合理做的唯一论据是luaL_checkany
:
int GameObject::LuaSetNoClip( lua_State *L ) {
luaL_checkany(L, 1);
m_noClip = lua_toboolean( L, 1 );
return 0;
}
答案 2 :(得分:0)
这取决于SetNoClip内部的内容(即,这不一定会导致问题)。但是,我很确定问题是and
和or
会返回两边的值,而不是评估true
或false
。换句话说,
foo and bar
如果foo
为foo
或nil
,将返回false
,否则会返回bar
。
在您的情况下,原始代码将true
或false
传递给SetNoClip,而在其他示例中,您要么传递"water"
,要么将布尔传递给SetNoClip。 SetNoClip可能会阻塞字符串。