概要
アクターがカメラ表示されたかの判定についてのメモ書きです。
更新履歴
| 日付 | 内容 |
|---|---|
| 2026/05/31 | 初版 |
参考
以下を参考にさせて頂きました、ありがとうございます。
UE5/UE4 C++でワールド座標をスクリーン座標に変換する
【UE5】WasRecentlyRendered()の罠
RecentlyRenderedを使って可視判定を行う(UE5版)
【カメラ】TPSでプレイヤー視点とカメラ視点での当たり判定
環境
Windows11
Visual Studio 2022
UnrealEngine 5.7
実際に描画されたかで判定する
WasRecentlyRendered()
該当のメッシュコンポーネントが指定時間以内に実際に描画されたかどうかの判定が返ってくるメソッドです。引き数は最後にレンダリングされてからの経過時間で指定時間内であれば trueが返ってくるようです。
bool AMyActor::IsVisibleOnCamera() const
{
if (!GetMeshComponent()){ return(false); }
return(GetMeshComponent()->WasRecentlyRendered(0.1f));
}
このメソッドは影の描画やシーンキャプチャをされてもtrueが返ってくるため使用には注意が必要とのことです。
GetLastRenderTimeOnScreen()
こちらもメッシュコンポーネントのメソッドで実際にスクリーン上へ描画された最後の時間を取得することができるメソッドで、こちらは遮蔽物でカリングされた場合は時間が更新されないようです。
bool AMyActor::IsVisibleOnCamera() const
{
if (!GetMeshComponent()){ return(false); }
const float _Tolerance = 0.1f;
const float _LastRenderTime = GetMeshComponent()->GetLastRenderTimeOnScreen();
const float _CurrentTime = GetWorld()->GetTimeSeconds();
return((_CurrentTime - _LastRenderTime) <= _Tolerance);
}
スクリーン座標から判定する
アクターの座標からスクリーン座標を計算して判定する方法です。
以下サンプルコード。
bool AMyActor::IsInCamera(float _InCameraMarginRate) const
{
bool _bRet = true;
if (APlayerController* _PC = GetWorld()->GetFirstPlayerController()){
FVector2D _ScreenPos;
bool bProjected = _PC->ProjectWorldLocationToScreen(
GetActorLocation(),
_ScreenPos
);
if (!bProjected){
return(false);
}
int32 _SizeX, _SizeY;
_PC->GetViewportSize(_SizeX, _SizeY);
float _MarginX = GetCapsuleComponent()->GetScaledCapsuleRadius() * _InCameraMarginRate;
float _MarginY = GetCapsuleComponent()->GetScaledCapsuleHalfHeight() * _InCameraMarginRate;
if (_ScreenPos.Y < -_MarginY) _bRet = false;
else if (_ScreenPos.Y > _SizeY + _MarginY) _bRet = false;
else if (_ScreenPos.X < -_MarginX) _bRet = false;
else if (_ScreenPos.X > _SizeX + _MarginX) _bRet = false;
}
return(_bRet);
}
カプセルコンポーネントから大きさのマージンを取りつつスクリーン座標内かどうかを判定していますが、もっと大きい(or複雑な)アクターの場合これでは不十分かもしれません。
その場合は、GetActorBounds() でバウンディグボックスの各頂点を判定するなどといった工夫が必要です。
また遮蔽物の判定もこのままでは無理でカメラからのレイキャストをやったり等の対応が必要です。
まとめ
用途によって使い分ける必要があるようです。