這個節點會在每次觸發時產生事件複本掛到發起者的事件列表下,因為它可以將一個事件掛上多個發起者,如果不複製事件節點,多個發起者將共用同一個事件實例導致per instance data出錯。然而如果不曉得這個特性,將可能導致不必用的複製動作。實際上任何可能對同一個Actor重覆觸發的AttachToEvent都會導致重覆複製的事件實例,它們在條件成立時也會造成多重觸發,這通常不會是想要的結果。
接下來示範一下要怎麼修改AttachToEvent來避免重覆複製。我並不想去動引擎的原始碼,所以另外自訂一個事件叫BindEvent:
class SeqAct_BindEvent extends SequenceAction native(Sequence); /** prefer to attach events to Controllers instead of Pawns (for events you want to persist beyond the target dying and respawning) */ var() bool bPreferController; cpptext { void Activated(); }; defaultproperties { ObjName="Bind Event" ObjCategory="Event" VariableLinks.Empty VariableLinks(0)=(ExpectedType=class'SeqVar_Object',LinkDesc="Attachee") EventLinks(0)=(LinkDesc="Event") }程式碼大致跟AttachToEvent一樣,只是在綁定事件前先檢查是否已經綁定到此目標了:
void USeqAct_BindEvent::Activated() { ... if (targets.Num() > 0 && Events.Num() > 0) { USequence *Seq = ParentSequence; // then add the Events to the targets for (INT Idx = 0; Idx < targets.Num(); Idx++) { for (INT EventIdx = 0; EventIdx < Events.Num(); EventIdx++) { UBOOL bNeedsDuplicate = TRUE; AActor* Target = targets(Idx); TArray<USequenceEvent*>& DuplicateEvts = Events(EventIdx)->DuplicateEvts; INT DuplCount = DuplicateEvts.Num(); for(INT DuplIdx = 0; DuplIdx < DuplCount; DuplIdx++ ) { if( DuplicateEvts(DuplIdx)->Originator == Target ) { bNeedsDuplicate = FALSE; break; } } if( bNeedsDuplicate ) { // create a duplicate of the Event to avoid collision issues ... }然而還可以再進一步減少一次複製成本,第一次綁定時其實可以直接使用該事件實例,無需複製,只要確定不會有兩個Actor同時使用同一個事件實例即可:
void USeqAct_BindEvent::Activated() { ... if (targets.Num() > 0 && Events.Num() > 0) { USequence *Seq = ParentSequence; // then add the Events to the targets for (INT Idx = 0; Idx < targets.Num(); Idx++) { for (INT EventIdx = 0; EventIdx < Events.Num(); EventIdx++) { // If this event is not attached, use it instead of a duplicate. if( Events(EventIdx)->Originator == NULL ) { USequenceEvent *evt = Events(EventIdx); evt->Originator = targets(Idx); targets(Idx)->GeneratedEvents.AddItem(evt); evt->Originator->eventReceivedNewEvent(evt); } else { UBOOL bNeedsDuplicate = TRUE; AActor* Target = targets(Idx); TArray<USequenceEvent*>& DuplicateEvts = Events(EventIdx)->DuplicateEvts; INT DuplCount = DuplicateEvts.Num(); for(INT DuplIdx = 0; DuplIdx < DuplCount; DuplIdx++ ) { if( DuplicateEvts(DuplIdx)->Originator == Target ) { bNeedsDuplicate = FALSE; break; } } if( bNeedsDuplicate ) { // create a duplicate of the Event to avoid collision issues ... }
沒有留言:
張貼留言