日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

UE5: UpdateOverlap - 从源码深入探究UE的重叠触发

發(fā)布時(shí)間:2024/1/16 windows 51 coder
生活随笔 收集整理的這篇文章主要介紹了 UE5: UpdateOverlap - 从源码深入探究UE的重叠触发 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

出于工作需要和個(gè)人好奇,本文對(duì)UE重疊事件更新的主要函數(shù)UpdateOverlaps從源碼的角度進(jìn)行了詳細(xì)的分析,通過閱讀源碼,深入理解重疊事件是如何被觸發(fā)和更新的。

解決問題

閱讀本文,你將得到至少以下問題的答案:

  1. BeginComponentOverlap和EndComponentOverlap事件是如何被觸發(fā)的?

  2. UE是如何保存和管理組件之間的碰撞的?

  3. SetActorEnableCollision是如何起到作用的?

  4. UE如何處理不同Actor,或者同一個(gè)Actor里重復(fù)碰撞的情況?

以上只是提出了幾個(gè)很基礎(chǔ)的問題,隨著源碼的不斷解析,還會(huì)有更多新的問題會(huì)被提出。

說是深入探究,更像是筆者個(gè)人的學(xué)習(xí)筆記。其中一些筆者認(rèn)為本應(yīng)被了解的細(xì)節(jié)不會(huì)被提起,請(qǐng)讀者至少對(duì)UE的重疊機(jī)制有基礎(chǔ)的理解。


重疊更新的入口:USceneComponent::UpdateOverlaps

Queries world and updates overlap tracking state for this component

當(dāng)一個(gè)組件需要更新當(dāng)前重疊狀態(tài)時(shí),就會(huì)調(diào)用這個(gè)函數(shù)。

這個(gè)函數(shù)定義在USceneComponent,表明只有場(chǎng)景組件的子類才能調(diào)用該函數(shù)。并且它不是一個(gè)虛函數(shù),更新重疊相關(guān)的具體實(shí)現(xiàn)放在一個(gè)叫``UpdateOverlapsImpl的虛函數(shù)中。因此可以將UpdateOverlaps視作為重疊更新的總?cè)肟冢缓笳{(diào)用子類的UpdateOverlapsImpl`從而執(zhí)行具體的更新邏輯。

觀察該函數(shù)的聲明:

bool UpdateOverlaps(const TOverlapArrayView* PendingOverlaps = nullptr, bool bDoNotifies = true, const TOverlapArrayView* OverlapsAtEndLocation = nullptr);

其中,TOverlapArrayView就是經(jīng)過了typedef的TArrayView<const FOverlapInfo>.

FOverlapInfo是對(duì)FHitResult的一個(gè)簡(jiǎn)單封裝,FHitResult相信大家都很熟悉了,通過使用FHitResult,我們可以很輕松的獲得本次碰撞查詢中碰撞到的組件,以及碰撞的各種信息,例如碰撞坐標(biāo),法線等等。

接下來對(duì)參數(shù)列表中三個(gè)參數(shù)進(jìn)行講解,這幾個(gè)參數(shù)還是挺重要的,后面會(huì)反復(fù)使用到這三個(gè)參數(shù)。

NewPendingOverlaps

An ordered list of components that the MovedComponent overlapped during its movement (eg. generated during a sweep). Only used to add potentially new overlaps.
Might not be overlapping them now.

移動(dòng)組件在移動(dòng)過程中重疊的有序組件列表(例如:在掃描過程中生成)。僅用于添加潛在的新重疊。

說人話就是,本次碰撞查詢中檢測(cè)到的將要碰到的重疊。之后在UpdateOverlapsImpl中,將會(huì)使用該數(shù)組調(diào)用BeginComponentOverlap.

值得一提的是,即使我們當(dāng)前的組件(后續(xù)我們就叫它Self組件吧)已經(jīng)在其他組件的重疊里了,此時(shí)如果有移動(dòng)行為的話,該數(shù)組仍會(huì)把已經(jīng)重疊的組件保存進(jìn)去,至于會(huì)不會(huì)重復(fù)觸發(fā)BeginOverlap,后續(xù)當(dāng)然有相關(guān)的邏輯處理,這里先按下不表。

如果當(dāng)前沒有移動(dòng),只是簡(jiǎn)單的對(duì)組件進(jìn)行了旋轉(zhuǎn),那么這個(gè)數(shù)組將會(huì)是空的,可以查閱UPrimitiveComponent::MoveComponentImpl, 其中有這么一段代碼:

				TInlineOverlapInfoArray OverlapsAtEndLocation;
				bool bHasEndOverlaps = false;
				if (bRotationOnly)
				{
					bHasEndOverlaps = ConvertRotationOverlapsToCurrentOverlaps(OverlapsAtEndLocation, OverlappingComponents);
				}
				else
				{
					bHasEndOverlaps = ConvertSweptOverlapsToCurrentOverlaps(OverlapsAtEndLocation, PendingOverlaps, 0, GetComponentLocation(), GetComponentQuat());
				}
				TOverlapArrayView PendingOverlapsView(PendingOverlaps);
				TOverlapArrayView OverlapsAtEndView(OverlapsAtEndLocation);
				UpdateOverlaps(&PendingOverlapsView, true, bHasEndOverlaps ? &OverlapsAtEndView : nullptr);

有個(gè)bRotationOnly變量,如果只有旋轉(zhuǎn)的話,不會(huì)對(duì)PendingOverlaps進(jìn)行賦值。

也就是說,組件只做原地旋轉(zhuǎn)的話,是不會(huì)有新的重疊開始事件的。

OverlapsAtEndLocation

If non-null, the given list of overlaps will be used as the overlaps for this component at the current location, rather than checking for them with a scene query.
Generally this should only be used if this component is the RootComponent of the owning actor and overlaps with other descendant components have been verified.

(機(jī)翻)如果非空,則給定的重疊列表將用作該組件在當(dāng)前位置的重疊,而不是使用場(chǎng)景查詢來檢查它們。
一般來說,只有當(dāng)這個(gè)組件是擁有Actor的RootComponent,并且與其他子組件的重疊已經(jīng)被驗(yàn)證時(shí),才應(yīng)該使用這個(gè)組件。

說人話就是,這個(gè)數(shù)組將會(huì)存有Self組件當(dāng)前位置(查詢末端位置)的所有重疊,并且只有self組件是Actor的根組件時(shí)才應(yīng)該使用這個(gè)數(shù)組。

bDoNotifies

True to dispatch being/end overlap notifications when these events occur.

用于判斷是否觸發(fā)重疊事件。例如,當(dāng)bDoNotifies為false時(shí),OnBeginComponentOverlap、OnBeginActorComponentOverlap、OnEndComponentOverlap等相關(guān)委托都不會(huì)被觸發(fā)。

目前看來OverlapsAtEndLocation和NewPendingOverlaps的關(guān)系挺微妙的,隨著后面代碼的分析,他們的作用會(huì)越來越清晰。

調(diào)用該函數(shù)的幾種情況

那么什么情況下需要更新組件的重疊呢?

很明顯,當(dāng)組件產(chǎn)生任何Transform的變換時(shí),都應(yīng)該更新重疊以防止漏過任何一個(gè)事件。

除此以外,當(dāng)組件的碰撞狀態(tài)發(fā)生變化時(shí),也應(yīng)該及時(shí)更新重疊。筆者經(jīng)過對(duì)一個(gè)Character進(jìn)行不嚴(yán)謹(jǐn)?shù)恼{(diào)試,找到了幾個(gè)比較典型的調(diào)用方式:

1. UCharacterMovementComponent::PerformMovement

該函數(shù)是移動(dòng)組件進(jìn)行移動(dòng)的主要函數(shù),該函數(shù)會(huì)結(jié)合碰撞查詢,計(jì)算出組件移動(dòng)的目標(biāo)位置,調(diào)用棧如下:

也就是說當(dāng)你控制角色,使用移動(dòng)組件進(jìn)行移動(dòng)時(shí),每tick都會(huì)對(duì)重疊進(jìn)行一次更新。

2.UPrimiticeComponent::MoveComponent

該函數(shù)用于更新Actor的transform時(shí)調(diào)用。例如SetActorRotation,SetActorPosition等函數(shù),最終都會(huì)調(diào)用到MoveComponent函數(shù),并對(duì)重疊進(jìn)行更新

3.AActor::SetActorEnableCollision

這類函數(shù)用于改變組件的碰撞狀態(tài),同理還有設(shè)置組件的通道類型等函數(shù)。當(dāng)組件的碰撞狀態(tài)發(fā)生改變時(shí),都會(huì)調(diào)用一次UpdateOverlaps以更新重疊。

值得一提的是,這類函數(shù)對(duì)UpdateOverlaps調(diào)用的傳參都是默認(rèn)的,即傳入的兩個(gè)數(shù)組都是空值。這意味著更新重疊時(shí)不會(huì)引入新的重疊,只會(huì)對(duì)當(dāng)前已記錄的重疊進(jìn)行操作。

// update overlaps once after all components have been updated
UpdateOverlaps();

真正更新重疊的實(shí)現(xiàn)函數(shù):UPrimitiveComponent::UpdateOverlapsImpl

篇幅有限,筆者不會(huì)去詳細(xì)講解碰撞是如何查詢并產(chǎn)生結(jié)果的,也不會(huì)去講解組件移動(dòng)具體會(huì)發(fā)生什么事情(因?yàn)楣P者也沒來得及弄懂)。現(xiàn)在只需要知道一個(gè)前提:UE能通過某種方式獲得當(dāng)前的碰撞信息,并存入前面提到的函數(shù)參數(shù)中的兩個(gè)數(shù)組中。根據(jù)這個(gè)前提,接下來將圍繞UpdateOverlapsImpl 函數(shù)對(duì)整個(gè)重疊更新進(jìn)行詳細(xì)的講解。

總所周知,USceneComponent為Actor提供了表達(dá)自身空間信息的能力,可以為開發(fā)者提供Transform等信息,而碰撞相關(guān)的信息則交給了其子類UPrimitiveComponent。也就是說,只有繼承了UPrimitiveComponent的類才能擁有碰撞處理的能力,否則這個(gè)組件就是空間中的一個(gè)幽靈,無法與世界進(jìn)行任何交互。

而作為第一個(gè)擁有碰撞能力的組件,它擁有著一個(gè)足以彰顯其身份的成員:

TArray<FOverlapInfo> OverlappingComponents;

Set of components that this component is currently overlapping.

含義很明顯,保存了所有與當(dāng)前組件重疊且能生成重疊事件的其他組件。記住這個(gè)組件,可以說一個(gè)組件的重疊更新始終是圍繞著這個(gè)組件完成的。

對(duì)新加入的重疊進(jìn)行處理

一開始是一些簡(jiǎn)單的判斷。如果Actor還沒有beginPlayer,將不會(huì)繼續(xù)后續(xù)的邏輯。

緊隨其后的,就是對(duì)NewPendingOverlaps數(shù)組進(jìn)行處理,相關(guān)代碼如下:

// first, dispatch any pending overlaps
	if (GetGenerateOverlapEvents() && IsQueryCollisionEnabled())	
	{
		bCanSkipUpdateOverlaps = false;
		if (MyActor)
		{
			const FTransform PrevTransform = GetComponentTransform();
			// If we are the root component we ignore child components. Those children will update their overlaps when we descend into the child tree.
			// This aids an optimization in MoveComponent.
			const bool bIgnoreChildren = (MyActor->GetRootComponent() == this);

			if (NewPendingOverlaps)
			{
				// Note: BeginComponentOverlap() only triggers overlaps where GetGenerateOverlapEvents() is true on both components.
				const int32 NumNewPendingOverlaps = NewPendingOverlaps->Num();
				for (int32 Idx=0; Idx < NumNewPendingOverlaps; ++Idx)
				{
					BeginComponentOverlap( (*NewPendingOverlaps)[Idx], bDoNotifies );
				}
			}
.........

GetGenerateOverlapEvents() && IsQueryCollisionEnabled()

是否生成重疊事件&是否允許碰撞。

IsQueryCollisionEnabled()可以通過SetActorEnableCollision改變其狀態(tài);

GetGenerateOverlapEvents()可以在藍(lán)圖里勾選“生成重疊事件”或者改變bool值bGenerateOverlapEvents進(jìn)行修改。

補(bǔ)充一點(diǎn),只有兩個(gè)組件都能生成重疊事件,才會(huì)觸發(fā)雙方的BeginOverlap事件。


注意到有一個(gè)bIgnoreChildren變量,當(dāng)self組件為根組件時(shí)其為true。這意味著根組件始終不會(huì)考慮子組件的影響。而子組件呢,默認(rèn)下是會(huì)與本Actor的其他組件發(fā)生碰撞的,實(shí)際使用中我們很少會(huì)考慮這種問題,但這里可以作為一個(gè)小細(xì)節(jié)記一下。

UPrimitiveComponent::BeginComponentOverlap(const FOverlapInfo& OtherOverlap, bool bDoNotifies)

之后將對(duì)NewPendingOverlaps進(jìn)行一次完整的遍歷。前面提到,NewPendingOverlaps可能包含已經(jīng)重疊的組件,也可能包含還未重疊的組件。這些組件將在這個(gè)函數(shù)中進(jìn)行統(tǒng)一處理,忽略已經(jīng)重疊的組件,而未重疊的組件則調(diào)用雙方的OnComponentBeginOverlap委托。

void UPrimitiveComponent::BeginComponentOverlap(const FOverlapInfo& OtherOverlap, bool bDoNotifies)
{
	// If pending kill, we should not generate any new overlaps
	if (!IsValid(this))
	{
		return;
	}

	const bool bComponentsAlreadyTouching = (IndexOfOverlapFast(OverlappingComponents, OtherOverlap) != INDEX_NONE);
	if (!bComponentsAlreadyTouching)
	{
		UPrimitiveComponent* OtherComp = OtherOverlap.OverlapInfo.Component.Get();
		if (CanComponentsGenerateOverlap(this, OtherComp))
		{
			GlobalOverlapEventsCounter++;			
			AActor* const OtherActor = OtherComp->GetOwner();
			AActor* const MyActor = GetOwner();

			const bool bSameActor = (MyActor == OtherActor);
			const bool bNotifyActorTouch = bDoNotifies && !bSameActor && !AreActorsOverlapping(*MyActor, *OtherActor);

			// Perform reflexive touch.
			OverlappingComponents.Add(OtherOverlap);												// already verified uniqueness above
			AddUniqueOverlapFast(OtherComp->OverlappingComponents, FOverlapInfo(this, INDEX_NONE));	// uniqueness unverified, so addunique
			
			const UWorld* World = GetWorld();
			const bool bLevelStreamingOverlap = (bDoNotifies && MyActor->bGenerateOverlapEventsDuringLevelStreaming && MyActor->IsActorBeginningPlayFromLevelStreaming());
			if (bDoNotifies && ((World && World->HasBegunPlay()) || bLevelStreamingOverlap))
			{
				// first execute component delegates
				if (IsValid(this))
				{
					OnComponentBeginOverlap.Broadcast(this, OtherActor, OtherComp, OtherOverlap.GetBodyIndex(), OtherOverlap.bFromSweep, OtherOverlap.OverlapInfo);
				}

				if (IsValid(OtherComp))
				{
					// Reverse normals for other component. When it's a sweep, we are the one that moved.
					OtherComp->OnComponentBeginOverlap.Broadcast(OtherComp, MyActor, this, INDEX_NONE, OtherOverlap.bFromSweep, OtherOverlap.bFromSweep ? FHitResult::GetReversedHit(OtherOverlap.OverlapInfo) : OtherOverlap.OverlapInfo);
				}

				// then execute actor notification if this is a new actor touch
				if (bNotifyActorTouch)
				{
					// First actor virtuals
					if (IsActorValidToNotify(MyActor))
					{
						MyActor->NotifyActorBeginOverlap(OtherActor);
					}

					if (IsActorValidToNotify(OtherActor))
					{
						OtherActor->NotifyActorBeginOverlap(MyActor);
					}

					// Then level-script delegates
					if (IsActorValidToNotify(MyActor))
					{
						MyActor->OnActorBeginOverlap.Broadcast(MyActor, OtherActor);
					}

					if (IsActorValidToNotify(OtherActor))
					{
						OtherActor->OnActorBeginOverlap.Broadcast(OtherActor, MyActor);
					}
				}
			}
		}
	}
}

邏輯并不難,主要做了以下幾件事:

  1. 檢查OverlappingComponents數(shù)組,判斷該組件是否已重疊,如果未重疊就執(zhí)行后面的邏輯
  2. CanComponentsGenerateOverlap 判斷雙方是否都能生成重疊事件,如果其中一方不能重疊,函數(shù)到這也就結(jié)束了
  3. 判斷兩個(gè)Actor是否已重疊,如果已重疊,后續(xù)則不會(huì)觸發(fā)ActorOverlap事件
  4. 添加新的重疊到自己的OverlappingComponents中
  5. 將自己添加到對(duì)方的OverlappingComponents中
  6. 觸發(fā)雙方的ComponentBeginOverlap委托
  7. 觸發(fā)雙方的ActorBeginOverlap委托

可以看到,組件通過檢查自己的OverlappingComponents數(shù)組來判斷是否是已經(jīng)觸發(fā)的重疊,來規(guī)避重疊事件的重復(fù)觸發(fā)。另外,主動(dòng)觸發(fā)重疊的一方會(huì)直接觸發(fā)雙方的重疊事件,因?yàn)橹丿B更新通常是在運(yùn)動(dòng)中觸發(fā)的,如果其中一方不移動(dòng),只觸發(fā)主動(dòng)方的事件的話將會(huì)漏掉對(duì)方的重疊事件。

由于該函數(shù)會(huì)自動(dòng)規(guī)避已重疊的組件,因此我們就不用費(fèi)心思考慮是否會(huì)重復(fù)觸發(fā)重疊開始事件了,這個(gè)后面也會(huì)用到。


在重疊開始事件中往往會(huì)存在各種各樣的邏輯,其中包括移動(dòng)、銷毀、添加其他Actor等等邏輯,這些都是不可預(yù)測(cè)的,UE很明顯考慮到了這一點(diǎn),在重疊開始事件結(jié)束后,還需要再次檢查當(dāng)前的狀態(tài)是否和之前有所改變。

另外,我們還需要考慮本次重疊更新調(diào)用時(shí),是否有舊的重疊已失效,比如我們走出了重疊的范圍,或是別的組件自己關(guān)閉了碰撞。

// now generate full list of new touches, so we can compare to existing list and determine what changed
			TInlineOverlapInfoArray OverlapMultiResult;
			TInlineOverlapPointerArray NewOverlappingComponentPtrs;

因此,代碼里新定義了兩個(gè)臨時(shí)數(shù)組,其中OverlapMultiResult將會(huì)保存在新的位置重新重疊檢測(cè)的結(jié)果;NewOverlappingComponentPtrs更重要一些,會(huì)保存當(dāng)前重疊的指針,讓我們繼續(xù)往后看。

Self組件沒有移動(dòng)的情況

// Might be able to avoid testing for new overlaps at the end location.
				if (OverlapsAtEndLocation != nullptr && bAllowCachedOverlapsCVar && PrevTransform.Equals(GetComponentTransform()))
				{
					const bool bCheckForInvalid = (NewPendingOverlaps && NewPendingOverlaps->Num() > 0);
					if (bCheckForInvalid)
					{
						// BeginComponentOverlap may have disabled what we thought were valid overlaps at the end (collision response or overlap flags could change).
						GetPointersToArrayDataByPredicate(NewOverlappingComponentPtrs, *OverlapsAtEndLocation, FPredicateFilterCanOverlap(*this));
					}
					else
					{
						GetPointersToArrayData(NewOverlappingComponentPtrs, *OverlapsAtEndLocation);
					}
				}

篩選OverlapsAtEndLocation,將當(dāng)前能觸發(fā)重疊事件的組件指針存入NewOverlappingComponentPtrs。

這里使用bCheckForInvalid做了一個(gè)小優(yōu)化,如果NewPendingOverlaps為空,就意味著沒有任何BeginOverlap事件,就不需要篩選OverlapsAtEndLocation了,畢竟始終沒有機(jī)會(huì)改變。

Self組件有移動(dòng)的情況(或OverlapsAtEndLocation為空的情況)

else
				{
					SCOPE_CYCLE_COUNTER(STAT_PerformOverlapQuery);
					UE_LOG(LogPrimitiveComponent, VeryVerbose, TEXT("%s->%s Performing overlaps!"), *GetNameSafe(GetOwner()), *GetName());
					UWorld* const MyWorld = GetWorld();
					TArray<FOverlapResult> Overlaps;
					// note this will optionally include overlaps with components in the same actor (depending on bIgnoreChildren). 
					FComponentQueryParams Params(SCENE_QUERY_STAT(UpdateOverlaps), bIgnoreChildren ? MyActor : nullptr);
					Params.bIgnoreBlocks = true;	//We don't care about blockers since we only route overlap events to real overlaps
					FCollisionResponseParams ResponseParam;
					InitSweepCollisionParams(Params, ResponseParam);
					ComponentOverlapMulti(Overlaps, MyWorld, GetComponentLocation(), GetComponentQuat(), GetCollisionObjectType(), Params);

					for (int32 ResultIdx=0; ResultIdx < Overlaps.Num(); ResultIdx++)
					{
						const FOverlapResult& Result = Overlaps[ResultIdx];

						UPrimitiveComponent* const HitComp = Result.Component.Get();
						if (HitComp && (HitComp != this) && HitComp->GetGenerateOverlapEvents())
						{
							const bool bCheckOverlapFlags = false; // Already checked above
							if (!ShouldIgnoreOverlapResult(MyWorld, MyActor, *this, Result.OverlapObjectHandle.FetchActor(), *HitComp, bCheckOverlapFlags))
							{
								OverlapMultiResult.Emplace(HitComp, Result.ItemIndex);		// don't need to add unique unless the overlap check can return dupes
							}
						}
					}

					// Fill pointers to overlap results. We ensure below that OverlapMultiResult stays in scope so these pointers remain valid.
					GetPointersToArrayData(NewOverlappingComponentPtrs, OverlapMultiResult);
				}

當(dāng)Self組件在BeginOverlap中發(fā)生了坐標(biāo)的變化,那么我們就需要重新進(jìn)行碰撞查詢。這段代碼看著復(fù)雜,其實(shí)也就只做了這一件事:調(diào)用ComponentOverlapMulti函數(shù)進(jìn)行重疊查詢,然后將新查詢到的重疊的指針放入NewOverlappingComponentPtrs中。

另外,這里再次用到了bIgnoreChildren,說明UE真的很不想讓根組件更新到子組件的重疊,據(jù)說是為了優(yōu)化MoveComponent的流程?大概吧,但是這并不意味著子組件不會(huì)和根組件發(fā)生重疊事件,當(dāng)子組件主動(dòng)更新重疊時(shí),仍會(huì)檢測(cè)到根組件,并觸發(fā)雙方的重疊事件。

這里埋下了一個(gè)伏筆,這段函數(shù)還有一個(gè)觸發(fā)條件,就是OverlapsAtEndLocation為空的情況。本以為是一個(gè)不起眼的判斷,卻為子組件的重疊更新埋下了伏筆。


整理出可能存在的新的重疊后,我們還需考慮舊的重疊是否已經(jīng)失效,因此需要對(duì)比新舊重疊,來獲取新增的過時(shí)的重疊。

對(duì)比新舊重疊

緩存舊重疊

總之先把舊的重疊緩存一下吧,很顯然,直到前面調(diào)用重疊開始事件之前,OverlappingComponents數(shù)組里都是“舊重疊”。

這里的代碼定義了OldOverlappingComponentPtrs數(shù)組,緩存了舊重疊的指針,對(duì)應(yīng)前面的NewOverlappingComponentPtrs數(shù)組。之后將OverlappingComponents的元素以指針的方式拷貝到OldOverlappingComponentPtrs中。

// If we have any overlaps from BeginComponentOverlap() (from now or in the past), see if anything has changed by filtering NewOverlappingComponents
			if (OverlappingComponents.Num() > 0)
			{
				TInlineOverlapPointerArray OldOverlappingComponentPtrs;
				if (bIgnoreChildren)
				{
					GetPointersToArrayDataByPredicate(OldOverlappingComponentPtrs, OverlappingComponents, FPredicateOverlapHasDifferentActor(*MyActor));
				}
				else
				{
					GetPointersToArrayData(OldOverlappingComponentPtrs, OverlappingComponents);
				}

篩選新舊重疊

那么怎么判斷哪些重疊是過時(shí)的,哪些重疊是新的呢?

我們現(xiàn)在手里有兩個(gè)數(shù)組,一個(gè)是NewOverlappingComponentPtrs,保存了當(dāng)前所有有效的重疊;另一個(gè)是OldOverlappingComponentPtrs,保存了曾經(jīng)有效的重疊。

那么去除這兩個(gè)數(shù)組重復(fù)的部分,我們就可以篩選出過時(shí)的重疊和新的需要觸發(fā)重疊事件的重疊。他們之間的關(guān)系如下圖所示。

// Now we want to compare the old and new overlap lists to determine 
				// what overlaps are in old and not in new (need end overlap notifies), and 
				// what overlaps are in new and not in old (need begin overlap notifies).
				// We do this by removing common entries from both lists, since overlapping status has not changed for them.
				// What is left over will be what has changed.
				// 去除重復(fù)的部分
				for (int32 CompIdx=0; CompIdx < OldOverlappingComponentPtrs.Num() && NewOverlappingComponentPtrs.Num() > 0; ++CompIdx)
				{
					// RemoveAtSwap is ok, since it is not necessary to maintain order
					const bool bAllowShrinking = false;

					const FOverlapInfo* SearchItem = OldOverlappingComponentPtrs[CompIdx];
					const int32 NewElementIdx = IndexOfOverlapFast(NewOverlappingComponentPtrs, SearchItem);
					if (NewElementIdx != INDEX_NONE)
					{
						NewOverlappingComponentPtrs.RemoveAtSwap(NewElementIdx, 1, bAllowShrinking);
						OldOverlappingComponentPtrs.RemoveAtSwap(CompIdx, 1, bAllowShrinking);
						--CompIdx;
					}
				}

最終,OldOverlappingComponentPtrs就只剩下了過時(shí)的,需要調(diào)用EndOverlap的重疊;NewOverlappingComponentPtrs剩下了新增的,需要調(diào)用BeginOverlap的重疊。

EndComponentOverlap


				const int32 NumOldOverlaps = OldOverlappingComponentPtrs.Num();
				if (NumOldOverlaps > 0)
				{
					// Now we have to make a copy of the overlaps because we can't keep pointers to them, that list is about to be manipulated in EndComponentOverlap().
					TInlineOverlapInfoArray OldOverlappingComponents;
					OldOverlappingComponents.SetNumUninitialized(NumOldOverlaps);
					for (int32 i=0; i < NumOldOverlaps; i++)
					{
						OldOverlappingComponents[i] = *(OldOverlappingComponentPtrs[i]);
					}

					// OldOverlappingComponents now contains only previous overlaps that are confirmed to no longer be valid.
					for (const FOverlapInfo& OtherOverlap : OldOverlappingComponents)
					{
						if (OtherOverlap.OverlapInfo.Component.IsValid())
						{
							EndComponentOverlap(OtherOverlap, bDoNotifies, false);
						}
						else
						{
							// Remove stale item. Reclaim memory only if it's getting large, to try to avoid churn but avoid bloating component's memory usage.
							const bool bAllowShrinking = (OverlappingComponents.Max() >= 24);
							const int32 StaleElementIndex = IndexOfOverlapFast(OverlappingComponents, OtherOverlap);
							if (StaleElementIndex != INDEX_NONE)
							{
								OverlappingComponents.RemoveAtSwap(StaleElementIndex, 1, bAllowShrinking);
							}
						}
					}
				}

具體EndComponentOverlap發(fā)生了什么,基本和BeginCompoentOverlap反著來,筆者就不贅述了。

之后再將新的重疊遍歷調(diào)用BeginCompoentOverlap,本次重疊更新的主要內(nèi)容就基本結(jié)束了。

Self組件沒開啟碰撞的情況

還記得前面提到的GetGenerateOverlapEvents() && IsQueryCollisionEnabled()條件判斷嗎?對(duì)于調(diào)用了SetActorEnableCollision關(guān)閉Actor碰撞的情況,這里當(dāng)然也是有考慮的。

// first, dispatch any pending overlaps
	if (GetGenerateOverlapEvents() && IsQueryCollisionEnabled())	//TODO: should modifying query collision remove from mayoverlapevents?
	{....}
	else
	{
		// GetGenerateOverlapEvents() is false or collision is disabled
		// End all overlaps that exist, in case GetGenerateOverlapEvents() was true last tick (i.e. was just turned off)
		if (OverlappingComponents.Num() > 0)
		{
			const bool bSkipNotifySelf = false;
			ClearComponentOverlaps(bDoNotifies, bSkipNotifySelf);
		}
	}

當(dāng)OverlappingComponents數(shù)組里還有重疊,我們需要將這些重疊全部處理掉,也就是一一調(diào)用EndComponentOverlap,UE在這里將其寫成了一個(gè)ClearComponentOverlaps函數(shù)。

ClearComponentOverlaps

void UPrimitiveComponent::ClearComponentOverlaps(bool bDoNotifies, bool bSkipNotifySelf)
{
	if (OverlappingComponents.Num() > 0)
	{
		// Make a copy since EndComponentOverlap will remove items from OverlappingComponents.
		const TInlineOverlapInfoArray OverlapsCopy(OverlappingComponents);
		for (const FOverlapInfo& OtherOverlap : OverlapsCopy)
		{
			EndComponentOverlap(OtherOverlap, bDoNotifies, bSkipNotifySelf);
		}
	}
}

調(diào)用子組件的UpdateOverlap

在講解這部分之前,必須強(qiáng)調(diào)很重要的一點(diǎn):

前面提到的移動(dòng)過程產(chǎn)生的重疊更新,是不會(huì)直接通過子組件調(diào)用的,必須通過根組件先調(diào)用UpdateOverlap,然后經(jīng)過循環(huán)遞歸調(diào)用,才能觸發(fā)子組件的UpdateOverlap。

然后呢,看看在根組件經(jīng)過前面一大串的邏輯后,在這個(gè)函數(shù)的末尾,是如何調(diào)用子組件的UpdateOverlap的:

// now update any children down the chain.
	// since on overlap events could manipulate the child array we need to take a copy
	// of it to avoid missing any children if one is removed from the middle
	TInlineComponentArray<USceneComponent*> AttachedChildren;
	AttachedChildren.Append(GetAttachChildren());

	for (USceneComponent* const ChildComp : AttachedChildren)
	{
		if (ChildComp)
		{
			// Do not pass on OverlapsAtEndLocation, it only applied to this component.
			bCanSkipUpdateOverlaps &= ChildComp->UpdateOverlaps(nullptr, bDoNotifies, nullptr);
		}
	}

先說一個(gè)小細(xì)節(jié):在遍歷子組件之前,先緩存了一份子組件,是因?yàn)樽咏M件更新重疊的過程中,可能會(huì)自己脫離父組件,導(dǎo)致循環(huán)出現(xiàn)BUG,這點(diǎn)大家平時(shí)寫代碼的時(shí)候要注意一下。

我們可以看到最后調(diào)用了這樣一行代碼:

ChildComp->UpdateOverlaps(nullptr, bDoNotifies, nullptr);

然后發(fā)現(xiàn)傳入的兩個(gè)數(shù)組都是nullptr。

what??jī)蓚€(gè)數(shù)組都是空指針的話,那么子組件還怎么更新重疊?

現(xiàn)在回過去看 Self組件有移動(dòng)的情況(或OverlapsAtEndLocation為空的情況)這一節(jié),會(huì)發(fā)現(xiàn)子組件會(huì)直接走這段邏輯,也就是現(xiàn)場(chǎng)判斷組件在場(chǎng)景中的重疊的方式,之后再進(jìn)行后面的邏輯。

至此,UpdateOverlap的流程就基本結(jié)束了。

根組件跳過子組件的重疊查詢

斷點(diǎn)調(diào)試發(fā)現(xiàn),根組件在調(diào)用UpdateOverlaps的NewPendingOverlaps數(shù)組中,并沒有任何子組件,哪怕子組件碰撞全開。

往上追溯,才發(fā)現(xiàn)UPrimitiveComponent::MoveComponentImpl里在重疊檢測(cè)時(shí)還藏了一手:

			FComponentQueryParams Params(SCENE_QUERY_STAT(MoveComponent), Actor);
			FCollisionResponseParams ResponseParam;
			InitSweepCollisionParams(Params, ResponseParam);
			Params.bIgnoreTouches |= !(GetGenerateOverlapEvents() || bForceGatherOverlaps);
			Params.TraceTag = TraceTagName;
			bool const bHadBlockingHit = MyWorld->ComponentSweepMulti(Hits, this, TraceStart, TraceEnd, InitialRotationQuat, Params);

FComponentQueryParams Params的第二個(gè)參數(shù)就是要忽略的Actor,這里的Actor指的就是本身,所以檢測(cè)的結(jié)果自然就沒有自己的子組件了。

不過即便如此,如果子組件在碰撞上允許和根組件生成重疊事件時(shí),在子組件的UpdateOverlaps還是不可避免地與根組件發(fā)生重疊關(guān)系。不過UE的注釋里都提到了,這都是為了優(yōu)化MovementCompoennt的移動(dòng)流程。

參考

角色移動(dòng)組件 | 虛幻引擎文檔 (unrealengine.com)

UE4的移動(dòng)碰撞 - 知乎 (zhihu.com)

總結(jié)

以上是生活随笔為你收集整理的UE5: UpdateOverlap - 从源码深入探究UE的重叠触发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

国产无遮挡猛进猛出免费软件 | 日韩精品一区二区电影 | 奇米导航 | 日韩1级片 | 欧美精品国产综合久久 | 精品一区二区电影 | 中文字幕电影一区 | 国产真实精品久久二三区 | 天天综合天天综合 | 国产精品久久久久久久久久久久冷 | 精品在线亚洲视频 | 婷婷丁香七月 | 精品久久久一区二区 | 亚在线播放中文视频 | 91成人网页版 | 欧美日韩国产欧美 | 欧美在线不卡一区 | 91探花视频 | 麻豆91在线看 | 欧美日韩午夜爽爽 | 成人动漫一区二区 | 99久久精品免费看国产 | 亚洲久草在线视频 | 日韩成人精品一区二区 | 四虎影视国产精品免费久久 | 亚洲乱码国产乱码精品天美传媒 | a久久久久久| 欧美精品一区二区蜜臀亚洲 | 天天综合视频在线观看 | 国产精品日韩高清 | 亚洲视频99 | 亚洲成av人片在线观看无 | 国内外成人在线 | 日韩理论在线视频 | 精品国产精品久久一区免费式 | 精品久久一二三区 | 亚洲综合日韩在线 | 精品一区二区三区电影 | 亚洲激情一区二区三区 | 久久伊人八月婷婷综合激情 | 国产精品一区二区av麻豆 | 欧美日韩国产一区二 | 日韩在线精品一区 | 久草在线久草在线2 | 亚洲伊人网在线观看 | 成人黄色大片网站 | 成人免费视频a | 久久美女电影 | 成年人电影免费看 | 中文字幕有码在线播放 | 国产手机在线精品 | 国产一区二区三区在线免费观看 | 国产日产欧美在线观看 | 欧美日韩国产伦理 | 欧美日韩色婷婷 | 亚洲综合精品在线 | www.伊人网 | 国产不卡一区二区视频 | 国产成人不卡 | 一区二区三区观看 | 色视频成人在线观看免 | 爱爱一区 | 国产在线视频在线观看 | 91精品国产福利在线观看 | 亚洲天堂首页 | 日韩视频一区二区三区在线播放免费观看 | 亚洲精品国产精品国 | 亚洲精品乱码白浆高清久久久久久 | 亚洲尺码电影av久久 | 国产精品精品国产 | 手机看片中文字幕 | 国产精品视频永久免费播放 | 日本黄色大片儿 | 黄色一级大片在线免费看产 | 字幕网在线观看 | 久久精品久久精品 | 日韩在线观看中文 | 久久综合中文色婷婷 | 国产免费嫩草影院 | 日本不卡视频 | 国产又粗又硬又爽的视频 | 日韩av影视在线观看 | 免费看十八岁美女 | www.一区二区三区 | 欧美精品久久久久久久亚洲调教 | 国产韩国日本高清视频 | 欧美与欧洲交xxxx免费观看 | 日韩一级黄色大片 | 中文字幕乱码电影 | 91视频久久久 | 五月婷婷狠狠 | 国产伦精品一区二区三区四区视频 | 草久久av| 91久久精品日日躁夜夜躁国产 | 日韩精品免费专区 | 国产特级毛片 | 久久99中文字幕 | 日日夜夜免费精品视频 | 免费日韩电影 | 天天性天天草 | 成人免费毛片aaaaaa片 | 5月丁香婷婷综合 | 国产成人av片 | 亚洲欧美激情精品一区二区 | 日韩欧美综合在线视频 | 国产视频不卡一区 | 伊人狠狠干 | avwww在线 | 亚洲综合丁香 | 日日干干| 国产你懂的在线 | 久草视频免费看 | 91亚洲精品久久久蜜桃借种 | 人人爽人人搞 | 97综合视频 | 成人在线播放av | 免费在线观看视频一区 | 欧美成人影音 | 夜色资源站wwwcom | 日本在线观看一区二区 | 安徽妇搡bbbb搡bbbb | 黄色午夜网站 | 色综合久久88色综合天天免费 | av在线一二三区 | 日日激情 | 狠狠色噜噜狠狠 | av色影院 | 国产美女永久免费 | 亚洲狠狠丁香婷婷综合久久久 | 天堂av网址| 色综合天天天天做夜夜夜夜做 | av免费在线观看1 | 亚洲专区欧美 | 国产精品 9999 | 韩国精品视频在线观看 | 九九免费精品视频在线观看 | 色丁香婷婷 | 亚洲视频 中文字幕 | 亚洲经典精品 | 中文字幕在线一二 | 日韩欧美国产成人 | 美女免费视频一区二区 | 久久精品国产精品亚洲 | 天天色.com| 91精品老司机久久一区啪 | 国产精品短视频 | 国产色女 | 看片网站黄 | 国产在线第三页 | 色综合久久悠悠 | 免费日韩 精品中文字幕视频在线 | 蜜臀久久99精品久久久久久网站 | 97视频入口免费观看 | 国产精品99久久久久久久久久久久 | 亚洲美女在线一区 | 91丨九色丨91啦蝌蚪老版 | 亚洲精品视频国产 | 天堂在线v| 九九热.com| 久久精品国产成人精品 | 国产日韩欧美视频 | av大全在线免费观看 | 亚洲麻豆精品 | 久久久精品福利视频 | 一区中文字幕电影 | 成人一区二区在线观看 | 久久在线 | 美女黄频网站 | 国产精品1区2区在线观看 | 日韩av影片在线观看 | 国产精品av电影 | 日韩成人精品一区二区 | 亚洲成人精品久久久 | 99久久99久久精品 | 婷婷丁香七月 | 国产精品久久久久久久久蜜臀 | 亚洲免费永久精品国产 | 日本韩国中文字幕 | 欧美精品一区二区在线观看 | 在线免费视频 你懂得 | 天天综合网久久综合网 | 久草视频免费 | 国产精品中文字幕在线播放 | 久久精品视频在线免费观看 | 99久久精品网 | 婷婷网站天天婷婷网站 | 精品在线播放视频 | 国产成人久久77777精品 | 欧美三人交 | 国产精品专区在线观看 | 91麻豆精品| 亚洲国产最新 | 91av免费在线观看 | 中文字幕免费不卡视频 | 国产精品免费在线 | 国产免费大片 | 久久情网| 亚洲综合一区二区精品导航 | 久久99亚洲网美利坚合众国 | 久久精品久久久久电影 | 日韩性xxxx | 久久久久久久久久久久久国产精品 | 国产一区二区中文字幕 | 91麻豆免费看 | 日韩两性视频 | 天天操天天色天天射 | 手机av看片 | 久久精品国产美女 | 久久久久亚洲a | 亚洲高清资源 | 国产精品中文字幕在线观看 | 91视频国产高清 | 久久伊人免费视频 | 亚洲免费av片 | 久久婷婷一区二区三区 | 久久综合九色 | 亚洲黄色网络 | 亚洲欧美日韩在线看 | 福利av在线| 97av色 | 亚洲专区中文字幕 | 日韩区视频 | 91麻豆精品国产91 | 91porny九色在线播放 | 久久亚洲欧美日韩精品专区 | 国产精品美女久久久免费 | 久久视频免费在线 | 国产日韩欧美网站 | 探花视频在线观看免费版 | 日韩欧美综合视频 | 成人黄色电影在线观看 | 欧美成a人片在线观看久 | 成人av亚洲| 婷婷午夜天 | 欧美一级电影免费观看 | 深爱激情综合网 | 亚洲国产免费看 | 在线视频黄 | 免费看的av片 | 亚洲清纯国产 | 福利网在线 | 在线婷婷| 一区二区三区动漫 | 少妇搡bbb | 成人一区二区三区中文字幕 | 99久久精品国产欧美主题曲 | 久久久久国| 五月天高清欧美mv | 久久天堂影院 | 黄色免费高清视频 | 国产一区二区三区视频在线 | 久久五月婷婷丁香 | 日韩欧美在线观看一区 | 91看片在线看片 | 国产又粗又猛又爽又黄的视频免费 | 免费精品视频在线观看 | 亚洲精品美女 | av色网站| 国产精品一区二区视频 | 国产精品久久久久久久久大全 | 国产麻豆精品久久一二三 | 亚洲精品在线看 | 精品一区二区三区香蕉蜜桃 | 国产亚州精品视频 | 最新成人在线 | 99re久久资源最新地址 | 少妇bbw揉bbb欧美 | 91亚洲国产成人 | 日日操日日插 | 欧美日韩一区二区免费在线观看 | 韩国av一区二区三区 | 97在线视频观看 | 黄色视屏免费在线观看 | 亚洲一区免费在线 | 亚洲国产精品电影 | 日韩av一区二区在线播放 | 麻豆视屏 | 天天干,天天射,天天操,天天摸 | 91av视频免费观看 | 欧美日韩高清国产 | a视频在线看 | 69视频国产 | 国产麻豆精品久久一二三 | 成人免费xxxxxx视频 | 中文字幕色婷婷在线视频 | 奇米网网址 | 亚洲精品人人 | 国产视频 亚洲视频 | 国产一区二区精品 | 亚洲精品自在在线观看 | 亚洲播放一区 | 玖玖玖在线| 夜添久久精品亚洲国产精品 | 最近中文字幕高清字幕在线视频 | 亚洲精品乱码白浆高清久久久久久 | 在线成人国产 | 久久精品国产v日韩v亚洲 | 天天射射天天 | 久久无码av一区二区三区电影网 | 国产字幕在线播放 | 在线观看亚洲国产精品 | 日韩视频免费观看高清 | 亚洲精品一区二区网址 | 一级黄色毛片 | 日韩av男人的天堂 | 夜色成人av| 国产97视频在线 | 热99在线视频 | 99精品免费在线观看 | 九色精品 | 午夜久久久久久久久久影院 | 国产一级视频在线免费观看 | 日韩精品极品视频 | 超碰在线中文字幕 | 韩日视频在线 | 日韩av伦理片| 久久69精品 | 亚洲人成影院在线 | 国产一区视频在线播放 | 亚洲精品久久久久中文字幕m男 | 免费手机黄色网址 | 黄色资源网站 | 嫩草伊人久久精品少妇av | 久草在线资源观看 | 成人性生爱a∨ | 日韩欧美电影在线 | av不卡免费在线观看 | 亚洲乱码精品久久久 | 麻花豆传媒mv在线观看网站 | 国产日韩欧美在线影视 | 超薄丝袜一二三区 | 国产精品成人一区二区三区吃奶 | 精品国产欧美 | 国产麻豆精品在线观看 | 亚洲区精品视频 | 国产91对白在线播 | 黄色日视频 | 久久综合色影院 | 天天躁天天操 | 美女久久久 | 日韩国产欧美在线视频 | 日韩成人邪恶影片 | 国产老妇av | 国产精品va在线观看入 | 国产精品免费视频网站 | av在线成人| 成年人视频免费在线播放 | 黄色软件视频大全免费下载 | 黄色一级在线观看 | 99tvdz@gmail.com| 一区二区中文字幕在线播放 | 99国产一区二区三精品乱码 | 欧美一级性视频 | 黄网站免费大全入口 | 在线播放av网址 | 国产亚洲在 | 一本—道久久a久久精品蜜桃 | 一级淫片a | 久久精选视频 | 久久伊人热| 一区二区三区四区久久 | 免费在线播放黄色 | 欧美日韩在线观看一区二区三区 | 一区二区精品在线 | 81国产精品久久久久久久久久 | 久久久国产精华液 | 天天干 夜夜操 | 精品视频在线观看 | 亚洲成人精品久久 | 在线看免费 | 9在线观看免费高清完整版在线观看明 | 在线观看岛国片 | 99热日本| 91免费版在线 | 国产福利一区二区在线 | 欧美尹人 | 久久久av电影 | 精品av在线播放 | 波多野结衣电影一区 | 国产黄色免费在线观看 | 超碰伊人网 | 久久av中文字幕片 | 午夜免费在线观看 | 国产片免费在线观看视频 | 免费视频黄色 | 天天射天天射天天射 | 精品在线小视频 | 91最新国产 | 99久在线精品99re8热视频 | 久久黄色影院 | 在线成人中文字幕 | 久久国产福利 | 在线观看亚洲专区 | 久久久久久久久久久久av | 中文字幕影片免费在线观看 | 久久少妇av | 亚洲国产成人在线播放 | 91少妇精拍在线播放 | 国产一级片在线播放 | 欧美片网站yy | 狠狠色狠狠色终合网 | 成人资源网 | 日本久久久亚洲精品 | 欧美性生活免费 | 亚洲污视频| 欧洲一区二区在线观看 | 亚洲天天看 | 亚洲九九九在线观看 | 国产精品成人久久久久 | 美女国内精品自产拍在线播放 | 欧美污污网站 | 成 人 黄 色 视频播放1 | 国产成人精品日本亚洲999 | 亚洲精品66 | 国产精品永久免费观看 | av在线影片 | 热久久视久久精品18亚洲精品 | 欧美a级片网站 | 日日操天天爽 | 人人插人人干 | 国产夫妻av在线 | 久久人人爽爽人人爽人人片av | 免费在线观看不卡av | 中文字幕av影院 | 日韩成片| 婷婷综合影院 | www.99久久.com | 伊人伊成久久人综合网小说 | wwwwww色| 91久久爱热色涩涩 | 久久综合色天天久久综合图片 | 337p日本欧洲亚洲大胆裸体艺术 | 婷婷在线网站 | 欧美激情另类文学 | 成人免费xxx在线观看 | 国产精品大尺度 | 中文字幕色播 | 香蕉色综合 | 国产一区二区三区网站 | 在线成人免费电影 | 狠狠狠色狠狠色综合 | 999久久国产 | 一本一道久久a久久精品 | 国产日韩中文字幕 | 免费网站黄 | 97视频在线播放 | 天天干天天干天天操 | 国产成人一区二区三区在线观看 | 日韩久久久久久久久久久久 | 日本mv大片欧洲mv大片 | 91久草视频 | 超碰人人在线观看 | 国产精品九九久久99视频 | 欧美激情在线网站 | 精品国产福利在线 | 亚洲国产中文字幕在线观看 | 免费视频97 | 激情婷婷色 | 夜又临在线观看 | 日韩在线欧美在线 | 国产人免费人成免费视频 | 国产中文字幕一区二区三区 | 99精品免费视频 | 黄色影院在线免费观看 | 在线观av | 四虎成人精品永久免费av | 人人澡人人添人人爽一区二区 | 日本高清久久久 | 日韩一区二区三区在线观看 | 国产精品久久电影网 | 51久久夜色精品国产麻豆 | 玖玖综合网 | 国产精品精品国产色婷婷 | 日韩电影中文字幕 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 国产.精品.日韩.另类.中文.在线.播放 | 在线免费亚洲 | 二区在线播放 | 在线观看岛国 | 黄色成人影院 | 91av视频在线免费观看 | 91亚洲国产成人久久精品网站 | 国产黄视频在线观看 | 久久成人精品电影 | 我爱av激情网 | 欧美特一级 | 久久免费一级片 | 人人干天天干 | 伊香蕉大综综综合久久啪 | 丁香在线视频 | 日本精品在线 | 91免费国产在线观看 | 国产精品毛片一区二区在线看 | 欧美国产日韩在线观看 | 亚洲黄色片一级 | 视频在线观看日韩 | 国产中文字幕亚洲 | 日韩成人免费在线电影 | 成人精品久久 | 久久丁香网| 伊人热 | 狠狠操夜夜操 | 国产精品每日更新 | 天天爽天天射 | 免费a一级 | 日韩在线在线 | 久久综合欧美精品亚洲一区 | 成人a毛片| 色偷偷97| 国产一级做a爱片久久毛片a | 国产v在线 | 久久午夜电影 | 精品亚洲二区 | 韩国av免费在线 | 国产91在| 精品一区二区三区久久久 | 在线免费观看一区二区三区 | 极品嫩模被强到高潮呻吟91 | 久久伊人精品一区二区三区 | 96精品在线 | 欧美精品成人在线 | 首页中文字幕 | 黄色免费观看网址 | 国内丰满少妇猛烈精品播 | 国产福利一区在线观看 | 在线精品视频免费观看 | 亚洲最快最全在线视频 | 91精品国自产在线观看欧美 | 亚洲综合成人专区片 | 一区二区精品视频 | 日韩中文三级 | 中文在线字幕观看电影 | 成人av播放| 亚洲精品久 | 亚洲成人精品av | 成人在线视频一区 | 亚洲国产偷 | 久久国色夜色精品国产 | 在线观看视频中文字幕 | 日日天天狠狠 | 亚洲精品视频中文字幕 | 91久久国产露脸精品国产闺蜜 | 97综合在线 | 久久久久久欧美二区电影网 | 97成人精品视频在线播放 | 国产 亚洲 欧美 在线 | 亚洲在线网址 | 中文字幕最新精品 | 中文字幕av网站 | 久久激情小视频 | 亚洲一级特黄 | 在线视频免费观看 | 亚洲精品一区二区三区新线路 | 一级黄色片毛片 | 超碰.com| 999热视频| 日韩免费在线观看视频 | 国产日韩欧美在线观看 | 在线观看黄av | 国内精品久久久久影院一蜜桃 | 成人黄色av免费在线观看 | 国产成人精品在线观看 | 天天伊人狠狠 | 国产一区二区精品在线 | 日韩精品短视频 | av+在线播放在线播放 | 久久国色夜色精品国产 | 婷婷视频在线播放 | www.色com | 日韩激情综合 | 国产一级精品在线观看 | 国产精品久久伊人 | 免费日韩视频 | 久久99亚洲精品 | 国产精品人成电影在线观看 | 一区二区三区不卡在线 | 亚洲精品国产精品国自产 | 美女视频黄在线 | 国产精品va视频 | 一区二区三区在线观看中文字幕 | 久久综合狠狠综合 | 婷婷丁香激情综合 | 午夜精品久久久99热福利 | 久久久久亚洲精品国产 | 91中文字幕在线 | 欧美一级特黄高清视频 | 国产电影黄色av | 久草在在线| av电影免费在线播放 | 91精品国产乱码久久桃 | 天天干夜夜想 | 国产极品尤物在线 | 免费观看国产成人 | 91在线公开视频 | 伊人国产在线播放 | 国产黄a三级三级 | 久久99精品国产91久久来源 | 在线视频观看国产 | 欧美性色网站 | 色婷婷免费 | 久99久在线视频 | 69亚洲乱| 亚洲精品一区二区在线观看 | 91激情在线视频 | 成人午夜电影久久影院 | 久久人人97超碰精品888 | 三级黄色大片在线观看 | 日韩精品一区二区免费 | 久久公开视频 | 依人成人综合网 | 欧美色插| 欧美一级黄色视屏 | 探花视频在线版播放免费观看 | 最新极品jizzhd欧美 | 婷婷精品在线视频 | 国产亚洲视频在线观看 | 亚洲永久精品在线观看 | 91完整视频| 婷婷精品国产欧美精品亚洲人人爽 | 国产亚洲精品xxoo | av黄色影院| 玖玖视频免费在线 | 热久精品 | 97超碰色偷偷 | av不卡网站 | 国产黄色大片 | 免费在线视频一区二区 | av中文字幕日韩 | 午夜私人影院久久久久 | 成人午夜剧场在线观看 | 国产一级高清视频 | 国产手机免费视频 | 99久久久国产精品 | 国内精品视频一区二区三区八戒 | 在线日韩中文 | 日韩激情第一页 | 2019中文最近的2019中文在线 | av看片网址 | 在线视频 成人 | 人人添人人澡人人澡人人人爽 | 国产精品系列在线播放 | 色综合久久99| av在线成人 | 日韩三级不卡 | 亚洲另类视频在线 | 激情av资源 | 日韩免费成人av | 欧美不卡在线 | 久久99久久99久久 | 亚洲另类在线视频 | 韩国av在线 | 一区二区中文字幕在线 | 中文字幕一区二区三 | 狠狠的干 | 干干日日 | 日韩性xxxx | 亚洲h在线播放在线观看h | 在线a亚洲视频播放在线观看 | 97精品在线观看 | av在线电影免费观看 | 久久成人免费 | sesese图片| 亚洲免费一级 | 国产粉嫩在线观看 | 欧美aa一级片| 久久久久久中文字幕 | 手机在线欧美 | 久久伊99综合婷婷久久伊 | 国产精品自拍在线 | 欧美日本日韩aⅴ在线视频 插插插色综合 | 日韩v欧美v日本v亚洲v国产v | 久久九九免费视频 | 亚洲黄色一级大片 | 97国产在线观看 | 成人在线播放av | 综合色站| 亚洲黄色成人 | 99高清视频有精品视频 | 国产99在线播放 | 欧美在线观看视频一区二区 | 久久精品视频播放 | 中文字幕在线看视频 | 96国产在线| 欧美日韩高清一区二区三区 | www黄色com| 二区视频在线观看 | 免费精品在线 | 久久久久久久久精 | www.91成人 | 92中文资源在线 | 亚洲精品久久久蜜臀下载官网 | 永久免费观看视频 | 日韩精品久久一区二区三区 | 日韩视频中文字幕在线观看 | 国内久久看 | 国产啊v在线观看 | 天天干天天操天天射 | 欧美另类一二三四区 | 久久精品久久久久 | 国产手机av在线 | 天天干夜夜爽 | 91在线成人| 日韩精品一区二区电影 | 91大神精品视频在线观看 | 91丨九色丨蝌蚪丨对白 | 精品一区二区在线免费观看 | 婷婷伊人五月 | 日本精品久久久久影院 | 中文字幕乱码视频 | 色婷婷亚洲婷婷 | 91爱爱中文字幕 | 国产精品精品久久久 | 在线观看亚洲a | 亚洲欧美国产精品久久久久 | 狠狠操综合 | 丁香久久| 午夜色大片在线观看 | 国产护士av | 果冻av在线 | 高清不卡免费视频 | 欧美性天天 | 久久久91精品国产一区二区三区 | 91在线一区 | 成人h视频在线播放 | 久久久国产一区 | 午夜在线国产 | 激情五月激情综合网 | 天天做天天爱夜夜爽 | 久久久免费看片 | 欧美精品在线观看一区 | 激情大尺度视频 | 中文字幕av影院 | 成在人线av | 日韩乱色精品一区二区 | 国产黄免费 | 午夜精品福利一区二区 | 六月丁香综合 | 国产一区二区在线免费播放 | 在线观看中文字幕dvd播放 | 久久精品视频18 | 久久久久国产精品厨房 | 日本在线观看中文字幕无线观看 | 日日夜夜婷婷 | 中文字幕有码在线观看 | 欧美日韩网站 | 免费看黄视频 | 日韩视频a| 国产精品手机播放 | 午夜在线免费视频 | 国产 视频 高清 免费 | 91亚洲狠狠婷婷综合久久久 | 国产99久久久国产精品成人免费 | 久久久久久在线观看 | www.国产精品 | av免费电影在线 | 成人黄色在线 | 九九热在线播放 | 国产亚洲久久 | 91福利视频网站 | 国产精品毛片久久久久久 | 色爱区综合激月婷婷 | 成人啊 v | 91新人在线观看 | 精品国产乱码久久久久久浪潮 | 美女久久久久久久久久 | 久草在线免 | 精品欧美一区二区三区久久久 | 婷婷久草 | 天天天插| 国产码电影| 麻豆果冻剧传媒在线播放 | 国产剧情一区二区 | 粉嫩一二三区 | 婷婷亚洲五月色综合 | 天天干,天天草 | 丁香花在线观看视频在线 | 99久久久久成人国产免费 | 在线播放一区二区三区 | 精品视频资源站 | 色国产在线 | 99热在| av综合站| 日本精品久久久久中文字幕 | 中文字幕免费看 | 亚洲精品欧美成人 | 国产第一页精品 | 亚洲性视频 | av高清在线 | 亚洲激情视频 | 国产中文字幕第一页 | 五月天亚洲综合 | 国产免费一区二区三区最新 | 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 中文字幕高清在线播放 | 国产成人亚洲在线电影 | 久久伊人91| 永久免费的啪啪网站免费观看浪潮 | 精品影院 | 日韩一区二区三区在线看 | av电影免费看 | 欧美日韩一区久久 | 狠狠色综合网站久久久久久久 | 欧洲精品久久久久毛片完整版 | 狠狠干网址 | 视频国产精品 | 九九免费精品视频在线观看 | 精品福利国产 | 久久午夜精品影院一区 | 国产亚洲欧美精品久久久久久 | 国产亚洲日 | 在线高清 | 91九色最新 | 天天av资源| 中文视频在线看 | 国产91精品高清一区二区三区 | 久草综合在线 | 国产97色在线 | 国产美女免费视频 | 亚洲精品在线观看视频 | 国产一卡二卡四卡国 | 亚洲精品乱码久久久久 | 精品一区二区三区在线播放 | 亚洲高清视频在线观看免费 | 亚洲精品a区 | 九热在线| 国产精品毛片一区二区在线看 | av一区二区在线观看中文字幕 | 少妇视频一区 | 国产成人精品免高潮在线观看 | 日韩一区二区三 | 女女av在线| 欧美日韩三级在线观看 | 久久夜色电影 | 久久久久久高潮国产精品视 | 亚洲一区 影院 | a√天堂中文在线 | 久久人人爽人人爽人人 | 黄色视屏免费在线观看 | 久久久免费高清视频 | 四虎免费在线观看 | 免费a v观看 | 欧美一区二区三区在线 | 久久久久免费精品国产 | 国产精品 久久 | 亚洲电影久久久 | 久草视频国产 | 天天干天天上 | 国产在线国偷精品产拍免费yy | 欧美日韩在线视频一区 | 韩日视频在线 | 激情婷婷网 | 精品一区二区在线免费观看 | 国产淫片 | 丁香六月五月婷婷 | 国产精品一级在线 | 国产69熟 | 日韩视频a | 国产91精品在线播放 | 人人插人人费 | 国产999精品久久久久久绿帽 | 91大神免费视频 | 欧美日韩高清不卡 | 人人舔人人爱 | 亚洲一区日韩精品 | 日韩在线视频在线观看 | 日韩精品一区二区三区第95 | 国产九九九视频 | 亚洲另类交 | 国产高清在线免费视频 | 91免费看黄 | 久久99国产精品自在自在app | 久久久久久久综合色一本 | 日韩中文在线播放 | 国产手机在线播放 | 国产一区在线播放 | 五月婷婷六月丁香在线观看 | 园产精品久久久久久久7电影 | www.狠狠插.com| av资源中文字幕 | 最近中文字幕完整视频高清1 | 亚洲尺码电影av久久 | 天天色天天操综合网 | 国产精品11 | 国产一级精品绿帽视频 | 91女神的呻吟细腰翘臀美女 | 17婷婷久久www | 日韩av快播电影网 | av成人免费在线看 | 免费在线观看一级片 | 国产精品美女免费看 | 日韩理论片中文字幕 | 日韩精品一区不卡 | 久久国产免费看 | 99久久这里有精品 | 一级免费黄视频 | 在线综合 亚洲 欧美在线视频 | 国产精品久久久久久久久久尿 | 日韩久久精品一区 | 国产色女人 | 天天干天天做天天操 | 免费看三级 | 麻豆精品视频在线 | 97超碰国产精品女人人人爽 | 久久伊人免费视频 | 欧美性脚交| av不卡免费看 | av在线免费播放 | av在线播放网址 | 亚洲一级黄色片 | 亚洲一区美女视频在线观看免费 | 亚洲视频网站在线观看 | 园产精品久久久久久久7电影 | 国产中文字幕91 | 久久免费国产精品 | 亚洲婷婷综合色高清在线 | 最近中文字幕免费av | 久久超碰在线 | 日批视频在线播放 | 精品专区 | 午夜精品一二区 | 国产一级片直播 | 久久欧美在线电影 | 成人h动漫精品一区二 | 日韩在线无 | 国产精品99久久久久的智能播放 | a在线播放| 在线黄色av电影 | 精品久久一二三区 | 久久精品欧美 | 一区二区三区免费播放 | 亚洲 欧美 国产 va在线影院 | 极品国产91在线网站 | 狠狠综合久久av | 天天操天天色综合 | 成人av免费在线看 | avwww在线 | www免费视频com━ | 日韩视频中文字幕 | 日韩丝袜在线观看 | 欧美日韩aaaa | 国产在线精品区 | 久草电影免费在线观看 | 韩日电影在线免费看 | 97人人模人人爽人人喊中文字 | 国产一区二区三区黄 | 久久久久久久久艹 | 日韩一二三区不卡 | 精品久久久一区二区 | 国产91电影在线观看 | 精品福利在线视频 | 在线成人高清电影 | av日韩中文 | 国产一二三四在线视频 | 在线视频精品播放 | 亚洲黄色免费观看 | 日韩欧美视频免费在线观看 | 中文字幕精品www乱入免费视频 | 三日本三级少妇三级99 | 夜夜夜夜爽 | 8x成人免费视频 | 在线免费高清一区二区三区 | 色噜噜在线观看 | 国产小视频免费在线网址 | 国产欧美在线一区 | 国产精品久久久免费 | 久久久午夜精品福利内容 | 国产精品毛片完整版 | 国产精品第一 | 黄色性av| 婷婷伊人五月 | 亚洲精品网站在线 | 成人欧美一区二区三区在线观看 | 国产区久久 | 麻豆极品 | 国产h在线播放 | 国产午夜精品一区二区三区在线观看 | 人人澡人人爽欧一区 | 日韩a级免费视频 | 欧美激情视频一二三区 | 婷婷午夜 | 国内精品久久久久久久久久久久 | 国产高清小视频 | 91视频首页| 免费能看的黄色片 | 手机在线黄色网址 | 久久久久久久久久久久99 | 狠狠色丁香婷婷综合久小说久 | 综合色婷婷 | 欧美激情奇米色 | 天无日天天操天天干 | 91网站在线视频 | 99夜色| 91av在线视频播放 | 国产精品va最新国产精品视频 | 日韩在线观看a | 99久久久国产免费 | 久久精品欧美 | 天天爽天天射 |