【UE4】LineTrace 功能详解

  UE4.25 中有各种Trace,最常用的就是 LIneTrace,即发射线看打到谁。

一、World.h 中的 Trace

  在引擎 World.h 中,

  • Trace 类型有两种:LineTrace、SweepTrace(射线方式、扫掠方式);
  • Trace 数量有两种: TraceSingle、TraceMulti(也就是射到一个就停止,还是可以射穿多个);
  • Trace 方式有三种:ByChannelByObjectTypeByProfile通过不同方式选择哪些东西可以Trace)。

  下边这个函数就是 “射线方式、射一个停止、通过 Channel查找射到谁” 的一个 LineTrace 方法。

/**
	 *  Trace a ray against the world using a specific channel and return the first blocking hit
	 *  @param  OutHit          First blocking hit found
	 *  @param  Start           Start location of the ray
	 *  @param  End             End location of the ray
	 *  @param  TraceChannel    The 'channel' that this ray is in, used to determine which components to hit
	 *  @param  Params          Additional parameters used for the trace
	 * 	@param 	ResponseParam	ResponseContainer to be used for this trace	 
	 *  @return TRUE if a blocking hit is found
	 */
	bool LineTraceSingleByChannel(struct FHitResult& OutHit,const FVector& Start,const FVector& End,ECollisionChannel TraceChannel,const FCollisionQueryParams& Params = FCollisionQueryParams::DefaultQueryParam, const FCollisionResponseParams& ResponseParam = FCollisionResponseParams::DefaultResponseParam) const;

  重点分析上边第三条:Trace 的方式。

1. ByChannel

  这个名称比较迷惑,通过 Channel 来控制那些东西可以 Trace,比如想只 Trace WorldStatic 的 Object,但其实 TraceChannel 参数不是 “只与 WorldStatic 交互” 的意思,而是 The 'channel' that this ray is in(源码注释),也就是这根射线的 Collision Type 是 WorldStatic,所有与 WorldStatic 类型有Block的,都会挡住射线,就会出现想发出一根只与 WorldStatic Object 交互的射线,但是却被怪物挡住的情况!
  上边这种需求应该用下边这种 ByObjectType 的 LineTrace 方法。

2. ByObjectType

  如果想发出射线,与碰到场景(一般地面、不动的物体等场景物体都是 WorldStatic)就停止,可以用

FHitResult HitResult;
GetWorld()->LineTraceSingleByObjectType(HitResult, Location, FVector(Location.X, Location.Y, 0), ECC_WorldStatic);

  这样的射线,只在碰到 WorldStatic Object 时停止,会穿过怪物、人物等 Dynamic物体。上边这个函数就可以从 Location 位置向世界坐标系的 Z 轴负方向(一般就是朝下)发射线,遇到地面等静态物体停止,再通过 Location.Z - HitResult.Location.Z 就可以算出 Location 位置距离地面的高度了。

3. ByProfile

  看参数和注释应该是通过 FName ProfileName 确定射线会射到的物体,还没用过,用到再说~

二、UKismetSystemLibrary 中的 Trace

  UKismetSystemLibrary 中的 Trace 有 LineTrace、BoxTrace、SphereTrace、CapsuleTrace 四种类型,每种又分为 xxxTraceSingle、xxxTraceMulti 两种(同上)。
  举例说明:

bool UKismetSystemLibrary::LineTraceSingle(UObject* WorldContextObject, const FVector Start, const FVector End, ETraceTypeQuery TraceChannel, bool bTraceComplex, const TArray<AActor*>& ActorsToIgnore, EDrawDebugTrace::Type DrawDebugType, FHitResult& OutHit, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime)
{
	ECollisionChannel CollisionChannel = UEngineTypes::ConvertToCollisionChannel(TraceChannel);

	static const FName LineTraceSingleName(TEXT("LineTraceSingle"));
	FCollisionQueryParams Params = ConfigureCollisionParams(LineTraceSingleName, bTraceComplex, ActorsToIgnore, bIgnoreSelf, WorldContextObject);

	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
	bool const bHit = World ? World->LineTraceSingleByChannel(OutHit, Start, End, CollisionChannel, Params) : false;

#if ENABLE_DRAW_DEBUG
	DrawDebugLineTraceSingle(World, Start, End, DrawDebugType, bHit, OutHit, TraceColor, TraceHitColor, DrawTime);
#endif

	return bHit;
}

  可以看到,其实最后还是调的 World->LineTraceSingleByChannel,UKismetSystemLibrary 里的 Trace 都是调用的 World 里的 Trace。从代码上看,调用对应关系如下(Single 和 Multi 对应关系显然):

UKismetSystemLibraryWorld
LineTraceSingle / LineTraceMultiLineTraceSingleByChannel / LineTraceMultiByChannel
BoxTraceSingleSweepSingleByChannel
SphereTraceSingleSweepSingleByChannel
CapsuleTraceSingleSweepSingleByChannel

  也就是 UKismetSystemLibrary 里默认是 ByChannel,也有对应其他方式的,比如 UKismetSystemLibrary::LineTraceSingleForObjects 对应 World->LineTraceSingleByObjectType,其他同理。
  即 Line 对应 Line,其他对应 Sweep。
  UKismetSystemLibrary 的好处就是可以直接画出 Trace的起点、终点以及 Trace 的线:

  e.g.

if (UKismetSystemLibrary::LineTraceSingleForObjects(
	GetWorld(),
	Location,								/** Start			*/
	FVector(Location.X, Location.Y, 0),		/** End				*/
	TArray<TEnumAsByte<EObjectTypeQuery>>{ UEngineTypes::ConvertToObjectType(ECC_WorldStatic) },
	false,									/** bTraceComplex	*/
	{},										/** ActorsToIgnore	*/
	EDrawDebugTrace::Persistent,			/** DrawDebugType	*/
	OUT HitResult,							/** OutHit			*/
	true))									/** bIgnoreSelf		*/
{
	if (HitResult.bBlockingHit)
	{
		TargetLocation = HitResult.Location;
	}
}
  • 14
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UE4的回放功能一般通过使用ReplaySubsystem实现。下面是一些基本步骤来实现回放功能: 1. 启用ReplaySubsystem 在UE4项目的配置文件(.ini)中启用ReplaySubsystem。在[Engine.GameEngine]部分添加以下行: ``` +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver") +NetConnectionClassName="/Script/OnlineSubsystemUtils.IpNetConnection" +DefaultPlatformServiceClassName="/Script/OnlineSubsystemUtils/NullReplayPlatformService" ``` 2. 记录回放数据 在游戏中记录回放数据,可以在服务器或客户端上执行。使用以下命令开始记录: ``` DemoNetDriver->StartDemoRecording(Filename, bOverwrite); ``` 其中Filename是回放文件的名称,bOverwrite指定是否覆盖现有的文件。 3. 停止记录 在游戏中停止记录回放数据,使用以下命令: ``` DemoNetDriver->StopDemoRecording(); ``` 4. 回放数据 在游戏中回放数据,使用以下命令开始回放: ``` DemoNetDriver->StartDemoPlayback(Filename); ``` 其中Filename是要回放的文件名称。 5. 停止回放 在游戏中停止回放数据,使用以下命令: ``` DemoNetDriver->StopDemoPlayback(); ``` 这些是实现UE4中回放功能的基本步骤,当然在具体实现中还需要根据项目的需求进行具体的调整。同时,您也可以查阅UE4官方文档或者相关的论坛和社区,了解更多关于UE4回放功能的内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值