栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

UE4SuggestProjectileVelocity

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

UE4SuggestProjectileVelocity

UE4SuggestProjectileVelocity_CustomArc

UE4中SuggestProjectileVelocity_CustomArc节点可以通过传入两个位置A,B,然后计算出从A到B的斜抛运动的初始速度。
结点的截图如下:


看看结点的中文解释:

由于对其中的原理感到很感兴趣因此就去找了C++的结点源码,然后了解了一下原理,本文是对该节点的一个源码解读,仅代表个人观点,若大佬有别的想法望指正。

首先看看C++代码:

bool UGameplayStatics::SuggestProjectileVelocity_CustomArc(const UObject* WorldContextObject, FVector& OutLaunchVelocity, FVector StartPos, FVector EndPos, float OverrideGravityZ , float ArcParam )
{
	
	FVector const StartToEnd = EndPos - StartPos;
	float const StartToEndDist = StartToEnd.Size();

	UWorld const* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull);
	if (World && StartToEndDist > KINDA_SMALL_NUMBER)
	{
		const float GravityZ = FMath::IsNearlyEqual(OverrideGravityZ, 0.0f) ? World->GetGravityZ() : OverrideGravityZ;

		// choose arc according to the arc param
		FVector const StartToEndDir = StartToEnd / StartToEndDist;
		FVector LaunchDir = FMath::Lerp(FVector::UpVector, StartToEndDir, ArcParam).GetSafeNormal();

		// v = sqrt ( g * dx^2 / ( (dx tan(angle) + dz) * 2 * cos(angle))^2 ) )

		FRotator const LaunchRot = LaunchDir.Rotation();
		float const Angle = FMath::DegreesToRadians(LaunchRot.Pitch);

		float const Dx = StartToEnd.Size2D();
		float const Dz = StartToEnd.Z;
		float const NumeratorInsideSqrt = (GravityZ * FMath::Square(Dx) * 0.5f);
		float const DenominatorInsideSqrt = (Dz - (Dx * FMath::Tan(Angle))) * FMath::Square(FMath::Cos(Angle));
		float const InsideSqrt = NumeratorInsideSqrt / DenominatorInsideSqrt;
		if (InsideSqrt >= 0.f)
		{
			// there exists a solution
			float const Speed = FMath::Sqrt(InsideSqrt);	// this is the mag of the vertical component
			OutLaunchVelocity = LaunchDir * Speed;
			return true;
		}
	}

	OutLaunchVelocity = FVector::ZeroVector;
	return false;
}

要了解这部分的代码,首先要了解斜抛运动,因为该运动其实主要运用的是中学的物理,因此不过多赘述可以参考文章:https://www.zhihu.com/topic/20683808/intro

大家可以自己简单推导一下,而UE的C++主要应用的是最下面的公式

接下来就来具体看看代码部分:

代码的第一部分,主要是通过传入的参数两个位置相减得到一个方向向量,然后那向量的长度就可以得到两个点的距离,然后方向向量除距离得到方向向量的单位向量StartToEndDir,然后将其与Actor的向上向量做一个插值,插值由Arc决定,注意,因为因为这个Arc默认值是0.5,所以如果你传入的两个点的位置为同一平面的,得出的速度值也是会让Actor向上抛一定高度的。插值后得到的向量就定为最终发射速度的方向向量LaunchDir。然后用这个向量的rotation的pitch值得到这个方向向量相对于水平面的夹角。因为pitch代表的是绕x轴的旋转,所以可以表示一个角度。
得到了方向,还要计算出这个速度的大小,这个就是利用斜抛运动的上文提到的y的公式:

可能这么看比较不直观,简单来讲,C++代码里面求的就是公式里面的V0,首先我们试着通过这个公式转换出关于V的公式。:

然后1+tanθ的平方其实就是1/cosθ平方,所以也可以化简为:

此时就可以与代码中间部分一一对应了(注,图中的V0应该带有平方,截图的时候发现有遗漏):

Dz代表的是斜抛运动的高度,Dx代表的是这个方向向量的水平投影,因为这个公式的推到其实是在二维的,就利用向量的水平投影代表斜抛运动的水平位移。
NumeratorInsideSqrt代表的就是公式中分子的部分,(Squara(Dx)表示求Dx的平方)
DenominatorInsideSqrt表示的是公式中的分母部分,然后相除便可以得到V0的平方。
也就是速度的大小。

最后一部分就是通过判断最终的速度大小如果大于0,则将其乘方向向量,就可以得到最终的初始速度。
以上便是本人对该节点的解读,如果有错误的地方还望大佬指正。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038070.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号