native(307) final iterator function TouchingActors( class<Actor> BaseClass, out Actor OutActor );迭代子宣告在一個原生UnrealScript類別裡,由C++實作,實際上是一個成員函式。要在UnrealScript中使用一個迭代子,需要透過foreach語法。下列程式碼示範如何使用一個迭代子:
function PrintTouchingActors() { local Actor TouchedActor; foreach TouchingActors(class'Actor', TouchedActor) { `log(TouchedActor.Name); } }
範例
以下程式碼示範如何自訂一個可以取得所有類別的迭代子:
class MyIterator extends Object native; native iterator static function AllClasses( class BaseClass, out class OutClass ); static function PrintAllClasses( class BaseClass ) { local class cls; foreach AllClasses( BaseClass, cls ) { `log( cls ); } }編譯過上列UnrealScript後會自動產生以下的C++類別定義:
class UMyIterator : public UObject { public: DECLARE_FUNCTION(execAllClasses); DECLARE_CLASS(UMyIterator,UObject,0,MyGame) NO_DEFAULT_CONSTRUCTOR(UMyIterator) };其中的execAllClasses()函式正是對應到先前在UnrealScript宣告的迭代子。DECLARE_FUNCTION 巨集宣告的函式參數都一樣,第一個參數是執行UnrealScript用的堆疊,可由此取得運算元,第二個參數是存放傳回值位址的void指標。以下是該 函式的實作碼:
void UMyIterator::execAllClasses( FFrame& Stack, RESULT_DECL ) { P_GET_OBJECT(UClass, BaseClass); P_GET_OBJECT_REF(UClass, OutClass); P_FINISH; TObjectIterator<UClass> It; PRE_ITERATOR OutClass = NULL; // Fetch a valid output. while( It ) { UClass* CurrentClass = *It; ++It; if( CurrentClass->IsChildOf(BaseClass) ) { OutClass = CurrentClass; break; } } // If there is no output, skip POST_ITERATOR and go to the end of the script block. if(! OutClass) { Stack.Code = &Stack.Node->Script(wEndOffset + 1); break; } POST_ITERATOR }其中的PRE_ITERATOR和POST_ITERATOR巨集其實是一個do while迴圈,必須在POST_ITERATOR前取得每次迭代的輸出物件並且指派到輸出參數(本例中是OutClass),POST_ITERATOR本身會執行一次迴圈內容然後前進到下一次迭代。所以當遇到終止條件時就要逕自跳離巨集所形成的迴圈,以避免執行POST_ITERATOR,並且利用如上面if區塊的程式碼跳離UnrealScript的foreach區塊。
沒有留言:
張貼留言