這個節點會在每次觸發時產生事件複本掛到發起者的事件列表下,因為它可以將一個事件掛上多個發起者,如果不複製事件節點,多個發起者將共用同一個事件實例導致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
...
}
沒有留言:
張貼留言