UE4 ActionGame知识点总结N-杂项

1. 游戏开始的按3次键才能把门一点点打开,实现是Sequence或者Matinee完整地把门打开的全部过程Key好了,只不过增加了几个Event点,Event响应就是暂停Sequence或者Matinee的播放,然后按键后继续播放,再触发事件再次暂停播放。

2.通过Delay的办法解决动画瞬移的问题。角色播放了一个蒙太奇动画并且同时进行显示操作,如果两个操作之间不加入delay操作的话,那么由于角色出生位置与蒙太奇初始帧的位置不同,可以明显看到有位置瞬移的问题,如果操作之间加入Delay的话,执行的流程就是播放动画N秒后再开始显示,那么角色的位置就是当前动画的那个位置,可以解决瞬移问题。

UE4 ActionGame知识点总结N-杂项_第1张图片

3. FHitResult.Normal 碰撞点的法线方向,也可以理解成碰撞点相对于面的垂直方向,例如奔跑碰到了方块,那么Normal的方向就是碰撞点指向你的方向。FHitResult.ImpactPoint就是碰撞点的世界坐标。

4.slomo操作可以起到整个游戏加快或者减慢的效果,比如游戏中动作慢镜头效果。参数为1表示正常,小于1表示减慢,大于1表示加快。如果是想在sequence中进行设置的话,有个“播放速率轨迹”可以设置。如果想在蓝图中动态设置的话,可以下面这样:

UE4 ActionGame知识点总结N-杂项_第2张图片

如果在C++代码中设置的话,可以如下调用:

/**
	 * Sets the global time dilation.
	 * @param	TimeDilation	value to set the global time dilation to
	 */
	UFUNCTION(BlueprintCallable, Category="Utilities|Time", meta=(WorldContext="WorldContextObject") )
	static void SetGlobalTimeDilation(const UObject* WorldContextObject, float TimeDilation);

如果是调试阶段,可以命令行输入“slomo 0.1”即可。

5. 某些库函数声明中会出现meta=(WorldContext="WorldContextObject")和名字为WorldContext的参数,比如:

/** Returns the player controller at the specified player index */
	UFUNCTION(BlueprintPure, Category="Game", meta=(WorldContext="WorldContextObject", UnsafeDuringActorConstruction="true"))
	static class APlayerController* GetPlayerController(const UObject* WorldContextObject, int32 PlayerIndex);

在蓝图中调用该函数的时候并不用传入WorldCotextObject的参数,系统会自动帮你传入,这对于调用方和实现方都是很方便的。通过WorldCotextObject可以拿到World的指针,然后就可以处理你的逻辑了。

6. ActionGame过场动画播放之后可以看到镜头是从下往上升过去的,蓝图和c++源码中并没有明显的设置啊,这是如何执行的呢?通过调试发现,原因在APlayerCameraManager::UpdateViewTarget中找到了。

void APlayerCameraManager::UpdateViewTarget(FTViewTarget& OutVT, float DeltaTime)
{
	// Don't update outgoing viewtarget during an interpolation 
	if ((PendingViewTarget.Target != NULL) && BlendParams.bLockOutgoing && OutVT.Equal(ViewTarget))
	{
		return;
	}

	// store previous POV, in case we need it later
	FMinimalViewInfo OrigPOV = OutVT.POV;

	//@TODO: CAMERA: Should probably reset the view target POV fully here
	OutVT.POV.FOV = DefaultFOV;
	OutVT.POV.OrthoWidth = DefaultOrthoWidth;
	OutVT.POV.AspectRatio = DefaultAspectRatio;
	OutVT.POV.bConstrainAspectRatio = bDefaultConstrainAspectRatio;
	OutVT.POV.bUseFieldOfViewForLOD = true;
	OutVT.POV.ProjectionMode = bIsOrthographic ? ECameraProjectionMode::Orthographic : ECameraProjectionMode::Perspective;
	OutVT.POV.PostProcessSettings.SetBaseValues();
	OutVT.POV.PostProcessBlendWeight = 1.0f;


	bool bDoNotApplyModifiers = false;

	if (ACameraActor* CamActor = Cast(OutVT.Target))
	{
		// Viewing through a camera actor.
		CamActor->GetCameraComponent()->GetCameraView(DeltaTime, OutVT.POV);
	}
	else
	{

		static const FName NAME_Fixed = FName(TEXT("Fixed"));
		static const FName NAME_ThirdPerson = FName(TEXT("ThirdPerson"));
		static const FName NAME_FreeCam = FName(TEXT("FreeCam"));
		static const FName NAME_FreeCam_Default = FName(TEXT("FreeCam_Default"));
		static const FName NAME_FirstPerson = FName(TEXT("FirstPerson"));

		if (CameraStyle == NAME_Fixed)
		{
			// do not update, keep previous camera position by restoring
			// saved POV, in case CalcCamera changes it but still returns false
			OutVT.POV = OrigPOV;

			// don't apply modifiers when using this debug camera mode
			bDoNotApplyModifiers = true;
		}
		else if (CameraStyle == NAME_ThirdPerson || CameraStyle == NAME_FreeCam || CameraStyle == NAME_FreeCam_Default)
		{
			// Simple third person view implementation
			FVector Loc = OutVT.Target->GetActorLocation();
			FRotator Rotator = OutVT.Target->GetActorRotation();

			if (OutVT.Target == PCOwner)
			{
				Loc = PCOwner->GetFocalLocation();
			}

			// Take into account Mesh Translation so it takes into account the PostProcessing we do there.
			// @fixme, can crash in certain BP cases where default mesh is null
//			APawn* TPawn = Cast(OutVT.Target);
// 			if ((TPawn != NULL) && (TPawn->Mesh != NULL))
// 			{
// 				Loc += FQuatRotationMatrix(OutVT.Target->GetActorQuat()).TransformVector(TPawn->Mesh->RelativeLocation - GetDefault(TPawn->GetClass())->Mesh->RelativeLocation);
// 			}

			//OutVT.Target.GetActorEyesViewPoint(Loc, Rot);
			if( CameraStyle == NAME_FreeCam || CameraStyle == NAME_FreeCam_Default )
			{
				Rotator = PCOwner->GetControlRotation();
			}

			FVector Pos = Loc + ViewTargetOffset + FRotationMatrix(Rotator).TransformVector(FreeCamOffset) - Rotator.Vector() * FreeCamDistance;
			FCollisionQueryParams BoxParams(SCENE_QUERY_STAT(FreeCam), false, this);
			BoxParams.AddIgnoredActor(OutVT.Target);
			FHitResult Result;

			GetWorld()->SweepSingleByChannel(Result, Loc, Pos, FQuat::Identity, ECC_Camera, FCollisionShape::MakeBox(FVector(12.f)), BoxParams);
			OutVT.POV.Location = !Result.bBlockingHit ? Pos : Result.Location;
			OutVT.POV.Rotation = Rotator;

			// don't apply modifiers when using this debug camera mode
			bDoNotApplyModifiers = true;
		}
		else if (CameraStyle == NAME_FirstPerson)
		{
			// Simple first person, view through viewtarget's 'eyes'
			OutVT.Target->GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
	
			// don't apply modifiers when using this debug camera mode
			bDoNotApplyModifiers = true;
		}
		else
		{
			UpdateViewTargetInternal(OutVT, DeltaTime);
		}
	}

	if (!bDoNotApplyModifiers || bAlwaysApplyModifiers)
	{
		// Apply camera modifiers at the end (view shakes for example)
		ApplyCameraModifiers(DeltaTime, OutVT.POV);
	}

	// Synchronize the actor with the view target results
	SetActorLocationAndRotation(OutVT.POV.Location, OutVT.POV.Rotation, false);

	UpdateCameraLensEffects(OutVT);
}
可以看到,如果当前的OutVT.Target是CameraActor的话,执行的是CameraActor组件的GetCameraView函数而不是APlatformerPlayerCameraManager::UpdateViewTargetInternal,因为过场动画使用的镜头就是CameraActor,所以刚开始播放过场动画的时候,APlatformerPlayerCameraManager::UpdateViewTargetInternal并没有执行。当过场动画播放完毕,镜头需要回归到人物时,APlatformerPlayerCameraManager::UpdateViewTargetInternal开始执行,APlatformerPlayerCameraManager::CalcCameraOffsetZ则描述了Z插值的相关东西。

你可能感兴趣的:(UE4)